Compare commits
163 Commits
tmp-gltext
...
temp-vr-dr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1fcc5adc60 | ||
|
|
5350015d51 | ||
|
|
3483aa57b3 | ||
|
|
44a220f721 | ||
|
|
fa7643bc7b | ||
|
|
02aca1bfb7 | ||
|
|
43d4ac5db6 | ||
|
|
834b0b8262 | ||
|
|
d20393c8bd | ||
|
|
6a46860220 | ||
|
|
34506a1276 | ||
|
|
5274c5cce6 | ||
|
|
eee5ba5cc3 | ||
|
|
f5c023dfd7 | ||
|
|
06e0ea0c16 | ||
|
|
41ed61b273 | ||
|
|
88b79cacb2 | ||
|
|
0d70afed19 | ||
|
|
c7653fad67 | ||
|
|
7a711e133c | ||
|
|
7922bd26a2 | ||
|
|
9b6ce439bb | ||
|
|
11975d5d95 | ||
|
|
03b09dbe32 | ||
|
|
f04a5ad1e4 | ||
|
|
ab1455e972 | ||
|
|
b94af38c31 | ||
|
|
40db778de3 | ||
|
|
22966f4d35 | ||
|
|
e8f66ff060 | ||
|
|
8d3f4a1df3 | ||
|
|
9ac33e56a1 | ||
|
|
b961b3f0c9 | ||
|
|
091cc94379 | ||
|
|
fc31be5ab0 | ||
|
|
aff49f607a | ||
|
|
57b77cd193 | ||
|
|
d58eb8d29d | ||
|
|
a4310ba85f | ||
|
|
bd42740ef1 | ||
|
|
679a4c34fc | ||
|
|
55362436d9 | ||
|
|
c1d164070b | ||
|
|
3a4034a741 | ||
|
|
a0be113d2e | ||
|
|
151fb129e7 | ||
|
|
165c5a5259 | ||
|
|
74fc1db25b | ||
|
|
03ff2a8dd5 | ||
| d99d15f48d | |||
|
|
6a998833cd | ||
|
|
fca4826c7f | ||
|
|
b0845fc133 | ||
|
|
70cf8bd9c6 | ||
|
|
3a2e459f58 | ||
|
|
330f062099 | ||
|
|
09872df1c7 | ||
|
|
67d6399da6 | ||
|
|
c29724912b | ||
|
|
99560d9657 | ||
|
|
b8a7b87873 | ||
|
|
c9f6c1a054 | ||
|
|
dd0fcb50b4 | ||
|
|
c1e9cf00ac | ||
|
|
84d609f67b | ||
|
|
86178548d5 | ||
|
|
d711540a85 | ||
|
|
6e3158cb00 | ||
|
|
b216690505 | ||
|
|
b98896ddd9 | ||
|
|
a05104d61f | ||
|
|
7fe1cc8d24 | ||
|
|
70e84a2c20 | ||
|
|
084a33ca94 | ||
|
|
37f619aea3 | ||
|
|
6904ab10f4 | ||
|
|
146ef0dd1e | ||
|
|
5891e86420 | ||
|
|
2cedad990a | ||
|
|
109be29e42 | ||
|
|
13442da69f | ||
|
|
231dbd53bf | ||
|
|
d3e48fb096 | ||
|
|
d544a0b41c | ||
|
|
cf4799e299 | ||
|
|
57d9f004aa | ||
|
|
62cde7a9ef | ||
|
|
e4fcf25fc5 | ||
|
|
215c919b33 | ||
|
|
da44a02d00 | ||
|
|
867007d9d7 | ||
|
|
e9ea814233 | ||
|
|
6b43c82cb5 | ||
|
|
afbb62fecd | ||
|
|
8a676e8fa9 | ||
|
|
c52111e983 | ||
|
|
d749e8a2c4 | ||
|
|
8663aa80e6 | ||
|
|
88b39444a0 | ||
|
|
4cfc3caa09 | ||
|
|
28428b3462 | ||
|
|
24146563a0 | ||
|
|
2ee9c60c20 | ||
|
|
fb64675209 | ||
|
|
76385139cf | ||
|
|
b18f5a6a81 | ||
|
|
9d29373b06 | ||
|
|
f2f1e4dfed | ||
|
|
0da0f29ade | ||
|
|
a8519dbac2 | ||
|
|
d15d07c4f6 | ||
|
|
d356787a65 | ||
|
|
a284fa3abb | ||
|
|
4eeb7523e9 | ||
|
|
f30fcd6c85 | ||
|
|
47e8133520 | ||
|
|
3fa7d59a04 | ||
|
|
df8dc43946 | ||
|
|
3b0a2fecfc | ||
|
|
80af6d534d | ||
|
|
71c7d61808 | ||
|
|
637b803b97 | ||
|
|
314eef0df8 | ||
|
|
34fa0f8ac6 | ||
|
|
16366724bd | ||
|
|
fc8127d070 | ||
|
|
3ac37fb552 | ||
|
|
8e51a75772 | ||
|
|
ba2dab402d | ||
|
|
796994d222 | ||
|
|
66e90e9179 | ||
|
|
1404edbe3a | ||
|
|
2f68a76409 | ||
|
|
304d9a20fc | ||
|
|
b169e327bf | ||
|
|
7238bbecc4 | ||
|
|
a49b4ca402 | ||
|
|
eb0424c946 | ||
|
|
5d6da57aa3 | ||
|
|
e968bbc5d8 | ||
|
|
b1b0e05c54 | ||
|
|
e547026dfe | ||
|
|
f816380af5 | ||
|
|
5e642bfea1 | ||
|
|
0d1a22f74f | ||
|
|
20a1af936d | ||
|
|
c9c1b90532 | ||
|
|
4192281e14 | ||
|
|
329deadc9e | ||
|
|
53845c554d | ||
|
|
35c9e3beed | ||
|
|
60f66768cf | ||
|
|
3e88974a80 | ||
|
|
09e7d6cd26 | ||
|
|
5d5ad5d6dd | ||
|
|
e70894c360 | ||
|
|
4c11886c4e | ||
|
|
41e2f2e75f | ||
|
|
864abbd425 | ||
|
|
f333e7eb56 | ||
|
|
a2ac2ec3c3 | ||
|
|
06d52afcda | ||
|
|
e65ba62c37 |
@@ -234,6 +234,17 @@ option(WITH_BULLET "Enable Bullet (Physics Engine)" ON)
|
|||||||
option(WITH_SYSTEM_BULLET "Use the systems bullet library (currently unsupported due to missing features in upstream!)" )
|
option(WITH_SYSTEM_BULLET "Use the systems bullet library (currently unsupported due to missing features in upstream!)" )
|
||||||
mark_as_advanced(WITH_SYSTEM_BULLET)
|
mark_as_advanced(WITH_SYSTEM_BULLET)
|
||||||
option(WITH_OPENCOLORIO "Enable OpenColorIO color management" ${_init_OPENCOLORIO})
|
option(WITH_OPENCOLORIO "Enable OpenColorIO color management" ${_init_OPENCOLORIO})
|
||||||
|
option(WITH_OPENXR "Enable VR features through the OpenXR specification" ON)
|
||||||
|
if(WITH_OPENXR)
|
||||||
|
option(OPENXR_USE_BUNDLED_SRC "Compile using the bundled OpenXR SDK sources (otherwise it has to be compiled manually)" ON)
|
||||||
|
if(NOT OPENXR_USE_BUNDLED_SRC)
|
||||||
|
find_package(OpenXR-SDK)
|
||||||
|
if(NOT OPENXR_SDK_FOUND)
|
||||||
|
message(WARNING "OpenXR-SDK was not found, disabling WITH_OPENXR")
|
||||||
|
set(WITH_OPENXR OFF)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
# Compositor
|
# Compositor
|
||||||
option(WITH_COMPOSITOR "Enable the tile based nodal compositor" ON)
|
option(WITH_COMPOSITOR "Enable the tile based nodal compositor" ON)
|
||||||
@@ -1760,6 +1771,7 @@ if(FIRST_RUN)
|
|||||||
info_cfg_option(WITH_CYCLES)
|
info_cfg_option(WITH_CYCLES)
|
||||||
info_cfg_option(WITH_FREESTYLE)
|
info_cfg_option(WITH_FREESTYLE)
|
||||||
info_cfg_option(WITH_OPENCOLORIO)
|
info_cfg_option(WITH_OPENCOLORIO)
|
||||||
|
info_cfg_option(WITH_OPENXR)
|
||||||
info_cfg_option(WITH_OPENVDB)
|
info_cfg_option(WITH_OPENVDB)
|
||||||
info_cfg_option(WITH_ALEMBIC)
|
info_cfg_option(WITH_ALEMBIC)
|
||||||
|
|
||||||
|
|||||||
67
build_files/cmake/Modules/FindOpenXR-SDK.cmake
Normal file
67
build_files/cmake/Modules/FindOpenXR-SDK.cmake
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# - Find OpenXR-SDK library
|
||||||
|
# Find the native OpenXR-SDK includes and library
|
||||||
|
# This module defines
|
||||||
|
# OPENXR_SDK_INCLUDE_DIRS, where to find OpenXR-SDK headers, Set when
|
||||||
|
# OPENXR_SDK_INCLUDE_DIR is found.
|
||||||
|
# OPENXR_SDK_LIBRARIES, libraries to link against to use OpenXR-SDK.
|
||||||
|
# OPENXR_SDK_ROOT_DIR, the base directory to search for OpenXR-SDK.
|
||||||
|
# This can also be an environment variable.
|
||||||
|
# OPENXR_SDK_FOUND, if false, do not try to use OpenXR-SDK.
|
||||||
|
#
|
||||||
|
# also defined, but not for general use are
|
||||||
|
# OPENXR_LOADER_LIBRARY, where to find the OpenXR-SDK library.
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# Distributed under the OSI-approved BSD License (the "License");
|
||||||
|
# see accompanying file Copyright.txt for details.
|
||||||
|
#
|
||||||
|
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||||
|
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
# See the License for more information.
|
||||||
|
#=============================================================================
|
||||||
|
|
||||||
|
# If OPENXR_SDK_ROOT_DIR was defined in the environment, use it.
|
||||||
|
IF(NOT OPENXR_SDK_ROOT_DIR AND NOT $ENV{OPENXR_SDK_ROOT_DIR} STREQUAL "")
|
||||||
|
SET(OPENXR_SDK_ROOT_DIR $ENV{OPENXR_SDK_ROOT_DIR})
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
SET(_openxr_sdk_SEARCH_DIRS
|
||||||
|
${OPENXR_SDK_ROOT_DIR}
|
||||||
|
/usr/local
|
||||||
|
/sw # Fink
|
||||||
|
/opt/local # DarwinPorts
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_PATH(OPENXR_SDK_INCLUDE_DIR
|
||||||
|
NAMES
|
||||||
|
openxr/openxr.h
|
||||||
|
HINTS
|
||||||
|
${_openxr_sdk_SEARCH_DIRS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
include
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY(OPENXR_LOADER_LIBRARY
|
||||||
|
NAMES
|
||||||
|
openxr_loader
|
||||||
|
HINTS
|
||||||
|
${_openxr_sdk_SEARCH_DIRS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
lib64 lib
|
||||||
|
)
|
||||||
|
|
||||||
|
# handle the QUIETLY and REQUIRED arguments and set OPENXR_SDK_FOUND to TRUE if
|
||||||
|
# all listed variables are TRUE
|
||||||
|
INCLUDE(FindPackageHandleStandardArgs)
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OPENXR_SDK DEFAULT_MSG
|
||||||
|
OPENXR_LOADER_LIBRARY OPENXR_SDK_INCLUDE_DIR)
|
||||||
|
|
||||||
|
IF(OPENXR_SDK_FOUND)
|
||||||
|
SET(OPENXR_SDK_LIBRARIES ${OPENXR_LOADER_LIBRARY})
|
||||||
|
SET(OPENXR_SDK_INCLUDE_DIRS ${OPENXR_SDK_INCLUDE_DIR})
|
||||||
|
ENDIF(OPENXR_SDK_FOUND)
|
||||||
|
|
||||||
|
MARK_AS_ADVANCED(
|
||||||
|
OPENXR_SDK_INCLUDE_DIR
|
||||||
|
OPENXR_LOADER_LIBRARY
|
||||||
|
)
|
||||||
101
build_files/cmake/Modules/presentation.cmake
Normal file
101
build_files/cmake/Modules/presentation.cmake
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
set(PRESENTATION_BACKENDS xlib xcb wayland)
|
||||||
|
set(PRESENTATION_BACKEND xlib CACHE STRING
|
||||||
|
"Presentation backend chosen at configure time")
|
||||||
|
set_property(CACHE PRESENTATION_BACKEND PROPERTY STRINGS
|
||||||
|
${PRESENTATION_BACKENDS})
|
||||||
|
|
||||||
|
list(FIND PRESENTATION_BACKENDS ${PRESENTATION_BACKEND} index)
|
||||||
|
if(index EQUAL -1)
|
||||||
|
message(FATAL_ERROR "Presentation backend must be one of
|
||||||
|
${PRESENTATION_BACKENDS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Using presentation backend: ${PRESENTATION_BACKEND}")
|
||||||
|
|
||||||
|
|
||||||
|
if( PRESENTATION_BACKEND MATCHES "xlib" )
|
||||||
|
find_package(X11 REQUIRED)
|
||||||
|
if ((NOT X11_Xxf86vm_LIB) OR (NOT X11_Xrandr_LIB))
|
||||||
|
message(FATAL_ERROR "OpenXR xlib backend requires Xxf86vm and Xrandr")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_definitions( -DSUPPORT_X )
|
||||||
|
add_definitions( -DOS_LINUX_XLIB )
|
||||||
|
set( XLIB_LIBRARIES
|
||||||
|
${X11_LIBRARIES}
|
||||||
|
${X11_Xxf86vm_LIB}
|
||||||
|
${X11_Xrandr_LIB} )
|
||||||
|
|
||||||
|
elseif( PRESENTATION_BACKEND MATCHES "xcb" )
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
# XCB + XCB GLX is limited to OpenGL 2.1
|
||||||
|
# add_definitions( -DOS_LINUX_XCB )
|
||||||
|
# XCB + Xlib GLX 1.3
|
||||||
|
add_definitions( -DOS_LINUX_XCB_GLX )
|
||||||
|
|
||||||
|
pkg_search_module(X11 REQUIRED x11)
|
||||||
|
pkg_search_module(XCB REQUIRED xcb)
|
||||||
|
pkg_search_module(XCB_RANDR REQUIRED xcb-randr)
|
||||||
|
pkg_search_module(XCB_KEYSYMS REQUIRED xcb-keysyms)
|
||||||
|
pkg_search_module(XCB_GLX REQUIRED xcb-glx)
|
||||||
|
pkg_search_module(XCB_DRI2 REQUIRED xcb-dri2)
|
||||||
|
pkg_search_module(XCB_ICCCM REQUIRED xcb-icccm)
|
||||||
|
|
||||||
|
set( XCB_LIBRARIES
|
||||||
|
${XCB_LIBRARIES}
|
||||||
|
${XCB_KEYSYMS_LIBRARIES}
|
||||||
|
${XCB_RANDR_LIBRARIES}
|
||||||
|
${XCB_GLX_LIBRARIES}
|
||||||
|
${XCB_DRI2_LIBRARIES}
|
||||||
|
${X11_LIBRARIES} )
|
||||||
|
|
||||||
|
elseif( PRESENTATION_BACKEND MATCHES "wayland" )
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_search_module(WAYLAND_CLIENT REQUIRED wayland-client)
|
||||||
|
pkg_search_module(WAYLAND_EGL REQUIRED wayland-egl)
|
||||||
|
pkg_search_module(WAYLAND_SCANNER REQUIRED wayland-scanner)
|
||||||
|
pkg_search_module(WAYLAND_PROTOCOLS REQUIRED wayland-protocols>=1.7)
|
||||||
|
pkg_search_module(EGL REQUIRED egl)
|
||||||
|
|
||||||
|
add_definitions( -DOS_LINUX_WAYLAND )
|
||||||
|
set( WAYLAND_LIBRARIES
|
||||||
|
${EGL_LIBRARIES}
|
||||||
|
${WAYLAND_CLIENT_LIBRARIES}
|
||||||
|
${WAYLAND_EGL_LIBRARIES} )
|
||||||
|
|
||||||
|
# generate wayland protocols
|
||||||
|
set(WAYLAND_PROTOCOLS_DIR ${CMAKE_SOURCE_DIR}/wayland-protocols/)
|
||||||
|
file(MAKE_DIRECTORY ${WAYLAND_PROTOCOLS_DIR})
|
||||||
|
|
||||||
|
pkg_get_variable(WAYLAND_PROTOCOLS_DATADIR wayland-protocols pkgdatadir)
|
||||||
|
pkg_get_variable(WAYLAND_SCANNER wayland-scanner wayland_scanner)
|
||||||
|
|
||||||
|
set(PROTOCOL xdg-shell-unstable-v6)
|
||||||
|
set(PROTOCOL_XML
|
||||||
|
${WAYLAND_PROTOCOLS_DATADIR}/unstable/xdg-shell/${PROTOCOL}.xml)
|
||||||
|
|
||||||
|
if( EXISTS ${PROTOCOL_XML} )
|
||||||
|
execute_process(COMMAND
|
||||||
|
${WAYLAND_SCANNER}
|
||||||
|
code
|
||||||
|
${PROTOCOL_XML}
|
||||||
|
${WAYLAND_PROTOCOLS_DIR}/${PROTOCOL}.c)
|
||||||
|
execute_process(COMMAND
|
||||||
|
${WAYLAND_SCANNER}
|
||||||
|
client-header
|
||||||
|
${PROTOCOL_XML}
|
||||||
|
${WAYLAND_PROTOCOLS_DIR}/${PROTOCOL}.h)
|
||||||
|
|
||||||
|
set( WAYLAND_PROTOCOL_SRC
|
||||||
|
${WAYLAND_PROTOCOLS_DIR}/${PROTOCOL}.c
|
||||||
|
${WAYLAND_PROTOCOLS_DIR}/${PROTOCOL}.h )
|
||||||
|
|
||||||
|
include_directories(${WAYLAND_PROTOCOLS_DIR})
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"xdg-shell-unstable-v6.xml not found in "
|
||||||
|
${WAYLAND_PROTOCOLS_DATADIR}
|
||||||
|
"\nYour wayland-protocols package does not "
|
||||||
|
"contain xdg-shell-unstable-v6.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
47
build_files/cmake/Modules/xr_platform_defines.cmake
Normal file
47
build_files/cmake/Modules/xr_platform_defines.cmake
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# Copyright (c) 2017 The Khronos Group Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
add_definitions(-DXR_OS_WINDOWS)
|
||||||
|
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
add_definitions(-DXR_OS_LINUX)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Determine the presentation backend for Linux systems.
|
||||||
|
# Use an include because the code is pretty big.
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
include(presentation)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Several files use these compile-time platform switches
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
add_definitions( -DXR_USE_PLATFORM_WIN32 )
|
||||||
|
elseif( PRESENTATION_BACKEND MATCHES "xlib" )
|
||||||
|
add_definitions( -DXR_USE_PLATFORM_XLIB )
|
||||||
|
elseif( PRESENTATION_BACKEND MATCHES "xcb" )
|
||||||
|
add_definitions( -DXR_USE_PLATFORM_XCB )
|
||||||
|
elseif( PRESENTATION_BACKEND MATCHES "wayland" )
|
||||||
|
add_definitions( -DXR_USE_PLATFORM_WAYLAND )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_definitions(-DXR_USE_GRAPHICS_API_OPENGL)
|
||||||
|
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
add_definitions(-DXR_USE_GRAPHICS_API_D3D)
|
||||||
|
add_definitions(-DXR_USE_GRAPHICS_API_D3D10)
|
||||||
|
add_definitions(-DXR_USE_GRAPHICS_API_D3D11)
|
||||||
|
add_definitions(-DXR_USE_GRAPHICS_API_D3D12)
|
||||||
|
endif()
|
||||||
|
|
||||||
@@ -40,6 +40,7 @@ set(WITH_AUDASPACE ON CACHE BOOL "" FORCE)
|
|||||||
set(WITH_OPENAL ON CACHE BOOL "" FORCE)
|
set(WITH_OPENAL ON CACHE BOOL "" FORCE)
|
||||||
set(WITH_OPENCOLLADA ON CACHE BOOL "" FORCE)
|
set(WITH_OPENCOLLADA ON CACHE BOOL "" FORCE)
|
||||||
set(WITH_OPENCOLORIO ON CACHE BOOL "" FORCE)
|
set(WITH_OPENCOLORIO ON CACHE BOOL "" FORCE)
|
||||||
|
set(WITH_OPENXR ON CACHE BOOL "" FORCE)
|
||||||
set(WITH_OPENMP ON CACHE BOOL "" FORCE)
|
set(WITH_OPENMP ON CACHE BOOL "" FORCE)
|
||||||
set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
|
set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
|
||||||
set(WITH_OPENVDB ON CACHE BOOL "" FORCE)
|
set(WITH_OPENVDB ON CACHE BOOL "" FORCE)
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ set(WITH_AUDASPACE OFF CACHE BOOL "" FORCE)
|
|||||||
set(WITH_OPENAL OFF CACHE BOOL "" FORCE)
|
set(WITH_OPENAL OFF CACHE BOOL "" FORCE)
|
||||||
set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)
|
set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)
|
||||||
set(WITH_OPENCOLORIO OFF CACHE BOOL "" FORCE)
|
set(WITH_OPENCOLORIO OFF CACHE BOOL "" FORCE)
|
||||||
|
set(WITH_OPENXR OFF CACHE BOOL "" FORCE)
|
||||||
set(WITH_OPENIMAGEIO OFF CACHE BOOL "" FORCE)
|
set(WITH_OPENIMAGEIO OFF CACHE BOOL "" FORCE)
|
||||||
set(WITH_OPENMP OFF CACHE BOOL "" FORCE)
|
set(WITH_OPENMP OFF CACHE BOOL "" FORCE)
|
||||||
set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)
|
set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ set(WITH_AUDASPACE ON CACHE BOOL "" FORCE)
|
|||||||
set(WITH_OPENAL ON CACHE BOOL "" FORCE)
|
set(WITH_OPENAL ON CACHE BOOL "" FORCE)
|
||||||
set(WITH_OPENCOLLADA ON CACHE BOOL "" FORCE)
|
set(WITH_OPENCOLLADA ON CACHE BOOL "" FORCE)
|
||||||
set(WITH_OPENCOLORIO ON CACHE BOOL "" FORCE)
|
set(WITH_OPENCOLORIO ON CACHE BOOL "" FORCE)
|
||||||
|
set(WITH_OPENXR ON CACHE BOOL "" FORCE)
|
||||||
set(WITH_OPENMP ON CACHE BOOL "" FORCE)
|
set(WITH_OPENMP ON CACHE BOOL "" FORCE)
|
||||||
set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
|
set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
|
||||||
set(WITH_OPENVDB ON CACHE BOOL "" FORCE)
|
set(WITH_OPENVDB ON CACHE BOOL "" FORCE)
|
||||||
|
|||||||
@@ -468,6 +468,9 @@ function(setup_liblinks
|
|||||||
if(WITH_OPENSUBDIV)
|
if(WITH_OPENSUBDIV)
|
||||||
target_link_libraries(${target} ${OPENSUBDIV_LIBRARIES})
|
target_link_libraries(${target} ${OPENSUBDIV_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
if(WITH_OPENXR)
|
||||||
|
target_link_libraries(${target} ${OPENXR_SDK_LIBRARIES})
|
||||||
|
endif()
|
||||||
if(WITH_CYCLES_EMBREE)
|
if(WITH_CYCLES_EMBREE)
|
||||||
target_link_libraries(${target} ${EMBREE_LIBRARIES})
|
target_link_libraries(${target} ${EMBREE_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
5
extern/CMakeLists.txt
vendored
5
extern/CMakeLists.txt
vendored
@@ -105,3 +105,8 @@ if(WITH_AUDASPACE AND NOT WITH_SYSTEM_AUDASPACE)
|
|||||||
set(AUDASPACE_CMAKE_CFG ${CMAKE_CURRENT_SOURCE_DIR}/audaspace/blender_config.cmake)
|
set(AUDASPACE_CMAKE_CFG ${CMAKE_CURRENT_SOURCE_DIR}/audaspace/blender_config.cmake)
|
||||||
add_subdirectory(audaspace)
|
add_subdirectory(audaspace)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_OPENXR AND OPENXR_USE_BUNDLED_SRC)
|
||||||
|
add_subdirectory(jsoncpp)
|
||||||
|
add_subdirectory(openxr)
|
||||||
|
endif()
|
||||||
|
|||||||
20
extern/jsoncpp/CMakeLists.txt
vendored
Normal file
20
extern/jsoncpp/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program 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 General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# All rights reserved.
|
||||||
|
# ***** END GPL LICENSE BLOCK *****
|
||||||
|
|
||||||
|
add_subdirectory(src)
|
||||||
98
extern/jsoncpp/include/json/allocator.h
vendored
Normal file
98
extern/jsoncpp/include/json/allocator.h
vendored
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef CPPTL_JSON_ALLOCATOR_H_INCLUDED
|
||||||
|
#define CPPTL_JSON_ALLOCATOR_H_INCLUDED
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#pragma pack(push, 8)
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
template<typename T>
|
||||||
|
class SecureAllocator {
|
||||||
|
public:
|
||||||
|
// Type definitions
|
||||||
|
using value_type = T;
|
||||||
|
using pointer = T*;
|
||||||
|
using const_pointer = const T*;
|
||||||
|
using reference = T&;
|
||||||
|
using const_reference = const T&;
|
||||||
|
using size_type = std::size_t;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate memory for N items using the standard allocator.
|
||||||
|
*/
|
||||||
|
pointer allocate(size_type n) {
|
||||||
|
// allocate using "global operator new"
|
||||||
|
return static_cast<pointer>(::operator new(n * sizeof(T)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release memory which was allocated for N items at pointer P.
|
||||||
|
*
|
||||||
|
* The memory block is filled with zeroes before being released.
|
||||||
|
* The pointer argument is tagged as "volatile" to prevent the
|
||||||
|
* compiler optimizing out this critical step.
|
||||||
|
*/
|
||||||
|
void deallocate(volatile pointer p, size_type n) {
|
||||||
|
std::memset(p, 0, n * sizeof(T));
|
||||||
|
// free using "global operator delete"
|
||||||
|
::operator delete(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an item in-place at pointer P.
|
||||||
|
*/
|
||||||
|
template<typename... Args>
|
||||||
|
void construct(pointer p, Args&&... args) {
|
||||||
|
// construct using "placement new" and "perfect forwarding"
|
||||||
|
::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_type max_size() const {
|
||||||
|
return size_t(-1) / sizeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer address( reference x ) const {
|
||||||
|
return std::addressof(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_pointer address( const_reference x ) const {
|
||||||
|
return std::addressof(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy an item in-place at pointer P.
|
||||||
|
*/
|
||||||
|
void destroy(pointer p) {
|
||||||
|
// destroy using "explicit destructor"
|
||||||
|
p->~T();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Boilerplate
|
||||||
|
SecureAllocator() {}
|
||||||
|
template<typename U> SecureAllocator(const SecureAllocator<U>&) {}
|
||||||
|
template<typename U> struct rebind { using other = SecureAllocator<U>; };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} //namespace Json
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#endif // CPPTL_JSON_ALLOCATOR_H_INCLUDED
|
||||||
54
extern/jsoncpp/include/json/assertions.h
vendored
Normal file
54
extern/jsoncpp/include/json/assertions.h
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED
|
||||||
|
#define CPPTL_JSON_ASSERTIONS_H_INCLUDED
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include "config.h"
|
||||||
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
|
/** It should not be possible for a maliciously designed file to
|
||||||
|
* cause an abort() or seg-fault, so these macros are used only
|
||||||
|
* for pre-condition violations and internal logic errors.
|
||||||
|
*/
|
||||||
|
#if JSON_USE_EXCEPTION
|
||||||
|
|
||||||
|
// @todo <= add detail about condition in exception
|
||||||
|
# define JSON_ASSERT(condition) \
|
||||||
|
{if (!(condition)) {Json::throwLogicError( "assert json failed" );}}
|
||||||
|
|
||||||
|
# define JSON_FAIL_MESSAGE(message) \
|
||||||
|
{ \
|
||||||
|
JSONCPP_OSTRINGSTREAM oss; oss << message; \
|
||||||
|
Json::throwLogicError(oss.str()); \
|
||||||
|
abort(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // JSON_USE_EXCEPTION
|
||||||
|
|
||||||
|
# define JSON_ASSERT(condition) assert(condition)
|
||||||
|
|
||||||
|
// The call to assert() will show the failure message in debug builds. In
|
||||||
|
// release builds we abort, for a core-dump or debugger.
|
||||||
|
# define JSON_FAIL_MESSAGE(message) \
|
||||||
|
{ \
|
||||||
|
JSONCPP_OSTRINGSTREAM oss; oss << message; \
|
||||||
|
assert(false && oss.str().c_str()); \
|
||||||
|
abort(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define JSON_ASSERT_MESSAGE(condition, message) \
|
||||||
|
if (!(condition)) { \
|
||||||
|
JSON_FAIL_MESSAGE(message); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED
|
||||||
25
extern/jsoncpp/include/json/autolink.h
vendored
Normal file
25
extern/jsoncpp/include/json/autolink.h
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef JSON_AUTOLINK_H_INCLUDED
|
||||||
|
#define JSON_AUTOLINK_H_INCLUDED
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#ifdef JSON_IN_CPPTL
|
||||||
|
#include <cpptl/cpptl_autolink.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && \
|
||||||
|
!defined(JSON_IN_CPPTL)
|
||||||
|
#define CPPTL_AUTOLINK_NAME "json"
|
||||||
|
#undef CPPTL_AUTOLINK_DLL
|
||||||
|
#ifdef JSON_DLL
|
||||||
|
#define CPPTL_AUTOLINK_DLL
|
||||||
|
#endif
|
||||||
|
#include "autolink.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // JSON_AUTOLINK_H_INCLUDED
|
||||||
184
extern/jsoncpp/include/json/config.h
vendored
Normal file
184
extern/jsoncpp/include/json/config.h
vendored
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef JSON_CONFIG_H_INCLUDED
|
||||||
|
#define JSON_CONFIG_H_INCLUDED
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string> //typedef String
|
||||||
|
#include <stdint.h> //typedef int64_t, uint64_t
|
||||||
|
|
||||||
|
/// If defined, indicates that json library is embedded in CppTL library.
|
||||||
|
//# define JSON_IN_CPPTL 1
|
||||||
|
|
||||||
|
/// If defined, indicates that json may leverage CppTL library
|
||||||
|
//# define JSON_USE_CPPTL 1
|
||||||
|
/// If defined, indicates that cpptl vector based map should be used instead of
|
||||||
|
/// std::map
|
||||||
|
/// as Value container.
|
||||||
|
//# define JSON_USE_CPPTL_SMALLMAP 1
|
||||||
|
|
||||||
|
// If non-zero, the library uses exceptions to report bad input instead of C
|
||||||
|
// assertion macros. The default is to use exceptions.
|
||||||
|
#ifndef JSON_USE_EXCEPTION
|
||||||
|
#define JSON_USE_EXCEPTION 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// If defined, indicates that the source file is amalgated
|
||||||
|
/// to prevent private header inclusion.
|
||||||
|
/// Remarks: it is automatically defined in the generated amalgated header.
|
||||||
|
// #define JSON_IS_AMALGAMATION
|
||||||
|
|
||||||
|
#ifdef JSON_IN_CPPTL
|
||||||
|
#include <cpptl/config.h>
|
||||||
|
#ifndef JSON_USE_CPPTL
|
||||||
|
#define JSON_USE_CPPTL 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JSON_IN_CPPTL
|
||||||
|
#define JSON_API CPPTL_API
|
||||||
|
#elif defined(JSON_DLL_BUILD)
|
||||||
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
|
#define JSON_API __declspec(dllexport)
|
||||||
|
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
||||||
|
#endif // if defined(_MSC_VER)
|
||||||
|
#elif defined(JSON_DLL)
|
||||||
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
|
#define JSON_API __declspec(dllimport)
|
||||||
|
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
||||||
|
#endif // if defined(_MSC_VER)
|
||||||
|
#endif // ifdef JSON_IN_CPPTL
|
||||||
|
#if !defined(JSON_API)
|
||||||
|
#define JSON_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
|
||||||
|
// integer
|
||||||
|
// Storages, and 64 bits integer support is disabled.
|
||||||
|
// #define JSON_NO_INT64 1
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) // MSVC
|
||||||
|
# if _MSC_VER <= 1200 // MSVC 6
|
||||||
|
// Microsoft Visual Studio 6 only support conversion from __int64 to double
|
||||||
|
// (no conversion from unsigned __int64).
|
||||||
|
# define JSON_USE_INT64_DOUBLE_CONVERSION 1
|
||||||
|
// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
|
||||||
|
// characters in the debug information)
|
||||||
|
// All projects I've ever seen with VS6 were using this globally (not bothering
|
||||||
|
// with pragma push/pop).
|
||||||
|
# pragma warning(disable : 4786)
|
||||||
|
# endif // MSVC 6
|
||||||
|
|
||||||
|
# if _MSC_VER >= 1500 // MSVC 2008
|
||||||
|
/// Indicates that the following function is deprecated.
|
||||||
|
# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif // defined(_MSC_VER)
|
||||||
|
|
||||||
|
// In c++11 the override keyword allows you to explicity define that a function
|
||||||
|
// is intended to override the base-class version. This makes the code more
|
||||||
|
// managable and fixes a set of common hard-to-find bugs.
|
||||||
|
#if __cplusplus >= 201103L
|
||||||
|
# define JSONCPP_OVERRIDE override
|
||||||
|
# define JSONCPP_NOEXCEPT noexcept
|
||||||
|
#elif defined(_MSC_VER) && _MSC_VER > 1600 && _MSC_VER < 1900
|
||||||
|
# define JSONCPP_OVERRIDE override
|
||||||
|
# define JSONCPP_NOEXCEPT throw()
|
||||||
|
#elif defined(_MSC_VER) && _MSC_VER >= 1900
|
||||||
|
# define JSONCPP_OVERRIDE override
|
||||||
|
# define JSONCPP_NOEXCEPT noexcept
|
||||||
|
#else
|
||||||
|
# define JSONCPP_OVERRIDE
|
||||||
|
# define JSONCPP_NOEXCEPT throw()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef JSON_HAS_RVALUE_REFERENCES
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010
|
||||||
|
#define JSON_HAS_RVALUE_REFERENCES 1
|
||||||
|
#endif // MSVC >= 2010
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#if __has_feature(cxx_rvalue_references)
|
||||||
|
#define JSON_HAS_RVALUE_REFERENCES 1
|
||||||
|
#endif // has_feature
|
||||||
|
|
||||||
|
#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
|
||||||
|
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
|
||||||
|
#define JSON_HAS_RVALUE_REFERENCES 1
|
||||||
|
#endif // GXX_EXPERIMENTAL
|
||||||
|
|
||||||
|
#endif // __clang__ || __GNUC__
|
||||||
|
|
||||||
|
#endif // not defined JSON_HAS_RVALUE_REFERENCES
|
||||||
|
|
||||||
|
#ifndef JSON_HAS_RVALUE_REFERENCES
|
||||||
|
#define JSON_HAS_RVALUE_REFERENCES 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
|
||||||
|
# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
|
||||||
|
# define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message)))
|
||||||
|
# elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||||
|
# define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
|
||||||
|
# endif // GNUC version
|
||||||
|
#endif // __clang__ || __GNUC__
|
||||||
|
|
||||||
|
#if !defined(JSONCPP_DEPRECATED)
|
||||||
|
#define JSONCPP_DEPRECATED(message)
|
||||||
|
#endif // if !defined(JSONCPP_DEPRECATED)
|
||||||
|
|
||||||
|
#if __GNUC__ >= 6
|
||||||
|
# define JSON_USE_INT64_DOUBLE_CONVERSION 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
|
# include "version.h"
|
||||||
|
|
||||||
|
# if JSONCPP_USING_SECURE_MEMORY
|
||||||
|
# include "allocator.h" //typedef Allocator
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
typedef int Int;
|
||||||
|
typedef unsigned int UInt;
|
||||||
|
#if defined(JSON_NO_INT64)
|
||||||
|
typedef int LargestInt;
|
||||||
|
typedef unsigned int LargestUInt;
|
||||||
|
#undef JSON_HAS_INT64
|
||||||
|
#else // if defined(JSON_NO_INT64)
|
||||||
|
// For Microsoft Visual use specific types as long long is not supported
|
||||||
|
#if defined(_MSC_VER) // Microsoft Visual Studio
|
||||||
|
typedef __int64 Int64;
|
||||||
|
typedef unsigned __int64 UInt64;
|
||||||
|
#else // if defined(_MSC_VER) // Other platforms, use long long
|
||||||
|
typedef int64_t Int64;
|
||||||
|
typedef uint64_t UInt64;
|
||||||
|
#endif // if defined(_MSC_VER)
|
||||||
|
typedef Int64 LargestInt;
|
||||||
|
typedef UInt64 LargestUInt;
|
||||||
|
#define JSON_HAS_INT64
|
||||||
|
#endif // if defined(JSON_NO_INT64)
|
||||||
|
#if JSONCPP_USING_SECURE_MEMORY
|
||||||
|
#define JSONCPP_STRING std::basic_string<char, std::char_traits<char>, Json::SecureAllocator<char> >
|
||||||
|
#define JSONCPP_OSTRINGSTREAM std::basic_ostringstream<char, std::char_traits<char>, Json::SecureAllocator<char> >
|
||||||
|
#define JSONCPP_OSTREAM std::basic_ostream<char, std::char_traits<char>>
|
||||||
|
#define JSONCPP_ISTRINGSTREAM std::basic_istringstream<char, std::char_traits<char>, Json::SecureAllocator<char> >
|
||||||
|
#define JSONCPP_ISTREAM std::istream
|
||||||
|
#else
|
||||||
|
#define JSONCPP_STRING std::string
|
||||||
|
#define JSONCPP_OSTRINGSTREAM std::ostringstream
|
||||||
|
#define JSONCPP_OSTREAM std::ostream
|
||||||
|
#define JSONCPP_ISTRINGSTREAM std::istringstream
|
||||||
|
#define JSONCPP_ISTREAM std::istream
|
||||||
|
#endif // if JSONCPP_USING_SECURE_MEMORY
|
||||||
|
} // end namespace Json
|
||||||
|
|
||||||
|
#endif // JSON_CONFIG_H_INCLUDED
|
||||||
61
extern/jsoncpp/include/json/features.h
vendored
Normal file
61
extern/jsoncpp/include/json/features.h
vendored
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
|
||||||
|
#define CPPTL_JSON_FEATURES_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include "forwards.h"
|
||||||
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
|
#pragma pack(push, 8)
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
|
||||||
|
/** \brief Configuration passed to reader and writer.
|
||||||
|
* This configuration object can be used to force the Reader or Writer
|
||||||
|
* to behave in a standard conforming way.
|
||||||
|
*/
|
||||||
|
class JSON_API Features {
|
||||||
|
public:
|
||||||
|
/** \brief A configuration that allows all features and assumes all strings
|
||||||
|
* are UTF-8.
|
||||||
|
* - C & C++ comments are allowed
|
||||||
|
* - Root object can be any JSON value
|
||||||
|
* - Assumes Value strings are encoded in UTF-8
|
||||||
|
*/
|
||||||
|
static Features all();
|
||||||
|
|
||||||
|
/** \brief A configuration that is strictly compatible with the JSON
|
||||||
|
* specification.
|
||||||
|
* - Comments are forbidden.
|
||||||
|
* - Root object must be either an array or an object value.
|
||||||
|
* - Assumes Value strings are encoded in UTF-8
|
||||||
|
*/
|
||||||
|
static Features strictMode();
|
||||||
|
|
||||||
|
/** \brief Initialize the configuration like JsonConfig::allFeatures;
|
||||||
|
*/
|
||||||
|
Features();
|
||||||
|
|
||||||
|
/// \c true if comments are allowed. Default: \c true.
|
||||||
|
bool allowComments_;
|
||||||
|
|
||||||
|
/// \c true if root must be either an array or an object value. Default: \c
|
||||||
|
/// false.
|
||||||
|
bool strictRoot_;
|
||||||
|
|
||||||
|
/// \c true if dropped null placeholders are allowed. Default: \c false.
|
||||||
|
bool allowDroppedNullPlaceholders_;
|
||||||
|
|
||||||
|
/// \c true if numeric object key are allowed. Default: \c false.
|
||||||
|
bool allowNumericKeys_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Json
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#endif // CPPTL_JSON_FEATURES_H_INCLUDED
|
||||||
37
extern/jsoncpp/include/json/forwards.h
vendored
Normal file
37
extern/jsoncpp/include/json/forwards.h
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef JSON_FORWARDS_H_INCLUDED
|
||||||
|
#define JSON_FORWARDS_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include "config.h"
|
||||||
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
|
||||||
|
// writer.h
|
||||||
|
class FastWriter;
|
||||||
|
class StyledWriter;
|
||||||
|
|
||||||
|
// reader.h
|
||||||
|
class Reader;
|
||||||
|
|
||||||
|
// features.h
|
||||||
|
class Features;
|
||||||
|
|
||||||
|
// value.h
|
||||||
|
typedef unsigned int ArrayIndex;
|
||||||
|
class StaticString;
|
||||||
|
class Path;
|
||||||
|
class PathArgument;
|
||||||
|
class Value;
|
||||||
|
class ValueIteratorBase;
|
||||||
|
class ValueIterator;
|
||||||
|
class ValueConstIterator;
|
||||||
|
|
||||||
|
} // namespace Json
|
||||||
|
|
||||||
|
#endif // JSON_FORWARDS_H_INCLUDED
|
||||||
15
extern/jsoncpp/include/json/json.h
vendored
Normal file
15
extern/jsoncpp/include/json/json.h
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef JSON_JSON_H_INCLUDED
|
||||||
|
#define JSON_JSON_H_INCLUDED
|
||||||
|
|
||||||
|
#include "autolink.h"
|
||||||
|
#include "value.h"
|
||||||
|
#include "reader.h"
|
||||||
|
#include "writer.h"
|
||||||
|
#include "features.h"
|
||||||
|
|
||||||
|
#endif // JSON_JSON_H_INCLUDED
|
||||||
408
extern/jsoncpp/include/json/reader.h
vendored
Normal file
408
extern/jsoncpp/include/json/reader.h
vendored
Normal file
@@ -0,0 +1,408 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef CPPTL_JSON_READER_H_INCLUDED
|
||||||
|
#define CPPTL_JSON_READER_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include "features.h"
|
||||||
|
#include "value.h"
|
||||||
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include <deque>
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <stack>
|
||||||
|
#include <string>
|
||||||
|
#include <istream>
|
||||||
|
|
||||||
|
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
|
||||||
|
// be used by...
|
||||||
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251)
|
||||||
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
|
#pragma pack(push, 8)
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
|
||||||
|
/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
|
||||||
|
*Value.
|
||||||
|
*
|
||||||
|
* \deprecated Use CharReader and CharReaderBuilder.
|
||||||
|
*/
|
||||||
|
class JSON_API Reader {
|
||||||
|
public:
|
||||||
|
typedef char Char;
|
||||||
|
typedef const Char* Location;
|
||||||
|
|
||||||
|
/** \brief An error tagged with where in the JSON text it was encountered.
|
||||||
|
*
|
||||||
|
* The offsets give the [start, limit) range of bytes within the text. Note
|
||||||
|
* that this is bytes, not codepoints.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct StructuredError {
|
||||||
|
ptrdiff_t offset_start;
|
||||||
|
ptrdiff_t offset_limit;
|
||||||
|
JSONCPP_STRING message;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Constructs a Reader allowing all features
|
||||||
|
* for parsing.
|
||||||
|
*/
|
||||||
|
Reader();
|
||||||
|
|
||||||
|
/** \brief Constructs a Reader allowing the specified feature set
|
||||||
|
* for parsing.
|
||||||
|
*/
|
||||||
|
Reader(const Features& features);
|
||||||
|
|
||||||
|
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
||||||
|
* document.
|
||||||
|
* \param document UTF-8 encoded string containing the document to read.
|
||||||
|
* \param root [out] Contains the root value of the document if it was
|
||||||
|
* successfully parsed.
|
||||||
|
* \param collectComments \c true to collect comment and allow writing them
|
||||||
|
* back during
|
||||||
|
* serialization, \c false to discard comments.
|
||||||
|
* This parameter is ignored if
|
||||||
|
* Features::allowComments_
|
||||||
|
* is \c false.
|
||||||
|
* \return \c true if the document was successfully parsed, \c false if an
|
||||||
|
* error occurred.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
parse(const std::string& document, Value& root, bool collectComments = true);
|
||||||
|
|
||||||
|
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
||||||
|
document.
|
||||||
|
* \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
|
||||||
|
document to read.
|
||||||
|
* \param endDoc Pointer on the end of the UTF-8 encoded string of the
|
||||||
|
document to read.
|
||||||
|
* Must be >= beginDoc.
|
||||||
|
* \param root [out] Contains the root value of the document if it was
|
||||||
|
* successfully parsed.
|
||||||
|
* \param collectComments \c true to collect comment and allow writing them
|
||||||
|
back during
|
||||||
|
* serialization, \c false to discard comments.
|
||||||
|
* This parameter is ignored if
|
||||||
|
Features::allowComments_
|
||||||
|
* is \c false.
|
||||||
|
* \return \c true if the document was successfully parsed, \c false if an
|
||||||
|
error occurred.
|
||||||
|
*/
|
||||||
|
bool parse(const char* beginDoc,
|
||||||
|
const char* endDoc,
|
||||||
|
Value& root,
|
||||||
|
bool collectComments = true);
|
||||||
|
|
||||||
|
/// \brief Parse from input stream.
|
||||||
|
/// \see Json::operator>>(std::istream&, Json::Value&).
|
||||||
|
bool parse(JSONCPP_ISTREAM& is, Value& root, bool collectComments = true);
|
||||||
|
|
||||||
|
/** \brief Returns a user friendly string that list errors in the parsed
|
||||||
|
* document.
|
||||||
|
* \return Formatted error message with the list of errors with their location
|
||||||
|
* in
|
||||||
|
* the parsed document. An empty string is returned if no error
|
||||||
|
* occurred
|
||||||
|
* during parsing.
|
||||||
|
* \deprecated Use getFormattedErrorMessages() instead (typo fix).
|
||||||
|
*/
|
||||||
|
JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
|
||||||
|
JSONCPP_STRING getFormatedErrorMessages() const;
|
||||||
|
|
||||||
|
/** \brief Returns a user friendly string that list errors in the parsed
|
||||||
|
* document.
|
||||||
|
* \return Formatted error message with the list of errors with their location
|
||||||
|
* in
|
||||||
|
* the parsed document. An empty string is returned if no error
|
||||||
|
* occurred
|
||||||
|
* during parsing.
|
||||||
|
*/
|
||||||
|
JSONCPP_STRING getFormattedErrorMessages() const;
|
||||||
|
|
||||||
|
/** \brief Returns a vector of structured erros encounted while parsing.
|
||||||
|
* \return A (possibly empty) vector of StructuredError objects. Currently
|
||||||
|
* only one error can be returned, but the caller should tolerate
|
||||||
|
* multiple
|
||||||
|
* errors. This can occur if the parser recovers from a non-fatal
|
||||||
|
* parse error and then encounters additional errors.
|
||||||
|
*/
|
||||||
|
std::vector<StructuredError> getStructuredErrors() const;
|
||||||
|
|
||||||
|
/** \brief Add a semantic error message.
|
||||||
|
* \param value JSON Value location associated with the error
|
||||||
|
* \param message The error message.
|
||||||
|
* \return \c true if the error was successfully added, \c false if the
|
||||||
|
* Value offset exceeds the document size.
|
||||||
|
*/
|
||||||
|
bool pushError(const Value& value, const JSONCPP_STRING& message);
|
||||||
|
|
||||||
|
/** \brief Add a semantic error message with extra context.
|
||||||
|
* \param value JSON Value location associated with the error
|
||||||
|
* \param message The error message.
|
||||||
|
* \param extra Additional JSON Value location to contextualize the error
|
||||||
|
* \return \c true if the error was successfully added, \c false if either
|
||||||
|
* Value offset exceeds the document size.
|
||||||
|
*/
|
||||||
|
bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
|
||||||
|
|
||||||
|
/** \brief Return whether there are any errors.
|
||||||
|
* \return \c true if there are no errors to report \c false if
|
||||||
|
* errors have occurred.
|
||||||
|
*/
|
||||||
|
bool good() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum TokenType {
|
||||||
|
tokenEndOfStream = 0,
|
||||||
|
tokenObjectBegin,
|
||||||
|
tokenObjectEnd,
|
||||||
|
tokenArrayBegin,
|
||||||
|
tokenArrayEnd,
|
||||||
|
tokenString,
|
||||||
|
tokenNumber,
|
||||||
|
tokenTrue,
|
||||||
|
tokenFalse,
|
||||||
|
tokenNull,
|
||||||
|
tokenArraySeparator,
|
||||||
|
tokenMemberSeparator,
|
||||||
|
tokenComment,
|
||||||
|
tokenError
|
||||||
|
};
|
||||||
|
|
||||||
|
class Token {
|
||||||
|
public:
|
||||||
|
TokenType type_;
|
||||||
|
Location start_;
|
||||||
|
Location end_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ErrorInfo {
|
||||||
|
public:
|
||||||
|
Token token_;
|
||||||
|
JSONCPP_STRING message_;
|
||||||
|
Location extra_;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::deque<ErrorInfo> Errors;
|
||||||
|
|
||||||
|
bool readToken(Token& token);
|
||||||
|
void skipSpaces();
|
||||||
|
bool match(Location pattern, int patternLength);
|
||||||
|
bool readComment();
|
||||||
|
bool readCStyleComment();
|
||||||
|
bool readCppStyleComment();
|
||||||
|
bool readString();
|
||||||
|
void readNumber();
|
||||||
|
bool readValue();
|
||||||
|
bool readObject(Token& token);
|
||||||
|
bool readArray(Token& token);
|
||||||
|
bool decodeNumber(Token& token);
|
||||||
|
bool decodeNumber(Token& token, Value& decoded);
|
||||||
|
bool decodeString(Token& token);
|
||||||
|
bool decodeString(Token& token, JSONCPP_STRING& decoded);
|
||||||
|
bool decodeDouble(Token& token);
|
||||||
|
bool decodeDouble(Token& token, Value& decoded);
|
||||||
|
bool decodeUnicodeCodePoint(Token& token,
|
||||||
|
Location& current,
|
||||||
|
Location end,
|
||||||
|
unsigned int& unicode);
|
||||||
|
bool decodeUnicodeEscapeSequence(Token& token,
|
||||||
|
Location& current,
|
||||||
|
Location end,
|
||||||
|
unsigned int& unicode);
|
||||||
|
bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
|
||||||
|
bool recoverFromError(TokenType skipUntilToken);
|
||||||
|
bool addErrorAndRecover(const JSONCPP_STRING& message,
|
||||||
|
Token& token,
|
||||||
|
TokenType skipUntilToken);
|
||||||
|
void skipUntilSpace();
|
||||||
|
Value& currentValue();
|
||||||
|
Char getNextChar();
|
||||||
|
void
|
||||||
|
getLocationLineAndColumn(Location location, int& line, int& column) const;
|
||||||
|
JSONCPP_STRING getLocationLineAndColumn(Location location) const;
|
||||||
|
void addComment(Location begin, Location end, CommentPlacement placement);
|
||||||
|
void skipCommentTokens(Token& token);
|
||||||
|
|
||||||
|
typedef std::stack<Value*> Nodes;
|
||||||
|
Nodes nodes_;
|
||||||
|
Errors errors_;
|
||||||
|
JSONCPP_STRING document_;
|
||||||
|
Location begin_;
|
||||||
|
Location end_;
|
||||||
|
Location current_;
|
||||||
|
Location lastValueEnd_;
|
||||||
|
Value* lastValue_;
|
||||||
|
JSONCPP_STRING commentsBefore_;
|
||||||
|
Features features_;
|
||||||
|
bool collectComments_;
|
||||||
|
}; // Reader
|
||||||
|
|
||||||
|
/** Interface for reading JSON from a char array.
|
||||||
|
*/
|
||||||
|
class JSON_API CharReader {
|
||||||
|
public:
|
||||||
|
virtual ~CharReader() {}
|
||||||
|
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
||||||
|
document.
|
||||||
|
* The document must be a UTF-8 encoded string containing the document to read.
|
||||||
|
*
|
||||||
|
* \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
|
||||||
|
document to read.
|
||||||
|
* \param endDoc Pointer on the end of the UTF-8 encoded string of the
|
||||||
|
document to read.
|
||||||
|
* Must be >= beginDoc.
|
||||||
|
* \param root [out] Contains the root value of the document if it was
|
||||||
|
* successfully parsed.
|
||||||
|
* \param errs [out] Formatted error messages (if not NULL)
|
||||||
|
* a user friendly string that lists errors in the parsed
|
||||||
|
* document.
|
||||||
|
* \return \c true if the document was successfully parsed, \c false if an
|
||||||
|
error occurred.
|
||||||
|
*/
|
||||||
|
virtual bool parse(
|
||||||
|
char const* beginDoc, char const* endDoc,
|
||||||
|
Value* root, JSONCPP_STRING* errs) = 0;
|
||||||
|
|
||||||
|
class JSON_API Factory {
|
||||||
|
public:
|
||||||
|
virtual ~Factory() {}
|
||||||
|
/** \brief Allocate a CharReader via operator new().
|
||||||
|
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||||
|
*/
|
||||||
|
virtual CharReader* newCharReader() const = 0;
|
||||||
|
}; // Factory
|
||||||
|
}; // CharReader
|
||||||
|
|
||||||
|
/** \brief Build a CharReader implementation.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
\code
|
||||||
|
using namespace Json;
|
||||||
|
CharReaderBuilder builder;
|
||||||
|
builder["collectComments"] = false;
|
||||||
|
Value value;
|
||||||
|
JSONCPP_STRING errs;
|
||||||
|
bool ok = parseFromStream(builder, std::cin, &value, &errs);
|
||||||
|
\endcode
|
||||||
|
*/
|
||||||
|
class JSON_API CharReaderBuilder : public CharReader::Factory {
|
||||||
|
public:
|
||||||
|
// Note: We use a Json::Value so that we can add data-members to this class
|
||||||
|
// without a major version bump.
|
||||||
|
/** Configuration of this builder.
|
||||||
|
These are case-sensitive.
|
||||||
|
Available settings (case-sensitive):
|
||||||
|
- `"collectComments": false or true`
|
||||||
|
- true to collect comment and allow writing them
|
||||||
|
back during serialization, false to discard comments.
|
||||||
|
This parameter is ignored if allowComments is false.
|
||||||
|
- `"allowComments": false or true`
|
||||||
|
- true if comments are allowed.
|
||||||
|
- `"strictRoot": false or true`
|
||||||
|
- true if root must be either an array or an object value
|
||||||
|
- `"allowDroppedNullPlaceholders": false or true`
|
||||||
|
- true if dropped null placeholders are allowed. (See StreamWriterBuilder.)
|
||||||
|
- `"allowNumericKeys": false or true`
|
||||||
|
- true if numeric object keys are allowed.
|
||||||
|
- `"allowSingleQuotes": false or true`
|
||||||
|
- true if '' are allowed for strings (both keys and values)
|
||||||
|
- `"stackLimit": integer`
|
||||||
|
- Exceeding stackLimit (recursive depth of `readValue()`) will
|
||||||
|
cause an exception.
|
||||||
|
- This is a security issue (seg-faults caused by deeply nested JSON),
|
||||||
|
so the default is low.
|
||||||
|
- `"failIfExtra": false or true`
|
||||||
|
- If true, `parse()` returns false when extra non-whitespace trails
|
||||||
|
the JSON value in the input string.
|
||||||
|
- `"rejectDupKeys": false or true`
|
||||||
|
- If true, `parse()` returns false when a key is duplicated within an object.
|
||||||
|
- `"allowSpecialFloats": false or true`
|
||||||
|
- If true, special float values (NaNs and infinities) are allowed
|
||||||
|
and their values are lossfree restorable.
|
||||||
|
|
||||||
|
You can examine 'settings_` yourself
|
||||||
|
to see the defaults. You can also write and read them just like any
|
||||||
|
JSON Value.
|
||||||
|
\sa setDefaults()
|
||||||
|
*/
|
||||||
|
Json::Value settings_;
|
||||||
|
|
||||||
|
CharReaderBuilder();
|
||||||
|
~CharReaderBuilder() JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
|
CharReader* newCharReader() const JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
|
/** \return true if 'settings' are legal and consistent;
|
||||||
|
* otherwise, indicate bad settings via 'invalid'.
|
||||||
|
*/
|
||||||
|
bool validate(Json::Value* invalid) const;
|
||||||
|
|
||||||
|
/** A simple way to update a specific setting.
|
||||||
|
*/
|
||||||
|
Value& operator[](JSONCPP_STRING key);
|
||||||
|
|
||||||
|
/** Called by ctor, but you can use this to reset settings_.
|
||||||
|
* \pre 'settings' != NULL (but Json::null is fine)
|
||||||
|
* \remark Defaults:
|
||||||
|
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
|
||||||
|
*/
|
||||||
|
static void setDefaults(Json::Value* settings);
|
||||||
|
/** Same as old Features::strictMode().
|
||||||
|
* \pre 'settings' != NULL (but Json::null is fine)
|
||||||
|
* \remark Defaults:
|
||||||
|
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
|
||||||
|
*/
|
||||||
|
static void strictMode(Json::Value* settings);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Consume entire stream and use its begin/end.
|
||||||
|
* Someday we might have a real StreamReader, but for now this
|
||||||
|
* is convenient.
|
||||||
|
*/
|
||||||
|
bool JSON_API parseFromStream(
|
||||||
|
CharReader::Factory const&,
|
||||||
|
JSONCPP_ISTREAM&,
|
||||||
|
Value* root, std::string* errs);
|
||||||
|
|
||||||
|
/** \brief Read from 'sin' into 'root'.
|
||||||
|
|
||||||
|
Always keep comments from the input JSON.
|
||||||
|
|
||||||
|
This can be used to read a file into a particular sub-object.
|
||||||
|
For example:
|
||||||
|
\code
|
||||||
|
Json::Value root;
|
||||||
|
cin >> root["dir"]["file"];
|
||||||
|
cout << root;
|
||||||
|
\endcode
|
||||||
|
Result:
|
||||||
|
\verbatim
|
||||||
|
{
|
||||||
|
"dir": {
|
||||||
|
"file": {
|
||||||
|
// The input stream JSON would be nested here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
\endverbatim
|
||||||
|
\throw std::exception on parse error.
|
||||||
|
\see Json::operator<<()
|
||||||
|
*/
|
||||||
|
JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&);
|
||||||
|
|
||||||
|
} // namespace Json
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
|
#endif // CPPTL_JSON_READER_H_INCLUDED
|
||||||
888
extern/jsoncpp/include/json/value.h
vendored
Normal file
888
extern/jsoncpp/include/json/value.h
vendored
Normal file
@@ -0,0 +1,888 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef CPPTL_JSON_H_INCLUDED
|
||||||
|
#define CPPTL_JSON_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include "forwards.h"
|
||||||
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
#ifndef JSON_USE_CPPTL_SMALLMAP
|
||||||
|
#include <map>
|
||||||
|
#else
|
||||||
|
#include <cpptl/smallmap.h>
|
||||||
|
#endif
|
||||||
|
#ifdef JSON_USE_CPPTL
|
||||||
|
#include <cpptl/forwards.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//Conditional NORETURN attribute on the throw functions would:
|
||||||
|
// a) suppress false positives from static code analysis
|
||||||
|
// b) possibly improve optimization opportunities.
|
||||||
|
#if !defined(JSONCPP_NORETURN)
|
||||||
|
# if defined(_MSC_VER)
|
||||||
|
# define JSONCPP_NORETURN __declspec(noreturn)
|
||||||
|
# elif defined(__GNUC__)
|
||||||
|
# define JSONCPP_NORETURN __attribute__ ((__noreturn__))
|
||||||
|
# else
|
||||||
|
# define JSONCPP_NORETURN
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
|
||||||
|
// be used by...
|
||||||
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251)
|
||||||
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
|
#pragma pack(push, 8)
|
||||||
|
|
||||||
|
/** \brief JSON (JavaScript Object Notation).
|
||||||
|
*/
|
||||||
|
namespace Json {
|
||||||
|
|
||||||
|
/** Base class for all exceptions we throw.
|
||||||
|
*
|
||||||
|
* We use nothing but these internally. Of course, STL can throw others.
|
||||||
|
*/
|
||||||
|
class JSON_API Exception : public std::exception {
|
||||||
|
public:
|
||||||
|
Exception(JSONCPP_STRING const& msg);
|
||||||
|
~Exception() JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
|
||||||
|
char const* what() const JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
|
||||||
|
protected:
|
||||||
|
JSONCPP_STRING msg_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Exceptions which the user cannot easily avoid.
|
||||||
|
*
|
||||||
|
* E.g. out-of-memory (when we use malloc), stack-overflow, malicious input
|
||||||
|
*
|
||||||
|
* \remark derived from Json::Exception
|
||||||
|
*/
|
||||||
|
class JSON_API RuntimeError : public Exception {
|
||||||
|
public:
|
||||||
|
RuntimeError(JSONCPP_STRING const& msg);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros.
|
||||||
|
*
|
||||||
|
* These are precondition-violations (user bugs) and internal errors (our bugs).
|
||||||
|
*
|
||||||
|
* \remark derived from Json::Exception
|
||||||
|
*/
|
||||||
|
class JSON_API LogicError : public Exception {
|
||||||
|
public:
|
||||||
|
LogicError(JSONCPP_STRING const& msg);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// used internally
|
||||||
|
JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg);
|
||||||
|
/// used internally
|
||||||
|
JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg);
|
||||||
|
|
||||||
|
/** \brief Type of the value held by a Value object.
|
||||||
|
*/
|
||||||
|
enum ValueType {
|
||||||
|
nullValue = 0, ///< 'null' value
|
||||||
|
intValue, ///< signed integer value
|
||||||
|
uintValue, ///< unsigned integer value
|
||||||
|
realValue, ///< double value
|
||||||
|
stringValue, ///< UTF-8 string value
|
||||||
|
booleanValue, ///< bool value
|
||||||
|
arrayValue, ///< array value (ordered list)
|
||||||
|
objectValue ///< object value (collection of name/value pairs).
|
||||||
|
};
|
||||||
|
|
||||||
|
enum CommentPlacement {
|
||||||
|
commentBefore = 0, ///< a comment placed on the line before a value
|
||||||
|
commentAfterOnSameLine, ///< a comment just after a value on the same line
|
||||||
|
commentAfter, ///< a comment on the line after a value (only make sense for
|
||||||
|
/// root value)
|
||||||
|
numberOfCommentPlacement
|
||||||
|
};
|
||||||
|
|
||||||
|
//# ifdef JSON_USE_CPPTL
|
||||||
|
// typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
|
||||||
|
// typedef CppTL::AnyEnumerator<const Value &> EnumValues;
|
||||||
|
//# endif
|
||||||
|
|
||||||
|
/** \brief Lightweight wrapper to tag static string.
|
||||||
|
*
|
||||||
|
* Value constructor and objectValue member assignement takes advantage of the
|
||||||
|
* StaticString and avoid the cost of string duplication when storing the
|
||||||
|
* string or the member name.
|
||||||
|
*
|
||||||
|
* Example of usage:
|
||||||
|
* \code
|
||||||
|
* Json::Value aValue( StaticString("some text") );
|
||||||
|
* Json::Value object;
|
||||||
|
* static const StaticString code("code");
|
||||||
|
* object[code] = 1234;
|
||||||
|
* \endcode
|
||||||
|
*/
|
||||||
|
class JSON_API StaticString {
|
||||||
|
public:
|
||||||
|
explicit StaticString(const char* czstring) : c_str_(czstring) {}
|
||||||
|
|
||||||
|
operator const char*() const { return c_str_; }
|
||||||
|
|
||||||
|
const char* c_str() const { return c_str_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* c_str_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Represents a <a HREF="http://www.json.org">JSON</a> value.
|
||||||
|
*
|
||||||
|
* This class is a discriminated union wrapper that can represents a:
|
||||||
|
* - signed integer [range: Value::minInt - Value::maxInt]
|
||||||
|
* - unsigned integer (range: 0 - Value::maxUInt)
|
||||||
|
* - double
|
||||||
|
* - UTF-8 string
|
||||||
|
* - boolean
|
||||||
|
* - 'null'
|
||||||
|
* - an ordered list of Value
|
||||||
|
* - collection of name/value pairs (javascript object)
|
||||||
|
*
|
||||||
|
* The type of the held value is represented by a #ValueType and
|
||||||
|
* can be obtained using type().
|
||||||
|
*
|
||||||
|
* Values of an #objectValue or #arrayValue can be accessed using operator[]()
|
||||||
|
* methods.
|
||||||
|
* Non-const methods will automatically create the a #nullValue element
|
||||||
|
* if it does not exist.
|
||||||
|
* The sequence of an #arrayValue will be automatically resized and initialized
|
||||||
|
* with #nullValue. resize() can be used to enlarge or truncate an #arrayValue.
|
||||||
|
*
|
||||||
|
* The get() methods can be used to obtain default value in the case the
|
||||||
|
* required element does not exist.
|
||||||
|
*
|
||||||
|
* It is possible to iterate over the list of a #objectValue values using
|
||||||
|
* the getMemberNames() method.
|
||||||
|
*
|
||||||
|
* \note #Value string-length fit in size_t, but keys must be < 2^30.
|
||||||
|
* (The reason is an implementation detail.) A #CharReader will raise an
|
||||||
|
* exception if a bound is exceeded to avoid security holes in your app,
|
||||||
|
* but the Value API does *not* check bounds. That is the responsibility
|
||||||
|
* of the caller.
|
||||||
|
*/
|
||||||
|
class JSON_API Value {
|
||||||
|
friend class ValueIteratorBase;
|
||||||
|
public:
|
||||||
|
typedef std::vector<JSONCPP_STRING> Members;
|
||||||
|
typedef ValueIterator iterator;
|
||||||
|
typedef ValueConstIterator const_iterator;
|
||||||
|
typedef Json::UInt UInt;
|
||||||
|
typedef Json::Int Int;
|
||||||
|
#if defined(JSON_HAS_INT64)
|
||||||
|
typedef Json::UInt64 UInt64;
|
||||||
|
typedef Json::Int64 Int64;
|
||||||
|
#endif // defined(JSON_HAS_INT64)
|
||||||
|
typedef Json::LargestInt LargestInt;
|
||||||
|
typedef Json::LargestUInt LargestUInt;
|
||||||
|
typedef Json::ArrayIndex ArrayIndex;
|
||||||
|
|
||||||
|
static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value().
|
||||||
|
static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null
|
||||||
|
static Value const& nullSingleton(); ///< Prefer this to null or nullRef.
|
||||||
|
|
||||||
|
/// Minimum signed integer value that can be stored in a Json::Value.
|
||||||
|
static const LargestInt minLargestInt;
|
||||||
|
/// Maximum signed integer value that can be stored in a Json::Value.
|
||||||
|
static const LargestInt maxLargestInt;
|
||||||
|
/// Maximum unsigned integer value that can be stored in a Json::Value.
|
||||||
|
static const LargestUInt maxLargestUInt;
|
||||||
|
|
||||||
|
/// Minimum signed int value that can be stored in a Json::Value.
|
||||||
|
static const Int minInt;
|
||||||
|
/// Maximum signed int value that can be stored in a Json::Value.
|
||||||
|
static const Int maxInt;
|
||||||
|
/// Maximum unsigned int value that can be stored in a Json::Value.
|
||||||
|
static const UInt maxUInt;
|
||||||
|
|
||||||
|
#if defined(JSON_HAS_INT64)
|
||||||
|
/// Minimum signed 64 bits int value that can be stored in a Json::Value.
|
||||||
|
static const Int64 minInt64;
|
||||||
|
/// Maximum signed 64 bits int value that can be stored in a Json::Value.
|
||||||
|
static const Int64 maxInt64;
|
||||||
|
/// Maximum unsigned 64 bits int value that can be stored in a Json::Value.
|
||||||
|
static const UInt64 maxUInt64;
|
||||||
|
#endif // defined(JSON_HAS_INT64)
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
|
||||||
|
class CZString {
|
||||||
|
public:
|
||||||
|
enum DuplicationPolicy {
|
||||||
|
noDuplication = 0,
|
||||||
|
duplicate,
|
||||||
|
duplicateOnCopy
|
||||||
|
};
|
||||||
|
CZString(ArrayIndex index);
|
||||||
|
CZString(char const* str, unsigned length, DuplicationPolicy allocate);
|
||||||
|
CZString(CZString const& other);
|
||||||
|
#if JSON_HAS_RVALUE_REFERENCES
|
||||||
|
CZString(CZString&& other);
|
||||||
|
#endif
|
||||||
|
~CZString();
|
||||||
|
CZString& operator=(const CZString& other);
|
||||||
|
|
||||||
|
#if JSON_HAS_RVALUE_REFERENCES
|
||||||
|
CZString& operator=(CZString&& other);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool operator<(CZString const& other) const;
|
||||||
|
bool operator==(CZString const& other) const;
|
||||||
|
ArrayIndex index() const;
|
||||||
|
//const char* c_str() const; ///< \deprecated
|
||||||
|
char const* data() const;
|
||||||
|
unsigned length() const;
|
||||||
|
bool isStaticString() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void swap(CZString& other);
|
||||||
|
|
||||||
|
struct StringStorage {
|
||||||
|
unsigned policy_: 2;
|
||||||
|
unsigned length_: 30; // 1GB max
|
||||||
|
};
|
||||||
|
|
||||||
|
char const* cstr_; // actually, a prefixed string, unless policy is noDup
|
||||||
|
union {
|
||||||
|
ArrayIndex index_;
|
||||||
|
StringStorage storage_;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
#ifndef JSON_USE_CPPTL_SMALLMAP
|
||||||
|
typedef std::map<CZString, Value> ObjectValues;
|
||||||
|
#else
|
||||||
|
typedef CppTL::SmallMap<CZString, Value> ObjectValues;
|
||||||
|
#endif // ifndef JSON_USE_CPPTL_SMALLMAP
|
||||||
|
#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** \brief Create a default Value of the given type.
|
||||||
|
|
||||||
|
This is a very useful constructor.
|
||||||
|
To create an empty array, pass arrayValue.
|
||||||
|
To create an empty object, pass objectValue.
|
||||||
|
Another Value can then be set to this one by assignment.
|
||||||
|
This is useful since clear() and resize() will not alter types.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
\code
|
||||||
|
Json::Value null_value; // null
|
||||||
|
Json::Value arr_value(Json::arrayValue); // []
|
||||||
|
Json::Value obj_value(Json::objectValue); // {}
|
||||||
|
\endcode
|
||||||
|
*/
|
||||||
|
Value(ValueType type = nullValue);
|
||||||
|
Value(Int value);
|
||||||
|
Value(UInt value);
|
||||||
|
#if defined(JSON_HAS_INT64)
|
||||||
|
Value(Int64 value);
|
||||||
|
Value(UInt64 value);
|
||||||
|
#endif // if defined(JSON_HAS_INT64)
|
||||||
|
Value(double value);
|
||||||
|
Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.)
|
||||||
|
Value(const char* begin, const char* end); ///< Copy all, incl zeroes.
|
||||||
|
/** \brief Constructs a value from a static string.
|
||||||
|
|
||||||
|
* Like other value string constructor but do not duplicate the string for
|
||||||
|
* internal storage. The given string must remain alive after the call to this
|
||||||
|
* constructor.
|
||||||
|
* \note This works only for null-terminated strings. (We cannot change the
|
||||||
|
* size of this class, so we have nowhere to store the length,
|
||||||
|
* which might be computed later for various operations.)
|
||||||
|
*
|
||||||
|
* Example of usage:
|
||||||
|
* \code
|
||||||
|
* static StaticString foo("some text");
|
||||||
|
* Json::Value aValue(foo);
|
||||||
|
* \endcode
|
||||||
|
*/
|
||||||
|
Value(const StaticString& value);
|
||||||
|
Value(const JSONCPP_STRING& value); ///< Copy data() til size(). Embedded zeroes too.
|
||||||
|
#ifdef JSON_USE_CPPTL
|
||||||
|
Value(const CppTL::ConstString& value);
|
||||||
|
#endif
|
||||||
|
Value(bool value);
|
||||||
|
/// Deep copy.
|
||||||
|
Value(const Value& other);
|
||||||
|
#if JSON_HAS_RVALUE_REFERENCES
|
||||||
|
/// Move constructor
|
||||||
|
Value(Value&& other);
|
||||||
|
#endif
|
||||||
|
~Value();
|
||||||
|
|
||||||
|
/// Deep copy, then swap(other).
|
||||||
|
/// \note Over-write existing comments. To preserve comments, use #swapPayload().
|
||||||
|
Value& operator=(const Value& other);
|
||||||
|
#if JSON_HAS_RVALUE_REFERENCES
|
||||||
|
Value& operator=(Value&& other);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Swap everything.
|
||||||
|
void swap(Value& other);
|
||||||
|
/// Swap values but leave comments and source offsets in place.
|
||||||
|
void swapPayload(Value& other);
|
||||||
|
|
||||||
|
/// copy everything.
|
||||||
|
void copy(const Value& other);
|
||||||
|
/// copy values but leave comments and source offsets in place.
|
||||||
|
void copyPayload(const Value& other);
|
||||||
|
|
||||||
|
ValueType type() const;
|
||||||
|
|
||||||
|
/// Compare payload only, not comments etc.
|
||||||
|
bool operator<(const Value& other) const;
|
||||||
|
bool operator<=(const Value& other) const;
|
||||||
|
bool operator>=(const Value& other) const;
|
||||||
|
bool operator>(const Value& other) const;
|
||||||
|
bool operator==(const Value& other) const;
|
||||||
|
bool operator!=(const Value& other) const;
|
||||||
|
int compare(const Value& other) const;
|
||||||
|
|
||||||
|
const char* asCString() const; ///< Embedded zeroes could cause you trouble!
|
||||||
|
#if JSONCPP_USING_SECURE_MEMORY
|
||||||
|
unsigned getCStringLength() const; //Allows you to understand the length of the CString
|
||||||
|
#endif
|
||||||
|
JSONCPP_STRING asString() const; ///< Embedded zeroes are possible.
|
||||||
|
/** Get raw char* of string-value.
|
||||||
|
* \return false if !string. (Seg-fault if str or end are NULL.)
|
||||||
|
*/
|
||||||
|
bool getString(
|
||||||
|
char const** begin, char const** end) const;
|
||||||
|
#ifdef JSON_USE_CPPTL
|
||||||
|
CppTL::ConstString asConstString() const;
|
||||||
|
#endif
|
||||||
|
Int asInt() const;
|
||||||
|
UInt asUInt() const;
|
||||||
|
#if defined(JSON_HAS_INT64)
|
||||||
|
Int64 asInt64() const;
|
||||||
|
UInt64 asUInt64() const;
|
||||||
|
#endif // if defined(JSON_HAS_INT64)
|
||||||
|
LargestInt asLargestInt() const;
|
||||||
|
LargestUInt asLargestUInt() const;
|
||||||
|
float asFloat() const;
|
||||||
|
double asDouble() const;
|
||||||
|
bool asBool() const;
|
||||||
|
|
||||||
|
bool isNull() const;
|
||||||
|
bool isBool() const;
|
||||||
|
bool isInt() const;
|
||||||
|
bool isInt64() const;
|
||||||
|
bool isUInt() const;
|
||||||
|
bool isUInt64() const;
|
||||||
|
bool isIntegral() const;
|
||||||
|
bool isDouble() const;
|
||||||
|
bool isNumeric() const;
|
||||||
|
bool isString() const;
|
||||||
|
bool isArray() const;
|
||||||
|
bool isObject() const;
|
||||||
|
|
||||||
|
bool isConvertibleTo(ValueType other) const;
|
||||||
|
|
||||||
|
/// Number of values in array or object
|
||||||
|
ArrayIndex size() const;
|
||||||
|
|
||||||
|
/// \brief Return true if empty array, empty object, or null;
|
||||||
|
/// otherwise, false.
|
||||||
|
bool empty() const;
|
||||||
|
|
||||||
|
/// Return isNull()
|
||||||
|
bool operator!() const;
|
||||||
|
|
||||||
|
/// Remove all object members and array elements.
|
||||||
|
/// \pre type() is arrayValue, objectValue, or nullValue
|
||||||
|
/// \post type() is unchanged
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
/// Resize the array to size elements.
|
||||||
|
/// New elements are initialized to null.
|
||||||
|
/// May only be called on nullValue or arrayValue.
|
||||||
|
/// \pre type() is arrayValue or nullValue
|
||||||
|
/// \post type() is arrayValue
|
||||||
|
void resize(ArrayIndex size);
|
||||||
|
|
||||||
|
/// Access an array element (zero based index ).
|
||||||
|
/// If the array contains less than index element, then null value are
|
||||||
|
/// inserted
|
||||||
|
/// in the array so that its size is index+1.
|
||||||
|
/// (You may need to say 'value[0u]' to get your compiler to distinguish
|
||||||
|
/// this from the operator[] which takes a string.)
|
||||||
|
Value& operator[](ArrayIndex index);
|
||||||
|
|
||||||
|
/// Access an array element (zero based index ).
|
||||||
|
/// If the array contains less than index element, then null value are
|
||||||
|
/// inserted
|
||||||
|
/// in the array so that its size is index+1.
|
||||||
|
/// (You may need to say 'value[0u]' to get your compiler to distinguish
|
||||||
|
/// this from the operator[] which takes a string.)
|
||||||
|
Value& operator[](int index);
|
||||||
|
|
||||||
|
/// Access an array element (zero based index )
|
||||||
|
/// (You may need to say 'value[0u]' to get your compiler to distinguish
|
||||||
|
/// this from the operator[] which takes a string.)
|
||||||
|
const Value& operator[](ArrayIndex index) const;
|
||||||
|
|
||||||
|
/// Access an array element (zero based index )
|
||||||
|
/// (You may need to say 'value[0u]' to get your compiler to distinguish
|
||||||
|
/// this from the operator[] which takes a string.)
|
||||||
|
const Value& operator[](int index) const;
|
||||||
|
|
||||||
|
/// If the array contains at least index+1 elements, returns the element
|
||||||
|
/// value,
|
||||||
|
/// otherwise returns defaultValue.
|
||||||
|
Value get(ArrayIndex index, const Value& defaultValue) const;
|
||||||
|
/// Return true if index < size().
|
||||||
|
bool isValidIndex(ArrayIndex index) const;
|
||||||
|
/// \brief Append value to array at the end.
|
||||||
|
///
|
||||||
|
/// Equivalent to jsonvalue[jsonvalue.size()] = value;
|
||||||
|
Value& append(const Value& value);
|
||||||
|
|
||||||
|
#if JSON_HAS_RVALUE_REFERENCES
|
||||||
|
Value& append(Value&& value);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Access an object value by name, create a null member if it does not exist.
|
||||||
|
/// \note Because of our implementation, keys are limited to 2^30 -1 chars.
|
||||||
|
/// Exceeding that will cause an exception.
|
||||||
|
Value& operator[](const char* key);
|
||||||
|
/// Access an object value by name, returns null if there is no member with
|
||||||
|
/// that name.
|
||||||
|
const Value& operator[](const char* key) const;
|
||||||
|
/// Access an object value by name, create a null member if it does not exist.
|
||||||
|
/// \param key may contain embedded nulls.
|
||||||
|
Value& operator[](const JSONCPP_STRING& key);
|
||||||
|
/// Access an object value by name, returns null if there is no member with
|
||||||
|
/// that name.
|
||||||
|
/// \param key may contain embedded nulls.
|
||||||
|
const Value& operator[](const JSONCPP_STRING& key) const;
|
||||||
|
/** \brief Access an object value by name, create a null member if it does not
|
||||||
|
exist.
|
||||||
|
|
||||||
|
* If the object has no entry for that name, then the member name used to store
|
||||||
|
* the new entry is not duplicated.
|
||||||
|
* Example of use:
|
||||||
|
* \code
|
||||||
|
* Json::Value object;
|
||||||
|
* static const StaticString code("code");
|
||||||
|
* object[code] = 1234;
|
||||||
|
* \endcode
|
||||||
|
*/
|
||||||
|
Value& operator[](const StaticString& key);
|
||||||
|
#ifdef JSON_USE_CPPTL
|
||||||
|
/// Access an object value by name, create a null member if it does not exist.
|
||||||
|
Value& operator[](const CppTL::ConstString& key);
|
||||||
|
/// Access an object value by name, returns null if there is no member with
|
||||||
|
/// that name.
|
||||||
|
const Value& operator[](const CppTL::ConstString& key) const;
|
||||||
|
#endif
|
||||||
|
/// Return the member named key if it exist, defaultValue otherwise.
|
||||||
|
/// \note deep copy
|
||||||
|
Value get(const char* key, const Value& defaultValue) const;
|
||||||
|
/// Return the member named key if it exist, defaultValue otherwise.
|
||||||
|
/// \note deep copy
|
||||||
|
/// \note key may contain embedded nulls.
|
||||||
|
Value get(const char* begin, const char* end, const Value& defaultValue) const;
|
||||||
|
/// Return the member named key if it exist, defaultValue otherwise.
|
||||||
|
/// \note deep copy
|
||||||
|
/// \param key may contain embedded nulls.
|
||||||
|
Value get(const JSONCPP_STRING& key, const Value& defaultValue) const;
|
||||||
|
#ifdef JSON_USE_CPPTL
|
||||||
|
/// Return the member named key if it exist, defaultValue otherwise.
|
||||||
|
/// \note deep copy
|
||||||
|
Value get(const CppTL::ConstString& key, const Value& defaultValue) const;
|
||||||
|
#endif
|
||||||
|
/// Most general and efficient version of isMember()const, get()const,
|
||||||
|
/// and operator[]const
|
||||||
|
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
|
||||||
|
Value const* find(char const* begin, char const* end) const;
|
||||||
|
/// Most general and efficient version of object-mutators.
|
||||||
|
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
|
||||||
|
/// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
|
||||||
|
Value const* demand(char const* begin, char const* end);
|
||||||
|
/// \brief Remove and return the named member.
|
||||||
|
///
|
||||||
|
/// Do nothing if it did not exist.
|
||||||
|
/// \return the removed Value, or null.
|
||||||
|
/// \pre type() is objectValue or nullValue
|
||||||
|
/// \post type() is unchanged
|
||||||
|
/// \deprecated
|
||||||
|
Value removeMember(const char* key);
|
||||||
|
/// Same as removeMember(const char*)
|
||||||
|
/// \param key may contain embedded nulls.
|
||||||
|
/// \deprecated
|
||||||
|
Value removeMember(const JSONCPP_STRING& key);
|
||||||
|
/// Same as removeMember(const char* begin, const char* end, Value* removed),
|
||||||
|
/// but 'key' is null-terminated.
|
||||||
|
bool removeMember(const char* key, Value* removed);
|
||||||
|
/** \brief Remove the named map member.
|
||||||
|
|
||||||
|
Update 'removed' iff removed.
|
||||||
|
\param key may contain embedded nulls.
|
||||||
|
\return true iff removed (no exceptions)
|
||||||
|
*/
|
||||||
|
bool removeMember(JSONCPP_STRING const& key, Value* removed);
|
||||||
|
/// Same as removeMember(JSONCPP_STRING const& key, Value* removed)
|
||||||
|
bool removeMember(const char* begin, const char* end, Value* removed);
|
||||||
|
/** \brief Remove the indexed array element.
|
||||||
|
|
||||||
|
O(n) expensive operations.
|
||||||
|
Update 'removed' iff removed.
|
||||||
|
\return true iff removed (no exceptions)
|
||||||
|
*/
|
||||||
|
bool removeIndex(ArrayIndex i, Value* removed);
|
||||||
|
|
||||||
|
/// Return true if the object has a member named key.
|
||||||
|
/// \note 'key' must be null-terminated.
|
||||||
|
bool isMember(const char* key) const;
|
||||||
|
/// Return true if the object has a member named key.
|
||||||
|
/// \param key may contain embedded nulls.
|
||||||
|
bool isMember(const JSONCPP_STRING& key) const;
|
||||||
|
/// Same as isMember(JSONCPP_STRING const& key)const
|
||||||
|
bool isMember(const char* begin, const char* end) const;
|
||||||
|
#ifdef JSON_USE_CPPTL
|
||||||
|
/// Return true if the object has a member named key.
|
||||||
|
bool isMember(const CppTL::ConstString& key) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \brief Return a list of the member names.
|
||||||
|
///
|
||||||
|
/// If null, return an empty list.
|
||||||
|
/// \pre type() is objectValue or nullValue
|
||||||
|
/// \post if type() was nullValue, it remains nullValue
|
||||||
|
Members getMemberNames() const;
|
||||||
|
|
||||||
|
//# ifdef JSON_USE_CPPTL
|
||||||
|
// EnumMemberNames enumMemberNames() const;
|
||||||
|
// EnumValues enumValues() const;
|
||||||
|
//# endif
|
||||||
|
|
||||||
|
/// \deprecated Always pass len.
|
||||||
|
JSONCPP_DEPRECATED("Use setComment(JSONCPP_STRING const&) instead.")
|
||||||
|
void setComment(const char* comment, CommentPlacement placement);
|
||||||
|
/// Comments must be //... or /* ... */
|
||||||
|
void setComment(const char* comment, size_t len, CommentPlacement placement);
|
||||||
|
/// Comments must be //... or /* ... */
|
||||||
|
void setComment(const JSONCPP_STRING& comment, CommentPlacement placement);
|
||||||
|
bool hasComment(CommentPlacement placement) const;
|
||||||
|
/// Include delimiters and embedded newlines.
|
||||||
|
JSONCPP_STRING getComment(CommentPlacement placement) const;
|
||||||
|
|
||||||
|
JSONCPP_STRING toStyledString() const;
|
||||||
|
|
||||||
|
const_iterator begin() const;
|
||||||
|
const_iterator end() const;
|
||||||
|
|
||||||
|
iterator begin();
|
||||||
|
iterator end();
|
||||||
|
|
||||||
|
// Accessors for the [start, limit) range of bytes within the JSON text from
|
||||||
|
// which this value was parsed, if any.
|
||||||
|
void setOffsetStart(ptrdiff_t start);
|
||||||
|
void setOffsetLimit(ptrdiff_t limit);
|
||||||
|
ptrdiff_t getOffsetStart() const;
|
||||||
|
ptrdiff_t getOffsetLimit() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initBasic(ValueType type, bool allocated = false);
|
||||||
|
|
||||||
|
Value& resolveReference(const char* key);
|
||||||
|
Value& resolveReference(const char* key, const char* end);
|
||||||
|
|
||||||
|
struct CommentInfo {
|
||||||
|
CommentInfo();
|
||||||
|
~CommentInfo();
|
||||||
|
|
||||||
|
void setComment(const char* text, size_t len);
|
||||||
|
|
||||||
|
char* comment_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// struct MemberNamesTransform
|
||||||
|
//{
|
||||||
|
// typedef const char *result_type;
|
||||||
|
// const char *operator()( const CZString &name ) const
|
||||||
|
// {
|
||||||
|
// return name.c_str();
|
||||||
|
// }
|
||||||
|
//};
|
||||||
|
|
||||||
|
union ValueHolder {
|
||||||
|
LargestInt int_;
|
||||||
|
LargestUInt uint_;
|
||||||
|
double real_;
|
||||||
|
bool bool_;
|
||||||
|
char* string_; // actually ptr to unsigned, followed by str, unless !allocated_
|
||||||
|
ObjectValues* map_;
|
||||||
|
} value_;
|
||||||
|
ValueType type_ : 8;
|
||||||
|
unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is useless.
|
||||||
|
// If not allocated_, string_ must be null-terminated.
|
||||||
|
CommentInfo* comments_;
|
||||||
|
|
||||||
|
// [start, limit) byte offsets in the source JSON text from which this Value
|
||||||
|
// was extracted.
|
||||||
|
ptrdiff_t start_;
|
||||||
|
ptrdiff_t limit_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Experimental and untested: represents an element of the "path" to
|
||||||
|
* access a node.
|
||||||
|
*/
|
||||||
|
class JSON_API PathArgument {
|
||||||
|
public:
|
||||||
|
friend class Path;
|
||||||
|
|
||||||
|
PathArgument();
|
||||||
|
PathArgument(ArrayIndex index);
|
||||||
|
PathArgument(const char* key);
|
||||||
|
PathArgument(const JSONCPP_STRING& key);
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum Kind {
|
||||||
|
kindNone = 0,
|
||||||
|
kindIndex,
|
||||||
|
kindKey
|
||||||
|
};
|
||||||
|
JSONCPP_STRING key_;
|
||||||
|
ArrayIndex index_;
|
||||||
|
Kind kind_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Experimental and untested: represents a "path" to access a node.
|
||||||
|
*
|
||||||
|
* Syntax:
|
||||||
|
* - "." => root node
|
||||||
|
* - ".[n]" => elements at index 'n' of root node (an array value)
|
||||||
|
* - ".name" => member named 'name' of root node (an object value)
|
||||||
|
* - ".name1.name2.name3"
|
||||||
|
* - ".[0][1][2].name1[3]"
|
||||||
|
* - ".%" => member name is provided as parameter
|
||||||
|
* - ".[%]" => index is provied as parameter
|
||||||
|
*/
|
||||||
|
class JSON_API Path {
|
||||||
|
public:
|
||||||
|
Path(const JSONCPP_STRING& path,
|
||||||
|
const PathArgument& a1 = PathArgument(),
|
||||||
|
const PathArgument& a2 = PathArgument(),
|
||||||
|
const PathArgument& a3 = PathArgument(),
|
||||||
|
const PathArgument& a4 = PathArgument(),
|
||||||
|
const PathArgument& a5 = PathArgument());
|
||||||
|
|
||||||
|
const Value& resolve(const Value& root) const;
|
||||||
|
Value resolve(const Value& root, const Value& defaultValue) const;
|
||||||
|
/// Creates the "path" to access the specified node and returns a reference on
|
||||||
|
/// the node.
|
||||||
|
Value& make(Value& root) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::vector<const PathArgument*> InArgs;
|
||||||
|
typedef std::vector<PathArgument> Args;
|
||||||
|
|
||||||
|
void makePath(const JSONCPP_STRING& path, const InArgs& in);
|
||||||
|
void addPathInArg(const JSONCPP_STRING& path,
|
||||||
|
const InArgs& in,
|
||||||
|
InArgs::const_iterator& itInArg,
|
||||||
|
PathArgument::Kind kind);
|
||||||
|
void invalidPath(const JSONCPP_STRING& path, int location);
|
||||||
|
|
||||||
|
Args args_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief base class for Value iterators.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class JSON_API ValueIteratorBase {
|
||||||
|
public:
|
||||||
|
typedef std::bidirectional_iterator_tag iterator_category;
|
||||||
|
typedef unsigned int size_t;
|
||||||
|
typedef int difference_type;
|
||||||
|
typedef ValueIteratorBase SelfType;
|
||||||
|
|
||||||
|
bool operator==(const SelfType& other) const { return isEqual(other); }
|
||||||
|
|
||||||
|
bool operator!=(const SelfType& other) const { return !isEqual(other); }
|
||||||
|
|
||||||
|
difference_type operator-(const SelfType& other) const {
|
||||||
|
return other.computeDistance(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return either the index or the member name of the referenced value as a
|
||||||
|
/// Value.
|
||||||
|
Value key() const;
|
||||||
|
|
||||||
|
/// Return the index of the referenced Value, or -1 if it is not an arrayValue.
|
||||||
|
UInt index() const;
|
||||||
|
|
||||||
|
/// Return the member name of the referenced Value, or "" if it is not an
|
||||||
|
/// objectValue.
|
||||||
|
/// \note Avoid `c_str()` on result, as embedded zeroes are possible.
|
||||||
|
JSONCPP_STRING name() const;
|
||||||
|
|
||||||
|
/// Return the member name of the referenced Value. "" if it is not an
|
||||||
|
/// objectValue.
|
||||||
|
/// \deprecated This cannot be used for UTF-8 strings, since there can be embedded nulls.
|
||||||
|
JSONCPP_DEPRECATED("Use `key = name();` instead.")
|
||||||
|
char const* memberName() const;
|
||||||
|
/// Return the member name of the referenced Value, or NULL if it is not an
|
||||||
|
/// objectValue.
|
||||||
|
/// \note Better version than memberName(). Allows embedded nulls.
|
||||||
|
char const* memberName(char const** end) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Value& deref() const;
|
||||||
|
|
||||||
|
void increment();
|
||||||
|
|
||||||
|
void decrement();
|
||||||
|
|
||||||
|
difference_type computeDistance(const SelfType& other) const;
|
||||||
|
|
||||||
|
bool isEqual(const SelfType& other) const;
|
||||||
|
|
||||||
|
void copy(const SelfType& other);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Value::ObjectValues::iterator current_;
|
||||||
|
// Indicates that iterator is for a null value.
|
||||||
|
bool isNull_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// For some reason, BORLAND needs these at the end, rather
|
||||||
|
// than earlier. No idea why.
|
||||||
|
ValueIteratorBase();
|
||||||
|
explicit ValueIteratorBase(const Value::ObjectValues::iterator& current);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief const iterator for object and array value.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class JSON_API ValueConstIterator : public ValueIteratorBase {
|
||||||
|
friend class Value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef const Value value_type;
|
||||||
|
//typedef unsigned int size_t;
|
||||||
|
//typedef int difference_type;
|
||||||
|
typedef const Value& reference;
|
||||||
|
typedef const Value* pointer;
|
||||||
|
typedef ValueConstIterator SelfType;
|
||||||
|
|
||||||
|
ValueConstIterator();
|
||||||
|
ValueConstIterator(ValueIterator const& other);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*! \internal Use by Value to create an iterator.
|
||||||
|
*/
|
||||||
|
explicit ValueConstIterator(const Value::ObjectValues::iterator& current);
|
||||||
|
public:
|
||||||
|
SelfType& operator=(const ValueIteratorBase& other);
|
||||||
|
|
||||||
|
SelfType operator++(int) {
|
||||||
|
SelfType temp(*this);
|
||||||
|
++*this;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelfType operator--(int) {
|
||||||
|
SelfType temp(*this);
|
||||||
|
--*this;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelfType& operator--() {
|
||||||
|
decrement();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelfType& operator++() {
|
||||||
|
increment();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
reference operator*() const { return deref(); }
|
||||||
|
|
||||||
|
pointer operator->() const { return &deref(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Iterator for object and array value.
|
||||||
|
*/
|
||||||
|
class JSON_API ValueIterator : public ValueIteratorBase {
|
||||||
|
friend class Value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef Value value_type;
|
||||||
|
typedef unsigned int size_t;
|
||||||
|
typedef int difference_type;
|
||||||
|
typedef Value& reference;
|
||||||
|
typedef Value* pointer;
|
||||||
|
typedef ValueIterator SelfType;
|
||||||
|
|
||||||
|
ValueIterator();
|
||||||
|
explicit ValueIterator(const ValueConstIterator& other);
|
||||||
|
ValueIterator(const ValueIterator& other);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*! \internal Use by Value to create an iterator.
|
||||||
|
*/
|
||||||
|
explicit ValueIterator(const Value::ObjectValues::iterator& current);
|
||||||
|
public:
|
||||||
|
SelfType& operator=(const SelfType& other);
|
||||||
|
|
||||||
|
SelfType operator++(int) {
|
||||||
|
SelfType temp(*this);
|
||||||
|
++*this;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelfType operator--(int) {
|
||||||
|
SelfType temp(*this);
|
||||||
|
--*this;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelfType& operator--() {
|
||||||
|
decrement();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelfType& operator++() {
|
||||||
|
increment();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
reference operator*() const { return deref(); }
|
||||||
|
|
||||||
|
pointer operator->() const { return &deref(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Json
|
||||||
|
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
/// Specialize std::swap() for Json::Value.
|
||||||
|
template<>
|
||||||
|
inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
|
#endif // CPPTL_JSON_H_INCLUDED
|
||||||
20
extern/jsoncpp/include/json/version.h
vendored
Normal file
20
extern/jsoncpp/include/json/version.h
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// DO NOT EDIT. This file (and "version") is generated by CMake.
|
||||||
|
// Run CMake configure step to update it.
|
||||||
|
#ifndef JSON_VERSION_H_INCLUDED
|
||||||
|
# define JSON_VERSION_H_INCLUDED
|
||||||
|
|
||||||
|
# define JSONCPP_VERSION_STRING "1.8.1"
|
||||||
|
# define JSONCPP_VERSION_MAJOR 1
|
||||||
|
# define JSONCPP_VERSION_MINOR 8
|
||||||
|
# define JSONCPP_VERSION_PATCH 1
|
||||||
|
# define JSONCPP_VERSION_QUALIFIER
|
||||||
|
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
|
||||||
|
|
||||||
|
#ifdef JSONCPP_USING_SECURE_MEMORY
|
||||||
|
#undef JSONCPP_USING_SECURE_MEMORY
|
||||||
|
#endif
|
||||||
|
#define JSONCPP_USING_SECURE_MEMORY 0
|
||||||
|
// If non-zero, the library zeroes any memory that it has allocated before
|
||||||
|
// it frees its memory.
|
||||||
|
|
||||||
|
#endif // JSON_VERSION_H_INCLUDED
|
||||||
335
extern/jsoncpp/include/json/writer.h
vendored
Normal file
335
extern/jsoncpp/include/json/writer.h
vendored
Normal file
@@ -0,0 +1,335 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef JSON_WRITER_H_INCLUDED
|
||||||
|
#define JSON_WRITER_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include "value.h"
|
||||||
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
|
||||||
|
// be used by...
|
||||||
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251)
|
||||||
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
|
#pragma pack(push, 8)
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
|
||||||
|
class Value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
\code
|
||||||
|
using namespace Json;
|
||||||
|
void writeToStdout(StreamWriter::Factory const& factory, Value const& value) {
|
||||||
|
std::unique_ptr<StreamWriter> const writer(
|
||||||
|
factory.newStreamWriter());
|
||||||
|
writer->write(value, &std::cout);
|
||||||
|
std::cout << std::endl; // add lf and flush
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
*/
|
||||||
|
class JSON_API StreamWriter {
|
||||||
|
protected:
|
||||||
|
JSONCPP_OSTREAM* sout_; // not owned; will not delete
|
||||||
|
public:
|
||||||
|
StreamWriter();
|
||||||
|
virtual ~StreamWriter();
|
||||||
|
/** Write Value into document as configured in sub-class.
|
||||||
|
Do not take ownership of sout, but maintain a reference during function.
|
||||||
|
\pre sout != NULL
|
||||||
|
\return zero on success (For now, we always return zero, so check the stream instead.)
|
||||||
|
\throw std::exception possibly, depending on configuration
|
||||||
|
*/
|
||||||
|
virtual int write(Value const& root, JSONCPP_OSTREAM* sout) = 0;
|
||||||
|
|
||||||
|
/** \brief A simple abstract factory.
|
||||||
|
*/
|
||||||
|
class JSON_API Factory {
|
||||||
|
public:
|
||||||
|
virtual ~Factory();
|
||||||
|
/** \brief Allocate a CharReader via operator new().
|
||||||
|
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||||
|
*/
|
||||||
|
virtual StreamWriter* newStreamWriter() const = 0;
|
||||||
|
}; // Factory
|
||||||
|
}; // StreamWriter
|
||||||
|
|
||||||
|
/** \brief Write into stringstream, then return string, for convenience.
|
||||||
|
* A StreamWriter will be created from the factory, used, and then deleted.
|
||||||
|
*/
|
||||||
|
JSONCPP_STRING JSON_API writeString(StreamWriter::Factory const& factory, Value const& root);
|
||||||
|
|
||||||
|
|
||||||
|
/** \brief Build a StreamWriter implementation.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
\code
|
||||||
|
using namespace Json;
|
||||||
|
Value value = ...;
|
||||||
|
StreamWriterBuilder builder;
|
||||||
|
builder["commentStyle"] = "None";
|
||||||
|
builder["indentation"] = " "; // or whatever you like
|
||||||
|
std::unique_ptr<Json::StreamWriter> writer(
|
||||||
|
builder.newStreamWriter());
|
||||||
|
writer->write(value, &std::cout);
|
||||||
|
std::cout << std::endl; // add lf and flush
|
||||||
|
\endcode
|
||||||
|
*/
|
||||||
|
class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
|
||||||
|
public:
|
||||||
|
// Note: We use a Json::Value so that we can add data-members to this class
|
||||||
|
// without a major version bump.
|
||||||
|
/** Configuration of this builder.
|
||||||
|
Available settings (case-sensitive):
|
||||||
|
- "commentStyle": "None" or "All"
|
||||||
|
- "indentation": "<anything>"
|
||||||
|
- "enableYAMLCompatibility": false or true
|
||||||
|
- slightly change the whitespace around colons
|
||||||
|
- "dropNullPlaceholders": false or true
|
||||||
|
- Drop the "null" string from the writer's output for nullValues.
|
||||||
|
Strictly speaking, this is not valid JSON. But when the output is being
|
||||||
|
fed to a browser's Javascript, it makes for smaller output and the
|
||||||
|
browser can handle the output just fine.
|
||||||
|
- "useSpecialFloats": false or true
|
||||||
|
- If true, outputs non-finite floating point values in the following way:
|
||||||
|
NaN values as "NaN", positive infinity as "Infinity", and negative infinity
|
||||||
|
as "-Infinity".
|
||||||
|
|
||||||
|
You can examine 'settings_` yourself
|
||||||
|
to see the defaults. You can also write and read them just like any
|
||||||
|
JSON Value.
|
||||||
|
\sa setDefaults()
|
||||||
|
*/
|
||||||
|
Json::Value settings_;
|
||||||
|
|
||||||
|
StreamWriterBuilder();
|
||||||
|
~StreamWriterBuilder() JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||||
|
*/
|
||||||
|
StreamWriter* newStreamWriter() const JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
|
/** \return true if 'settings' are legal and consistent;
|
||||||
|
* otherwise, indicate bad settings via 'invalid'.
|
||||||
|
*/
|
||||||
|
bool validate(Json::Value* invalid) const;
|
||||||
|
/** A simple way to update a specific setting.
|
||||||
|
*/
|
||||||
|
Value& operator[](JSONCPP_STRING key);
|
||||||
|
|
||||||
|
/** Called by ctor, but you can use this to reset settings_.
|
||||||
|
* \pre 'settings' != NULL (but Json::null is fine)
|
||||||
|
* \remark Defaults:
|
||||||
|
* \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults
|
||||||
|
*/
|
||||||
|
static void setDefaults(Json::Value* settings);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Abstract class for writers.
|
||||||
|
* \deprecated Use StreamWriter. (And really, this is an implementation detail.)
|
||||||
|
*/
|
||||||
|
class JSON_API Writer {
|
||||||
|
public:
|
||||||
|
virtual ~Writer();
|
||||||
|
|
||||||
|
virtual JSONCPP_STRING write(const Value& root) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
|
||||||
|
*without formatting (not human friendly).
|
||||||
|
*
|
||||||
|
* The JSON document is written in a single line. It is not intended for 'human'
|
||||||
|
*consumption,
|
||||||
|
* but may be usefull to support feature such as RPC where bandwith is limited.
|
||||||
|
* \sa Reader, Value
|
||||||
|
* \deprecated Use StreamWriterBuilder.
|
||||||
|
*/
|
||||||
|
class JSON_API FastWriter : public Writer {
|
||||||
|
|
||||||
|
public:
|
||||||
|
FastWriter();
|
||||||
|
~FastWriter() JSONCPP_OVERRIDE {}
|
||||||
|
|
||||||
|
void enableYAMLCompatibility();
|
||||||
|
|
||||||
|
/** \brief Drop the "null" string from the writer's output for nullValues.
|
||||||
|
* Strictly speaking, this is not valid JSON. But when the output is being
|
||||||
|
* fed to a browser's Javascript, it makes for smaller output and the
|
||||||
|
* browser can handle the output just fine.
|
||||||
|
*/
|
||||||
|
void dropNullPlaceholders();
|
||||||
|
|
||||||
|
void omitEndingLineFeed();
|
||||||
|
|
||||||
|
public: // overridden from Writer
|
||||||
|
JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void writeValue(const Value& value);
|
||||||
|
|
||||||
|
JSONCPP_STRING document_;
|
||||||
|
bool yamlCompatiblityEnabled_;
|
||||||
|
bool dropNullPlaceholders_;
|
||||||
|
bool omitEndingLineFeed_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
|
||||||
|
*human friendly way.
|
||||||
|
*
|
||||||
|
* The rules for line break and indent are as follow:
|
||||||
|
* - Object value:
|
||||||
|
* - if empty then print {} without indent and line break
|
||||||
|
* - if not empty the print '{', line break & indent, print one value per
|
||||||
|
*line
|
||||||
|
* and then unindent and line break and print '}'.
|
||||||
|
* - Array value:
|
||||||
|
* - if empty then print [] without indent and line break
|
||||||
|
* - if the array contains no object value, empty array or some other value
|
||||||
|
*types,
|
||||||
|
* and all the values fit on one lines, then print the array on a single
|
||||||
|
*line.
|
||||||
|
* - otherwise, it the values do not fit on one line, or the array contains
|
||||||
|
* object or non empty array, then print one value per line.
|
||||||
|
*
|
||||||
|
* If the Value have comments then they are outputed according to their
|
||||||
|
*#CommentPlacement.
|
||||||
|
*
|
||||||
|
* \sa Reader, Value, Value::setComment()
|
||||||
|
* \deprecated Use StreamWriterBuilder.
|
||||||
|
*/
|
||||||
|
class JSON_API StyledWriter : public Writer {
|
||||||
|
public:
|
||||||
|
StyledWriter();
|
||||||
|
~StyledWriter() JSONCPP_OVERRIDE {}
|
||||||
|
|
||||||
|
public: // overridden from Writer
|
||||||
|
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||||
|
* \param root Value to serialize.
|
||||||
|
* \return String containing the JSON document that represents the root value.
|
||||||
|
*/
|
||||||
|
JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void writeValue(const Value& value);
|
||||||
|
void writeArrayValue(const Value& value);
|
||||||
|
bool isMultineArray(const Value& value);
|
||||||
|
void pushValue(const JSONCPP_STRING& value);
|
||||||
|
void writeIndent();
|
||||||
|
void writeWithIndent(const JSONCPP_STRING& value);
|
||||||
|
void indent();
|
||||||
|
void unindent();
|
||||||
|
void writeCommentBeforeValue(const Value& root);
|
||||||
|
void writeCommentAfterValueOnSameLine(const Value& root);
|
||||||
|
bool hasCommentForValue(const Value& value);
|
||||||
|
static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text);
|
||||||
|
|
||||||
|
typedef std::vector<JSONCPP_STRING> ChildValues;
|
||||||
|
|
||||||
|
ChildValues childValues_;
|
||||||
|
JSONCPP_STRING document_;
|
||||||
|
JSONCPP_STRING indentString_;
|
||||||
|
unsigned int rightMargin_;
|
||||||
|
unsigned int indentSize_;
|
||||||
|
bool addChildValues_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
|
||||||
|
human friendly way,
|
||||||
|
to a stream rather than to a string.
|
||||||
|
*
|
||||||
|
* The rules for line break and indent are as follow:
|
||||||
|
* - Object value:
|
||||||
|
* - if empty then print {} without indent and line break
|
||||||
|
* - if not empty the print '{', line break & indent, print one value per
|
||||||
|
line
|
||||||
|
* and then unindent and line break and print '}'.
|
||||||
|
* - Array value:
|
||||||
|
* - if empty then print [] without indent and line break
|
||||||
|
* - if the array contains no object value, empty array or some other value
|
||||||
|
types,
|
||||||
|
* and all the values fit on one lines, then print the array on a single
|
||||||
|
line.
|
||||||
|
* - otherwise, it the values do not fit on one line, or the array contains
|
||||||
|
* object or non empty array, then print one value per line.
|
||||||
|
*
|
||||||
|
* If the Value have comments then they are outputed according to their
|
||||||
|
#CommentPlacement.
|
||||||
|
*
|
||||||
|
* \param indentation Each level will be indented by this amount extra.
|
||||||
|
* \sa Reader, Value, Value::setComment()
|
||||||
|
* \deprecated Use StreamWriterBuilder.
|
||||||
|
*/
|
||||||
|
class JSON_API StyledStreamWriter {
|
||||||
|
public:
|
||||||
|
StyledStreamWriter(JSONCPP_STRING indentation = "\t");
|
||||||
|
~StyledStreamWriter() {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||||
|
* \param out Stream to write to. (Can be ostringstream, e.g.)
|
||||||
|
* \param root Value to serialize.
|
||||||
|
* \note There is no point in deriving from Writer, since write() should not
|
||||||
|
* return a value.
|
||||||
|
*/
|
||||||
|
void write(JSONCPP_OSTREAM& out, const Value& root);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void writeValue(const Value& value);
|
||||||
|
void writeArrayValue(const Value& value);
|
||||||
|
bool isMultineArray(const Value& value);
|
||||||
|
void pushValue(const JSONCPP_STRING& value);
|
||||||
|
void writeIndent();
|
||||||
|
void writeWithIndent(const JSONCPP_STRING& value);
|
||||||
|
void indent();
|
||||||
|
void unindent();
|
||||||
|
void writeCommentBeforeValue(const Value& root);
|
||||||
|
void writeCommentAfterValueOnSameLine(const Value& root);
|
||||||
|
bool hasCommentForValue(const Value& value);
|
||||||
|
static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text);
|
||||||
|
|
||||||
|
typedef std::vector<JSONCPP_STRING> ChildValues;
|
||||||
|
|
||||||
|
ChildValues childValues_;
|
||||||
|
JSONCPP_OSTREAM* document_;
|
||||||
|
JSONCPP_STRING indentString_;
|
||||||
|
unsigned int rightMargin_;
|
||||||
|
JSONCPP_STRING indentation_;
|
||||||
|
bool addChildValues_ : 1;
|
||||||
|
bool indented_ : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(JSON_HAS_INT64)
|
||||||
|
JSONCPP_STRING JSON_API valueToString(Int value);
|
||||||
|
JSONCPP_STRING JSON_API valueToString(UInt value);
|
||||||
|
#endif // if defined(JSON_HAS_INT64)
|
||||||
|
JSONCPP_STRING JSON_API valueToString(LargestInt value);
|
||||||
|
JSONCPP_STRING JSON_API valueToString(LargestUInt value);
|
||||||
|
JSONCPP_STRING JSON_API valueToString(double value);
|
||||||
|
JSONCPP_STRING JSON_API valueToString(bool value);
|
||||||
|
JSONCPP_STRING JSON_API valueToQuotedString(const char* value);
|
||||||
|
|
||||||
|
/// \brief Output using the StyledStreamWriter.
|
||||||
|
/// \see Json::operator>>()
|
||||||
|
JSON_API JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM&, const Value& root);
|
||||||
|
|
||||||
|
} // namespace Json
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
|
#endif // JSON_WRITER_H_INCLUDED
|
||||||
80
extern/jsoncpp/src/CMakeLists.txt
vendored
Normal file
80
extern/jsoncpp/src/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
IF( CMAKE_COMPILER_IS_GNUCXX )
|
||||||
|
#Get compiler version.
|
||||||
|
EXECUTE_PROCESS( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
|
||||||
|
OUTPUT_VARIABLE GNUCXX_VERSION )
|
||||||
|
|
||||||
|
#-Werror=* was introduced -after- GCC 4.1.2
|
||||||
|
IF( GNUCXX_VERSION VERSION_GREATER 4.1.2 )
|
||||||
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=strict-aliasing")
|
||||||
|
ENDIF()
|
||||||
|
ENDIF( CMAKE_COMPILER_IS_GNUCXX )
|
||||||
|
|
||||||
|
INCLUDE(CheckIncludeFileCXX)
|
||||||
|
INCLUDE(CheckTypeSize)
|
||||||
|
INCLUDE(CheckStructHasMember)
|
||||||
|
INCLUDE(CheckCXXSymbolExists)
|
||||||
|
|
||||||
|
check_include_file_cxx(clocale HAVE_CLOCALE)
|
||||||
|
check_cxx_symbol_exists(localeconv clocale HAVE_LOCALECONV)
|
||||||
|
|
||||||
|
IF(CMAKE_VERSION VERSION_LESS 3.0.0)
|
||||||
|
# The "LANGUAGE CXX" parameter is not supported in CMake versions below 3,
|
||||||
|
# so the C compiler and header has to be used.
|
||||||
|
check_include_file(locale.h HAVE_LOCALE_H)
|
||||||
|
SET(CMAKE_EXTRA_INCLUDE_FILES locale.h)
|
||||||
|
check_type_size("struct lconv" LCONV_SIZE)
|
||||||
|
UNSET(CMAKE_EXTRA_INCLUDE_FILES)
|
||||||
|
check_struct_has_member("struct lconv" decimal_point locale.h HAVE_DECIMAL_POINT)
|
||||||
|
ELSE()
|
||||||
|
SET(CMAKE_EXTRA_INCLUDE_FILES clocale)
|
||||||
|
check_type_size(lconv LCONV_SIZE LANGUAGE CXX)
|
||||||
|
UNSET(CMAKE_EXTRA_INCLUDE_FILES)
|
||||||
|
check_struct_has_member(lconv decimal_point clocale HAVE_DECIMAL_POINT LANGUAGE CXX)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF(NOT (HAVE_CLOCALE AND HAVE_LCONV_SIZE AND HAVE_DECIMAL_POINT AND HAVE_LOCALECONV))
|
||||||
|
MESSAGE(WARNING "Locale functionality is not supported")
|
||||||
|
ADD_DEFINITIONS(-DJSONCPP_NO_LOCALE_SUPPORT)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
SET( JSONCPP_INCLUDE_DIR ../include )
|
||||||
|
|
||||||
|
SET( PUBLIC_HEADERS
|
||||||
|
${JSONCPP_INCLUDE_DIR}/json/config.h
|
||||||
|
${JSONCPP_INCLUDE_DIR}/json/forwards.h
|
||||||
|
${JSONCPP_INCLUDE_DIR}/json/features.h
|
||||||
|
${JSONCPP_INCLUDE_DIR}/json/value.h
|
||||||
|
${JSONCPP_INCLUDE_DIR}/json/reader.h
|
||||||
|
${JSONCPP_INCLUDE_DIR}/json/writer.h
|
||||||
|
${JSONCPP_INCLUDE_DIR}/json/assertions.h
|
||||||
|
${JSONCPP_INCLUDE_DIR}/json/version.h
|
||||||
|
)
|
||||||
|
|
||||||
|
SOURCE_GROUP( "Public API" FILES ${PUBLIC_HEADERS} )
|
||||||
|
|
||||||
|
SET(jsoncpp_sources
|
||||||
|
json_tool.h
|
||||||
|
json_reader.cpp
|
||||||
|
json_valueiterator.inl
|
||||||
|
json_value.cpp
|
||||||
|
json_writer.cpp
|
||||||
|
version.h.in
|
||||||
|
)
|
||||||
|
|
||||||
|
# Install instructions for this target
|
||||||
|
IF(JSONCPP_WITH_CMAKE_PACKAGE)
|
||||||
|
SET(INSTALL_EXPORT EXPORT jsoncpp)
|
||||||
|
ELSE(JSONCPP_WITH_CMAKE_PACKAGE)
|
||||||
|
SET(INSTALL_EXPORT)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
set(SRC
|
||||||
|
${PUBLIC_HEADERS}
|
||||||
|
${jsoncpp_sources}
|
||||||
|
)
|
||||||
|
|
||||||
|
set(INC
|
||||||
|
../include
|
||||||
|
)
|
||||||
|
|
||||||
|
blender_add_lib(jsoncpp_lib "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||||
2036
extern/jsoncpp/src/json_reader.cpp
vendored
Normal file
2036
extern/jsoncpp/src/json_reader.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
117
extern/jsoncpp/src/json_tool.h
vendored
Normal file
117
extern/jsoncpp/src/json_tool.h
vendored
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
||||||
|
#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
// Also support old flag NO_LOCALE_SUPPORT
|
||||||
|
#ifdef NO_LOCALE_SUPPORT
|
||||||
|
#define JSONCPP_NO_LOCALE_SUPPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef JSONCPP_NO_LOCALE_SUPPORT
|
||||||
|
#include <clocale>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* This header provides common string manipulation support, such as UTF-8,
|
||||||
|
* portable conversion from/to string...
|
||||||
|
*
|
||||||
|
* It is an internal header that must not be exposed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
static char getDecimalPoint() {
|
||||||
|
#ifdef JSONCPP_NO_LOCALE_SUPPORT
|
||||||
|
return '\0';
|
||||||
|
#else
|
||||||
|
struct lconv* lc = localeconv();
|
||||||
|
return lc ? *(lc->decimal_point) : '\0';
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts a unicode code-point to UTF-8.
|
||||||
|
static inline JSONCPP_STRING codePointToUTF8(unsigned int cp) {
|
||||||
|
JSONCPP_STRING result;
|
||||||
|
|
||||||
|
// based on description from http://en.wikipedia.org/wiki/UTF-8
|
||||||
|
|
||||||
|
if (cp <= 0x7f) {
|
||||||
|
result.resize(1);
|
||||||
|
result[0] = static_cast<char>(cp);
|
||||||
|
} else if (cp <= 0x7FF) {
|
||||||
|
result.resize(2);
|
||||||
|
result[1] = static_cast<char>(0x80 | (0x3f & cp));
|
||||||
|
result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
|
||||||
|
} else if (cp <= 0xFFFF) {
|
||||||
|
result.resize(3);
|
||||||
|
result[2] = static_cast<char>(0x80 | (0x3f & cp));
|
||||||
|
result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
|
||||||
|
result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
|
||||||
|
} else if (cp <= 0x10FFFF) {
|
||||||
|
result.resize(4);
|
||||||
|
result[3] = static_cast<char>(0x80 | (0x3f & cp));
|
||||||
|
result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
|
||||||
|
result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
|
||||||
|
result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if ch is a control character (in range [1,31]).
|
||||||
|
static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; }
|
||||||
|
|
||||||
|
enum {
|
||||||
|
/// Constant that specify the size of the buffer that must be passed to
|
||||||
|
/// uintToString.
|
||||||
|
uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1
|
||||||
|
};
|
||||||
|
|
||||||
|
// Defines a char buffer for use with uintToString().
|
||||||
|
typedef char UIntToStringBuffer[uintToStringBufferSize];
|
||||||
|
|
||||||
|
/** Converts an unsigned integer to string.
|
||||||
|
* @param value Unsigned interger to convert to string
|
||||||
|
* @param current Input/Output string buffer.
|
||||||
|
* Must have at least uintToStringBufferSize chars free.
|
||||||
|
*/
|
||||||
|
static inline void uintToString(LargestUInt value, char*& current) {
|
||||||
|
*--current = 0;
|
||||||
|
do {
|
||||||
|
*--current = static_cast<char>(value % 10U + static_cast<unsigned>('0'));
|
||||||
|
value /= 10;
|
||||||
|
} while (value != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Change ',' to '.' everywhere in buffer.
|
||||||
|
*
|
||||||
|
* We had a sophisticated way, but it did not work in WinCE.
|
||||||
|
* @see https://github.com/open-source-parsers/jsoncpp/pull/9
|
||||||
|
*/
|
||||||
|
static inline void fixNumericLocale(char* begin, char* end) {
|
||||||
|
while (begin < end) {
|
||||||
|
if (*begin == ',') {
|
||||||
|
*begin = '.';
|
||||||
|
}
|
||||||
|
++begin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void fixNumericLocaleInput(char* begin, char* end) {
|
||||||
|
char decimalPoint = getDecimalPoint();
|
||||||
|
if (decimalPoint != '\0' && decimalPoint != '.') {
|
||||||
|
while (begin < end) {
|
||||||
|
if (*begin == '.') {
|
||||||
|
*begin = decimalPoint;
|
||||||
|
}
|
||||||
|
++begin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Json {
|
||||||
|
|
||||||
|
#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
||||||
1665
extern/jsoncpp/src/json_value.cpp
vendored
Normal file
1665
extern/jsoncpp/src/json_value.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
167
extern/jsoncpp/src/json_valueiterator.inl
vendored
Normal file
167
extern/jsoncpp/src/json_valueiterator.inl
vendored
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
// included by json_value.cpp
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// class ValueIteratorBase
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ValueIteratorBase::ValueIteratorBase()
|
||||||
|
: current_(), isNull_(true) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueIteratorBase::ValueIteratorBase(
|
||||||
|
const Value::ObjectValues::iterator& current)
|
||||||
|
: current_(current), isNull_(false) {}
|
||||||
|
|
||||||
|
Value& ValueIteratorBase::deref() const {
|
||||||
|
return current_->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValueIteratorBase::increment() {
|
||||||
|
++current_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValueIteratorBase::decrement() {
|
||||||
|
--current_;
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueIteratorBase::difference_type
|
||||||
|
ValueIteratorBase::computeDistance(const SelfType& other) const {
|
||||||
|
#ifdef JSON_USE_CPPTL_SMALLMAP
|
||||||
|
return other.current_ - current_;
|
||||||
|
#else
|
||||||
|
// Iterator for null value are initialized using the default
|
||||||
|
// constructor, which initialize current_ to the default
|
||||||
|
// std::map::iterator. As begin() and end() are two instance
|
||||||
|
// of the default std::map::iterator, they can not be compared.
|
||||||
|
// To allow this, we handle this comparison specifically.
|
||||||
|
if (isNull_ && other.isNull_) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage of std::distance is not portable (does not compile with Sun Studio 12
|
||||||
|
// RogueWave STL,
|
||||||
|
// which is the one used by default).
|
||||||
|
// Using a portable hand-made version for non random iterator instead:
|
||||||
|
// return difference_type( std::distance( current_, other.current_ ) );
|
||||||
|
difference_type myDistance = 0;
|
||||||
|
for (Value::ObjectValues::iterator it = current_; it != other.current_;
|
||||||
|
++it) {
|
||||||
|
++myDistance;
|
||||||
|
}
|
||||||
|
return myDistance;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ValueIteratorBase::isEqual(const SelfType& other) const {
|
||||||
|
if (isNull_) {
|
||||||
|
return other.isNull_;
|
||||||
|
}
|
||||||
|
return current_ == other.current_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValueIteratorBase::copy(const SelfType& other) {
|
||||||
|
current_ = other.current_;
|
||||||
|
isNull_ = other.isNull_;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value ValueIteratorBase::key() const {
|
||||||
|
const Value::CZString czstring = (*current_).first;
|
||||||
|
if (czstring.data()) {
|
||||||
|
if (czstring.isStaticString())
|
||||||
|
return Value(StaticString(czstring.data()));
|
||||||
|
return Value(czstring.data(), czstring.data() + czstring.length());
|
||||||
|
}
|
||||||
|
return Value(czstring.index());
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt ValueIteratorBase::index() const {
|
||||||
|
const Value::CZString czstring = (*current_).first;
|
||||||
|
if (!czstring.data())
|
||||||
|
return czstring.index();
|
||||||
|
return Value::UInt(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONCPP_STRING ValueIteratorBase::name() const {
|
||||||
|
char const* keey;
|
||||||
|
char const* end;
|
||||||
|
keey = memberName(&end);
|
||||||
|
if (!keey) return JSONCPP_STRING();
|
||||||
|
return JSONCPP_STRING(keey, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
char const* ValueIteratorBase::memberName() const {
|
||||||
|
const char* cname = (*current_).first.data();
|
||||||
|
return cname ? cname : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
char const* ValueIteratorBase::memberName(char const** end) const {
|
||||||
|
const char* cname = (*current_).first.data();
|
||||||
|
if (!cname) {
|
||||||
|
*end = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*end = cname + (*current_).first.length();
|
||||||
|
return cname;
|
||||||
|
}
|
||||||
|
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// class ValueConstIterator
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ValueConstIterator::ValueConstIterator() {}
|
||||||
|
|
||||||
|
ValueConstIterator::ValueConstIterator(
|
||||||
|
const Value::ObjectValues::iterator& current)
|
||||||
|
: ValueIteratorBase(current) {}
|
||||||
|
|
||||||
|
ValueConstIterator::ValueConstIterator(ValueIterator const& other)
|
||||||
|
: ValueIteratorBase(other) {}
|
||||||
|
|
||||||
|
ValueConstIterator& ValueConstIterator::
|
||||||
|
operator=(const ValueIteratorBase& other) {
|
||||||
|
copy(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// class ValueIterator
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ValueIterator::ValueIterator() {}
|
||||||
|
|
||||||
|
ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
|
||||||
|
: ValueIteratorBase(current) {}
|
||||||
|
|
||||||
|
ValueIterator::ValueIterator(const ValueConstIterator& other)
|
||||||
|
: ValueIteratorBase(other) {
|
||||||
|
throwRuntimeError("ConstIterator to Iterator should never be allowed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueIterator::ValueIterator(const ValueIterator& other)
|
||||||
|
: ValueIteratorBase(other) {}
|
||||||
|
|
||||||
|
ValueIterator& ValueIterator::operator=(const SelfType& other) {
|
||||||
|
copy(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Json
|
||||||
1223
extern/jsoncpp/src/json_writer.cpp
vendored
Normal file
1223
extern/jsoncpp/src/json_writer.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
8
extern/jsoncpp/src/sconscript
vendored
Normal file
8
extern/jsoncpp/src/sconscript
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
Import( 'env buildLibrary' )
|
||||||
|
|
||||||
|
buildLibrary( env, Split( """
|
||||||
|
json_reader.cpp
|
||||||
|
json_value.cpp
|
||||||
|
json_writer.cpp
|
||||||
|
""" ),
|
||||||
|
'json' )
|
||||||
20
extern/jsoncpp/src/version.h.in
vendored
Normal file
20
extern/jsoncpp/src/version.h.in
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// DO NOT EDIT. This file (and "version") is generated by CMake.
|
||||||
|
// Run CMake configure step to update it.
|
||||||
|
#ifndef JSON_VERSION_H_INCLUDED
|
||||||
|
# define JSON_VERSION_H_INCLUDED
|
||||||
|
|
||||||
|
# define JSONCPP_VERSION_STRING "@JSONCPP_VERSION@"
|
||||||
|
# define JSONCPP_VERSION_MAJOR @JSONCPP_VERSION_MAJOR@
|
||||||
|
# define JSONCPP_VERSION_MINOR @JSONCPP_VERSION_MINOR@
|
||||||
|
# define JSONCPP_VERSION_PATCH @JSONCPP_VERSION_PATCH@
|
||||||
|
# define JSONCPP_VERSION_QUALIFIER
|
||||||
|
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
|
||||||
|
|
||||||
|
#ifdef JSONCPP_USING_SECURE_MEMORY
|
||||||
|
#undef JSONCPP_USING_SECURE_MEMORY
|
||||||
|
#endif
|
||||||
|
#define JSONCPP_USING_SECURE_MEMORY @JSONCPP_USE_SECURE_MEMORY@
|
||||||
|
// If non-zero, the library zeroes any memory that it has allocated before
|
||||||
|
// it frees its memory.
|
||||||
|
|
||||||
|
#endif // JSON_VERSION_H_INCLUDED
|
||||||
71
extern/openxr/CMakeLists.txt
vendored
Normal file
71
extern/openxr/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
# Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
# Author:
|
||||||
|
#
|
||||||
|
|
||||||
|
# Note: This is the top-level CMake file for the OpenXR project.
|
||||||
|
# It should contain only definitions that are applicable to the
|
||||||
|
# entire project and includes for the sub-directories.
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
project(OPENXR)
|
||||||
|
|
||||||
|
#find_package(PythonInterp 3)
|
||||||
|
|
||||||
|
# Enable IDE GUI folders. "Helper targets" that don't have interesting source code should set their FOLDER property to this
|
||||||
|
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
|
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMake predefined targets")
|
||||||
|
set(LOADER_FOLDER "Loader")
|
||||||
|
set(HELPER_FOLDER "Helpers")
|
||||||
|
set(CODEGEN_FOLDER "Generated")
|
||||||
|
set(TESTS_FOLDER "Tests")
|
||||||
|
set(API_LAYERS_FOLDER "Layers")
|
||||||
|
set(SAMPLES_FOLDER "Samples")
|
||||||
|
|
||||||
|
option(BUILD_FORCE_GENERATION "Force re-generation of files even in the presence of pre-generated copies, replacing those copies." OFF)
|
||||||
|
|
||||||
|
if(BUILD_FORCE_GENERATION AND NOT PYTHON_EXECUTABLE)
|
||||||
|
message(FATAL_ERROR "BUILD_FORCE_GENERATION requires Python")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(OPENXR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
add_subdirectory(include)
|
||||||
|
add_subdirectory(src)
|
||||||
|
|
||||||
|
# uninstall target
|
||||||
|
if(NOT TARGET uninstall)
|
||||||
|
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/cmake/cmake_uninstall.cmake.in"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||||
|
IMMEDIATE
|
||||||
|
@ONLY)
|
||||||
|
add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
||||||
|
set_target_properties(uninstall PROPERTIES FOLDER ${HELPER_FOLDER})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_program(BASH_COMMAND NAMES bash)
|
||||||
|
if(BASH_COMMAND AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/specification/Makefile")
|
||||||
|
option(BUILD_SPECIFICATION "Run './makeAllExts all' in the specification directory as part of the build - intended for one-step checking of spec changes" OFF)
|
||||||
|
if(BUILD_SPECIFICATION)
|
||||||
|
add_custom_target(spec-all ALL
|
||||||
|
${BASH_COMMAND} ./makeAllExts all
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/specification"
|
||||||
|
VERBATIM
|
||||||
|
COMMENT "Running './makeAllExts all' in the specification directory"
|
||||||
|
USES_TERMINAL)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE" DESTINATION share/doc/openxr)
|
||||||
202
extern/openxr/LICENSE
vendored
Normal file
202
extern/openxr/LICENSE
vendored
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
18
extern/openxr/include/CMakeLists.txt
vendored
Normal file
18
extern/openxr/include/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Copyright (c) 2017 The Khronos Group Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
# Author:
|
||||||
|
#
|
||||||
|
|
||||||
|
add_subdirectory(openxr)
|
||||||
94
extern/openxr/include/openxr/CMakeLists.txt
vendored
Normal file
94
extern/openxr/include/openxr/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
# Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
# Author:
|
||||||
|
#
|
||||||
|
|
||||||
|
# Copy the openxr_platform_defines.h file and place it in the binary (build) directory.
|
||||||
|
configure_file(openxr_platform_defines.h ${CMAKE_CURRENT_BINARY_DIR}/openxr_platform_defines.h COPYONLY)
|
||||||
|
|
||||||
|
# Generate OpenXR header files.
|
||||||
|
|
||||||
|
|
||||||
|
set(HEADERS
|
||||||
|
openxr.h
|
||||||
|
openxr_platform.h
|
||||||
|
openxr_reflection.h)
|
||||||
|
set(HAVE_PREGENERATED TRUE)
|
||||||
|
set(SOURCE_HEADERS)
|
||||||
|
foreach(output ${HEADERS})
|
||||||
|
list(APPEND SOURCE_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/${output})
|
||||||
|
if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${output})
|
||||||
|
set(HAVE_PREGENERATED FALSE)
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set(XR_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..)
|
||||||
|
if(HAVE_PREGENERATED AND NOT BUILD_FORCE_GENERATION)
|
||||||
|
add_custom_target(generate_openxr_header
|
||||||
|
COMMENT "Using found pre-generated OpenXR headers.")
|
||||||
|
|
||||||
|
set(INSTALL_HEADERS ${SOURCE_HEADERS})
|
||||||
|
else()
|
||||||
|
|
||||||
|
set(GENERATED_HEADERS)
|
||||||
|
set(OUTPUT_STAMPS)
|
||||||
|
# Copy the openxr_platform_defines.h file and place it in the binary (build) directory.
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/openxr_platform_defines.h
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/openxr_platform_defines.h
|
||||||
|
COPYONLY)
|
||||||
|
|
||||||
|
# Generate the header files and place it in the binary (build) directory.
|
||||||
|
foreach(output ${HEADERS})
|
||||||
|
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${output}
|
||||||
|
COMMAND ${PYTHON_EXECUTABLE} ${XR_ROOT}/specification/scripts/genxr.py
|
||||||
|
-registry ${XR_ROOT}/specification/registry/xr.xml
|
||||||
|
-o ${CMAKE_CURRENT_BINARY_DIR} ${output}
|
||||||
|
DEPENDS
|
||||||
|
${XR_ROOT}/specification/scripts/genxr.py
|
||||||
|
${XR_ROOT}/specification/scripts/cgenerator.py
|
||||||
|
${XR_ROOT}/specification/scripts/creflectiongenerator.py
|
||||||
|
${XR_ROOT}/specification/scripts/generator.py
|
||||||
|
${XR_ROOT}/specification/scripts/reg.py
|
||||||
|
${XR_ROOT}/specification/registry/xr.xml
|
||||||
|
COMMENT "Generating ${CMAKE_CURRENT_BINARY_DIR}/${output}"
|
||||||
|
)
|
||||||
|
list(APPEND GENERATED_HEADERS "${CMAKE_CURRENT_BINARY_DIR}/${output}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set_source_files_properties(
|
||||||
|
${GENERATED_HEADERS}
|
||||||
|
PROPERTIES GENERATED TRUE
|
||||||
|
)
|
||||||
|
|
||||||
|
set(INSTALL_HEADERS
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/openxr_platform_defines.h
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/openxr.h
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/openxr_platform.h)
|
||||||
|
|
||||||
|
|
||||||
|
# Define generate_openxr_header target to generate the OpenXR header files.
|
||||||
|
# Other targets that need the OpenXR headers should use generate_openxr_header as a dependency.
|
||||||
|
add_custom_target(generate_openxr_header
|
||||||
|
SOURCES ${XR_ROOT}/specification/registry/xr.xml
|
||||||
|
DEPENDS
|
||||||
|
${GENERATED_HEADERS}
|
||||||
|
${OUTPUT_STAMPS}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
set_target_properties(generate_openxr_header PROPERTIES FOLDER ${CODEGEN_FOLDER})
|
||||||
|
|
||||||
|
INSTALL(FILES ${INSTALL_HEADERS}
|
||||||
|
DESTINATION include/openxr
|
||||||
|
)
|
||||||
1538
extern/openxr/include/openxr/openxr.h
vendored
Normal file
1538
extern/openxr/include/openxr/openxr.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
383
extern/openxr/include/openxr/openxr_platform.h
vendored
Normal file
383
extern/openxr/include/openxr/openxr_platform.h
vendored
Normal file
@@ -0,0 +1,383 @@
|
|||||||
|
#ifndef OPENXR_PLATFORM_H_
|
||||||
|
#define OPENXR_PLATFORM_H_ 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
**
|
||||||
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
** you may not use this file except in compliance with the License.
|
||||||
|
** You may obtain a copy of the License at
|
||||||
|
**
|
||||||
|
** http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
**
|
||||||
|
** Unless required by applicable law or agreed to in writing, software
|
||||||
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
** See the License for the specific language governing permissions and
|
||||||
|
** limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
** This header is generated from the Khronos OpenXR XML API Registry.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "openxr.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_ANDROID
|
||||||
|
|
||||||
|
#define XR_KHR_android_thread_settings 1
|
||||||
|
#define XR_KHR_android_thread_settings_SPEC_VERSION 5
|
||||||
|
#define XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME "XR_KHR_android_thread_settings"
|
||||||
|
|
||||||
|
typedef enum XrAndroidThreadTypeKHR {
|
||||||
|
XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR = 1,
|
||||||
|
XR_ANDROID_THREAD_TYPE_APPLICATION_WORKER_KHR = 2,
|
||||||
|
XR_ANDROID_THREAD_TYPE_RENDERER_MAIN_KHR = 3,
|
||||||
|
XR_ANDROID_THREAD_TYPE_RENDERER_WORKER_KHR = 4,
|
||||||
|
XR_ANDROID_THREAD_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF
|
||||||
|
} XrAndroidThreadTypeKHR;
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrSetAndroidApplicationThreadKHR)(XrSession session, XrAndroidThreadTypeKHR threadType, uint32_t threadId);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrSetAndroidApplicationThreadKHR(
|
||||||
|
XrSession session,
|
||||||
|
XrAndroidThreadTypeKHR threadType,
|
||||||
|
uint32_t threadId);
|
||||||
|
#endif
|
||||||
|
#endif /* XR_USE_PLATFORM_ANDROID */
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_ANDROID
|
||||||
|
|
||||||
|
#define XR_KHR_android_surface_swapchain 1
|
||||||
|
#define XR_KHR_android_surface_swapchain_SPEC_VERSION 4
|
||||||
|
#define XR_KHR_ANDROID_SURFACE_SWAPCHAIN_EXTENSION_NAME "XR_KHR_android_surface_swapchain"
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrCreateSwapchainAndroidSurfaceKHR)(XrSession session, const XrSwapchainCreateInfo* info, XrSwapchain* swapchain, jobject* surface);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrCreateSwapchainAndroidSurfaceKHR(
|
||||||
|
XrSession session,
|
||||||
|
const XrSwapchainCreateInfo* info,
|
||||||
|
XrSwapchain* swapchain,
|
||||||
|
jobject* surface);
|
||||||
|
#endif
|
||||||
|
#endif /* XR_USE_PLATFORM_ANDROID */
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_ANDROID
|
||||||
|
|
||||||
|
#define XR_KHR_android_create_instance 1
|
||||||
|
#define XR_KHR_android_create_instance_SPEC_VERSION 3
|
||||||
|
#define XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME "XR_KHR_android_create_instance"
|
||||||
|
typedef struct XrInstanceCreateInfoAndroidKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
void* XR_MAY_ALIAS applicationVM;
|
||||||
|
void* XR_MAY_ALIAS applicationActivity;
|
||||||
|
} XrInstanceCreateInfoAndroidKHR;
|
||||||
|
|
||||||
|
#endif /* XR_USE_PLATFORM_ANDROID */
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
||||||
|
|
||||||
|
#define XR_KHR_vulkan_swapchain_format_list 1
|
||||||
|
#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"
|
||||||
|
typedef struct XrVulkanSwapchainFormatListCreateInfoKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
uint32_t viewFormatCount;
|
||||||
|
const VkFormat* viewFormats;
|
||||||
|
} XrVulkanSwapchainFormatListCreateInfoKHR;
|
||||||
|
|
||||||
|
#endif /* XR_USE_GRAPHICS_API_VULKAN */
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_OPENGL
|
||||||
|
|
||||||
|
#define XR_KHR_opengl_enable 1
|
||||||
|
#define XR_KHR_opengl_enable_SPEC_VERSION 7
|
||||||
|
#define XR_KHR_OPENGL_ENABLE_EXTENSION_NAME "XR_KHR_opengl_enable"
|
||||||
|
#ifdef XR_USE_PLATFORM_WIN32
|
||||||
|
typedef struct XrGraphicsBindingOpenGLWin32KHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
HDC hDC;
|
||||||
|
HGLRC hGLRC;
|
||||||
|
} XrGraphicsBindingOpenGLWin32KHR;
|
||||||
|
#endif // XR_USE_PLATFORM_WIN32
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_XLIB
|
||||||
|
typedef struct XrGraphicsBindingOpenGLXlibKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
Display* xDisplay;
|
||||||
|
uint32_t visualid;
|
||||||
|
GLXFBConfig glxFBConfig;
|
||||||
|
GLXDrawable glxDrawable;
|
||||||
|
GLXContext glxContext;
|
||||||
|
} XrGraphicsBindingOpenGLXlibKHR;
|
||||||
|
#endif // XR_USE_PLATFORM_XLIB
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_XCB
|
||||||
|
typedef struct XrGraphicsBindingOpenGLXcbKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
xcb_connection_t* connection;
|
||||||
|
uint32_t screenNumber;
|
||||||
|
xcb_glx_fbconfig_t fbconfigid;
|
||||||
|
xcb_visualid_t visualid;
|
||||||
|
xcb_glx_drawable_t glxDrawable;
|
||||||
|
xcb_glx_context_t glxContext;
|
||||||
|
} XrGraphicsBindingOpenGLXcbKHR;
|
||||||
|
#endif // XR_USE_PLATFORM_XCB
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_WAYLAND
|
||||||
|
typedef struct XrGraphicsBindingOpenGLWaylandKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
struct wl_display* display;
|
||||||
|
} XrGraphicsBindingOpenGLWaylandKHR;
|
||||||
|
#endif // XR_USE_PLATFORM_WAYLAND
|
||||||
|
|
||||||
|
typedef struct XrSwapchainImageOpenGLKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
uint32_t image;
|
||||||
|
} XrSwapchainImageOpenGLKHR;
|
||||||
|
|
||||||
|
typedef struct XrGraphicsRequirementsOpenGLKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
XrVersion minApiVersionSupported;
|
||||||
|
XrVersion maxApiVersionSupported;
|
||||||
|
} XrGraphicsRequirementsOpenGLKHR;
|
||||||
|
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetOpenGLGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsOpenGLKHR* graphicsRequirements);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLGraphicsRequirementsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrGraphicsRequirementsOpenGLKHR* graphicsRequirements);
|
||||||
|
#endif
|
||||||
|
#endif /* XR_USE_GRAPHICS_API_OPENGL */
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
|
||||||
|
|
||||||
|
#define XR_KHR_opengl_es_enable 1
|
||||||
|
#define XR_KHR_opengl_es_enable_SPEC_VERSION 6
|
||||||
|
#define XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME "XR_KHR_opengl_es_enable"
|
||||||
|
#ifdef XR_USE_PLATFORM_ANDROID
|
||||||
|
typedef struct XrGraphicsBindingOpenGLESAndroidKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
EGLDisplay display;
|
||||||
|
EGLConfig config;
|
||||||
|
EGLContext context;
|
||||||
|
} XrGraphicsBindingOpenGLESAndroidKHR;
|
||||||
|
#endif // XR_USE_PLATFORM_ANDROID
|
||||||
|
|
||||||
|
typedef struct XrSwapchainImageOpenGLESKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
uint32_t image;
|
||||||
|
} XrSwapchainImageOpenGLESKHR;
|
||||||
|
|
||||||
|
typedef struct XrGraphicsRequirementsOpenGLESKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
XrVersion minApiVersionSupported;
|
||||||
|
XrVersion maxApiVersionSupported;
|
||||||
|
} XrGraphicsRequirementsOpenGLESKHR;
|
||||||
|
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetOpenGLESGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLESGraphicsRequirementsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements);
|
||||||
|
#endif
|
||||||
|
#endif /* XR_USE_GRAPHICS_API_OPENGL_ES */
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
||||||
|
|
||||||
|
#define XR_KHR_vulkan_enable 1
|
||||||
|
#define XR_KHR_vulkan_enable_SPEC_VERSION 6
|
||||||
|
#define XR_KHR_VULKAN_ENABLE_EXTENSION_NAME "XR_KHR_vulkan_enable"
|
||||||
|
typedef struct XrGraphicsBindingVulkanKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
VkInstance instance;
|
||||||
|
VkPhysicalDevice physicalDevice;
|
||||||
|
VkDevice device;
|
||||||
|
uint32_t queueFamilyIndex;
|
||||||
|
uint32_t queueIndex;
|
||||||
|
} XrGraphicsBindingVulkanKHR;
|
||||||
|
|
||||||
|
typedef struct XrSwapchainImageVulkanKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
VkImage image;
|
||||||
|
} XrSwapchainImageVulkanKHR;
|
||||||
|
|
||||||
|
typedef struct XrGraphicsRequirementsVulkanKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
XrVersion minApiVersionSupported;
|
||||||
|
XrVersion maxApiVersionSupported;
|
||||||
|
} XrGraphicsRequirementsVulkanKHR;
|
||||||
|
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanInstanceExtensionsKHR)(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer);
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanDeviceExtensionsKHR)(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer);
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsDeviceKHR)(XrInstance instance, XrSystemId systemId, VkInstance vkInstance, VkPhysicalDevice* vkPhysicalDevice);
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanInstanceExtensionsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
uint32_t bufferCapacityInput,
|
||||||
|
uint32_t* bufferCountOutput,
|
||||||
|
char* buffer);
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanDeviceExtensionsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
uint32_t bufferCapacityInput,
|
||||||
|
uint32_t* bufferCountOutput,
|
||||||
|
char* buffer);
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsDeviceKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
VkInstance vkInstance,
|
||||||
|
VkPhysicalDevice* vkPhysicalDevice);
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsRequirementsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
|
||||||
|
#endif
|
||||||
|
#endif /* XR_USE_GRAPHICS_API_VULKAN */
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_D3D11
|
||||||
|
|
||||||
|
#define XR_KHR_D3D11_enable 1
|
||||||
|
#define XR_KHR_D3D11_enable_SPEC_VERSION 4
|
||||||
|
#define XR_KHR_D3D11_ENABLE_EXTENSION_NAME "XR_KHR_D3D11_enable"
|
||||||
|
typedef struct XrGraphicsBindingD3D11KHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
ID3D11Device* device;
|
||||||
|
} XrGraphicsBindingD3D11KHR;
|
||||||
|
|
||||||
|
typedef struct XrSwapchainImageD3D11KHR {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
ID3D11Texture2D* texture;
|
||||||
|
} XrSwapchainImageD3D11KHR;
|
||||||
|
|
||||||
|
typedef struct XrGraphicsRequirementsD3D11KHR {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
LUID adapterLuid;
|
||||||
|
D3D_FEATURE_LEVEL minFeatureLevel;
|
||||||
|
} XrGraphicsRequirementsD3D11KHR;
|
||||||
|
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetD3D11GraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D11KHR* graphicsRequirements);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D11GraphicsRequirementsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrGraphicsRequirementsD3D11KHR* graphicsRequirements);
|
||||||
|
#endif
|
||||||
|
#endif /* XR_USE_GRAPHICS_API_D3D11 */
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_D3D12
|
||||||
|
|
||||||
|
#define XR_KHR_D3D12_enable 1
|
||||||
|
#define XR_KHR_D3D12_enable_SPEC_VERSION 5
|
||||||
|
#define XR_KHR_D3D12_ENABLE_EXTENSION_NAME "XR_KHR_D3D12_enable"
|
||||||
|
typedef struct XrGraphicsBindingD3D12KHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
ID3D12Device* device;
|
||||||
|
ID3D12CommandQueue* queue;
|
||||||
|
} XrGraphicsBindingD3D12KHR;
|
||||||
|
|
||||||
|
typedef struct XrSwapchainImageD3D12KHR {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
ID3D12Resource* texture;
|
||||||
|
} XrSwapchainImageD3D12KHR;
|
||||||
|
|
||||||
|
typedef struct XrGraphicsRequirementsD3D12KHR {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
LUID adapterLuid;
|
||||||
|
D3D_FEATURE_LEVEL minFeatureLevel;
|
||||||
|
} XrGraphicsRequirementsD3D12KHR;
|
||||||
|
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetD3D12GraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D12KHR* graphicsRequirements);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D12GraphicsRequirementsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrGraphicsRequirementsD3D12KHR* graphicsRequirements);
|
||||||
|
#endif
|
||||||
|
#endif /* XR_USE_GRAPHICS_API_D3D12 */
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_WIN32
|
||||||
|
|
||||||
|
#define XR_KHR_win32_convert_performance_counter_time 1
|
||||||
|
#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"
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrConvertWin32PerformanceCounterToTimeKHR)(XrInstance instance, const LARGE_INTEGER* performanceCounter, XrTime* time);
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToWin32PerformanceCounterKHR)(XrInstance instance, XrTime time, LARGE_INTEGER* performanceCounter);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrConvertWin32PerformanceCounterToTimeKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
const LARGE_INTEGER* performanceCounter,
|
||||||
|
XrTime* time);
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToWin32PerformanceCounterKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrTime time,
|
||||||
|
LARGE_INTEGER* performanceCounter);
|
||||||
|
#endif
|
||||||
|
#endif /* XR_USE_PLATFORM_WIN32 */
|
||||||
|
|
||||||
|
#ifdef XR_USE_TIMESPEC
|
||||||
|
|
||||||
|
#define XR_KHR_convert_timespec_time 1
|
||||||
|
#define XR_KHR_convert_timespec_time_SPEC_VERSION 1
|
||||||
|
#define XR_KHR_CONVERT_TIMESPEC_TIME_EXTENSION_NAME "XR_KHR_convert_timespec_time"
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrConvertTimespecTimeToTimeKHR)(XrInstance instance, const struct timespec* timespecTime, XrTime* time);
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToTimespecTimeKHR)(XrInstance instance, XrTime time, struct timespec* timespecTime);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimespecTimeToTimeKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
const struct timespec* timespecTime,
|
||||||
|
XrTime* time);
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToTimespecTimeKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrTime time,
|
||||||
|
struct timespec* timespecTime);
|
||||||
|
#endif
|
||||||
|
#endif /* XR_USE_TIMESPEC */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
124
extern/openxr/include/openxr/openxr_platform_defines.h
vendored
Normal file
124
extern/openxr/include/openxr/openxr_platform_defines.h
vendored
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
** Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
**
|
||||||
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
** you may not use this file except in compliance with the License.
|
||||||
|
** You may obtain a copy of the License at
|
||||||
|
**
|
||||||
|
** http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
**
|
||||||
|
** Unless required by applicable law or agreed to in writing, software
|
||||||
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
** See the License for the specific language governing permissions and
|
||||||
|
** limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OPENXR_PLATFORM_DEFINES_H_
|
||||||
|
#define OPENXR_PLATFORM_DEFINES_H_ 1
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Platform-specific calling convention macros.
|
||||||
|
*
|
||||||
|
* Platforms should define these so that OpenXR clients call OpenXR functions
|
||||||
|
* with the same calling conventions that the OpenXR implementation expects.
|
||||||
|
*
|
||||||
|
* XRAPI_ATTR - Placed before the return type in function declarations.
|
||||||
|
* Useful for C++11 and GCC/Clang-style function attribute syntax.
|
||||||
|
* XRAPI_CALL - Placed after the return type in function declarations.
|
||||||
|
* Useful for MSVC-style calling convention syntax.
|
||||||
|
* XRAPI_PTR - Placed between the '(' and '*' in function pointer types.
|
||||||
|
*
|
||||||
|
* Function declaration: XRAPI_ATTR void XRAPI_CALL xrFunction(void);
|
||||||
|
* Function pointer type: typedef void (XRAPI_PTR *PFN_xrFunction)(void);
|
||||||
|
*/
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#ifdef XRAPI_DLL_EXPORT
|
||||||
|
#define XRAPI_ATTR __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define XRAPI_ATTR
|
||||||
|
#endif
|
||||||
|
// On Windows, functions use the stdcall convention
|
||||||
|
#define XRAPI_CALL __stdcall
|
||||||
|
#define XRAPI_PTR XRAPI_CALL
|
||||||
|
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
|
||||||
|
#error "API not supported for the 'armeabi' NDK ABI"
|
||||||
|
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
|
||||||
|
// On Android 32-bit ARM targets, functions use the "hardfloat"
|
||||||
|
// calling convention, i.e. float parameters are passed in registers. This
|
||||||
|
// is true even if the rest of the application passes floats on the stack,
|
||||||
|
// as it does by default when compiling for the armeabi-v7a NDK ABI.
|
||||||
|
#define XRAPI_ATTR __attribute__((pcs("aapcs-vfp")))
|
||||||
|
#define XRAPI_CALL
|
||||||
|
#define XRAPI_PTR XRAPI_ATTR
|
||||||
|
#else
|
||||||
|
// On other platforms, use the default calling convention
|
||||||
|
#define XRAPI_ATTR
|
||||||
|
#define XRAPI_CALL
|
||||||
|
#define XRAPI_PTR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#if !defined(XR_NO_STDINT_H)
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER < 1600)
|
||||||
|
typedef signed __int8 int8_t;
|
||||||
|
typedef unsigned __int8 uint8_t;
|
||||||
|
typedef signed __int16 int16_t;
|
||||||
|
typedef unsigned __int16 uint16_t;
|
||||||
|
typedef signed __int32 int32_t;
|
||||||
|
typedef unsigned __int32 uint32_t;
|
||||||
|
typedef signed __int64 int64_t;
|
||||||
|
typedef unsigned __int64 uint64_t;
|
||||||
|
#else
|
||||||
|
#include <stdint.h>
|
||||||
|
#endif
|
||||||
|
#endif // !defined( XR_NO_STDINT_H )
|
||||||
|
|
||||||
|
// XR_PTR_SIZE (in bytes)
|
||||||
|
#if (defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__))
|
||||||
|
#define XR_PTR_SIZE 8
|
||||||
|
#else
|
||||||
|
#define XR_PTR_SIZE 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Needed so we can use clang __has_feature portably.
|
||||||
|
#if !defined(XR_COMPILER_HAS_FEATURE)
|
||||||
|
#if defined(__clang__)
|
||||||
|
#define XR_COMPILER_HAS_FEATURE(x) __has_feature(x)
|
||||||
|
#else
|
||||||
|
#define XR_COMPILER_HAS_FEATURE(x) 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Identifies if the current compiler has C++11 support enabled.
|
||||||
|
// Does not by itself identify if any given C++11 feature is present.
|
||||||
|
#if !defined(XR_CPP11_ENABLED) && defined(__cplusplus)
|
||||||
|
#if defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||||
|
#define XR_CPP11_ENABLED 1
|
||||||
|
#elif defined(_MSC_VER) && (_MSC_VER >= 1600)
|
||||||
|
#define XR_CPP11_ENABLED 1
|
||||||
|
#elif (__cplusplus >= 201103L) // 201103 is the first C++11 version.
|
||||||
|
#define XR_CPP11_ENABLED 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Identifies if the current compiler supports C++11 nullptr.
|
||||||
|
#if !defined(XR_CPP_NULLPTR_SUPPORTED)
|
||||||
|
#if defined(XR_CPP11_ENABLED) && \
|
||||||
|
((defined(__clang__) && XR_COMPILER_HAS_FEATURE(cxx_nullptr)) || \
|
||||||
|
(defined(__GNUC__) && (((__GNUC__ * 1000) + __GNUC_MINOR__) >= 4006)) || \
|
||||||
|
(defined(_MSC_VER) && (_MSC_VER >= 1600)) || \
|
||||||
|
(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403)))
|
||||||
|
#define XR_CPP_NULLPTR_SUPPORTED 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
1004
extern/openxr/include/openxr/openxr_reflection.h
vendored
Normal file
1004
extern/openxr/include/openxr/openxr_reflection.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
194
extern/openxr/src/CMakeLists.txt
vendored
Normal file
194
extern/openxr/src/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
# Copyright (c) 2017 The Khronos Group Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
# Author:
|
||||||
|
#
|
||||||
|
|
||||||
|
# Entire project uses C++11
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
|
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
|
# All options defined here
|
||||||
|
option(BUILD_LOADER "Build loader" ON)
|
||||||
|
option(BUILD_LOADER_WITH_EXCEPTION_HANDLING "Enable exception handling in the loader. Leave this on unless your standard library is built to not throw." ON)
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
option(DYNAMIC_LOADER "Build the loader as a .dll library" OFF)
|
||||||
|
else()
|
||||||
|
option(DYNAMIC_LOADER "Build the loader as a .dll library" ON)
|
||||||
|
endif()
|
||||||
|
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/api_layers")
|
||||||
|
option(BUILD_API_LAYERS "Build API layers" ON)
|
||||||
|
endif()
|
||||||
|
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests")
|
||||||
|
option(BUILD_TESTS "Build tests" ON)
|
||||||
|
endif()
|
||||||
|
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/conformance")
|
||||||
|
option(BUILD_CONFORMANCE_TESTS "Build conformance tests" ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Several files use these compile-time OS switches
|
||||||
|
if(WIN32)
|
||||||
|
add_definitions(-DXR_OS_WINDOWS)
|
||||||
|
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
add_definitions(-DXR_OS_LINUX)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Determine the presentation backend for Linux systems.
|
||||||
|
# Use an include because the code is pretty big.
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
include(presentation)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Several files use these compile-time platform switches
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
add_definitions( -DXR_USE_PLATFORM_WIN32 )
|
||||||
|
elseif( PRESENTATION_BACKEND MATCHES "xlib" )
|
||||||
|
add_definitions( -DXR_USE_PLATFORM_XLIB )
|
||||||
|
elseif( PRESENTATION_BACKEND MATCHES "xcb" )
|
||||||
|
add_definitions( -DXR_USE_PLATFORM_XCB )
|
||||||
|
|
||||||
|
# TODO remove once conformance supports XCB
|
||||||
|
set(BUILD_CONFORMANCE_TESTS OFF)
|
||||||
|
elseif( PRESENTATION_BACKEND MATCHES "wayland" )
|
||||||
|
add_definitions( -DXR_USE_PLATFORM_WAYLAND )
|
||||||
|
|
||||||
|
# TODO remove once conformance supports Wayland
|
||||||
|
set(BUILD_CONFORMANCE_TESTS OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Enable graphics API available to the build.
|
||||||
|
if (NOT CMAKE_VERSION VERSION_LESS 3.7.0)
|
||||||
|
# Find the Vulkan headers
|
||||||
|
find_package(VulkanHeaders)
|
||||||
|
if (VulkanHeaders_FOUND)
|
||||||
|
add_definitions(-DXR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
endif()
|
||||||
|
# Find the Vulkan loader.
|
||||||
|
find_package(Vulkan)
|
||||||
|
# To use simply include ${Vulkan_LIBRARY} in your target_link_library or
|
||||||
|
# wherever you normally link your library files to your target.
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(OpenGL)
|
||||||
|
if (OPENGL_FOUND)
|
||||||
|
add_definitions(-DXR_USE_GRAPHICS_API_OPENGL)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
add_definitions(-DXR_USE_GRAPHICS_API_D3D)
|
||||||
|
add_definitions(-DXR_USE_GRAPHICS_API_D3D11)
|
||||||
|
add_definitions(-DXR_USE_GRAPHICS_API_D3D12)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_LOADER_WITH_EXCEPTION_HANDLING)
|
||||||
|
set(XRLOADER_ENABLE_EXCEPTION_HANDLING TRUE)
|
||||||
|
endif()
|
||||||
|
# Check for the existence of the secure_getenv or __secure_getenv commands
|
||||||
|
include(CheckFunctionExists)
|
||||||
|
CHECK_FUNCTION_EXISTS(secure_getenv HAVE_SECURE_GETENV)
|
||||||
|
CHECK_FUNCTION_EXISTS(__secure_getenv HAVE___SECURE_GETENV)
|
||||||
|
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/common_cmake_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/common_cmake_config.h)
|
||||||
|
|
||||||
|
# Be able to find pre-generated files, if used.
|
||||||
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
|
add_definitions(-DXR_USE_TIMESPEC)
|
||||||
|
|
||||||
|
# Set up the OpenXR version variables, used by several targets in this project.
|
||||||
|
include(${CMAKE_CURRENT_SOURCE_DIR}/version.cmake)
|
||||||
|
|
||||||
|
# Path separators ( : or ; ) are not handled well in CMake.
|
||||||
|
# This seems like a reasonable approach.
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
set(CODEGEN_PYTHON_PATH "${CMAKE_SOURCE_DIR}/specification/scripts;${CMAKE_SOURCE_DIR}/src/scripts;$ENV{PYTHONPATH}")
|
||||||
|
else()
|
||||||
|
set(CODEGEN_PYTHON_PATH "${CMAKE_SOURCE_DIR}/specification/scripts:${CMAKE_SOURCE_DIR}/src/scripts:$ENV{PYTHONPATH}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# General code generation macro used by several targets.
|
||||||
|
macro(run_xr_xml_generate dependency output)
|
||||||
|
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${output}" AND NOT BUILD_FORCE_GENERATION)
|
||||||
|
# pre-generated found
|
||||||
|
message(STATUS "Found and will use pre-generated ${output} in source tree")
|
||||||
|
list(APPEND GENERATED_OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/${output}")
|
||||||
|
else()
|
||||||
|
if(NOT PYTHON_EXECUTABLE)
|
||||||
|
message(FATAL_ERROR "Python 3 not found, but pre-generated ${CMAKE_CURRENT_SOURCE_DIR}/${output} not found")
|
||||||
|
endif()
|
||||||
|
add_custom_command(OUTPUT ${output}
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CODEGEN_PYTHON_PATH}"
|
||||||
|
${PYTHON_EXECUTABLE}
|
||||||
|
${CMAKE_SOURCE_DIR}/src/scripts/src_genxr.py
|
||||||
|
-registry ${CMAKE_SOURCE_DIR}/specification/registry/xr.xml
|
||||||
|
${output}
|
||||||
|
DEPENDS
|
||||||
|
"${CMAKE_SOURCE_DIR}/specification/registry/xr.xml"
|
||||||
|
"${CMAKE_SOURCE_DIR}/specification/scripts/generator.py"
|
||||||
|
"${CMAKE_SOURCE_DIR}/specification/scripts/reg.py"
|
||||||
|
"${CMAKE_SOURCE_DIR}/src/scripts/${dependency}"
|
||||||
|
"${CMAKE_SOURCE_DIR}/src/scripts/src_genxr.py"
|
||||||
|
${ARGN}
|
||||||
|
COMMENT "Generating ${output} using ${PYTHON_EXECUTABLE} on ${dependency}"
|
||||||
|
)
|
||||||
|
set_source_files_properties(${output} PROPERTIES GENERATED TRUE)
|
||||||
|
list(APPEND GENERATED_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${output}")
|
||||||
|
list(APPEND GENERATED_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${output}")
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# Layer JSON generation macro used by several targets.
|
||||||
|
macro(gen_xr_layer_json filename layername libfile version desc genbad)
|
||||||
|
add_custom_command(OUTPUT ${filename}
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CODEGEN_PYTHON_PATH}"
|
||||||
|
${PYTHON_EXECUTABLE}
|
||||||
|
${CMAKE_SOURCE_DIR}/src/scripts/generate_api_layer_manifest.py
|
||||||
|
-f ${filename} -n ${layername} -l ${libfile} -a ${MAJOR}.${MINOR} -v ${version} ${genbad} -d ${desc}
|
||||||
|
DEPENDS ${CMAKE_SOURCE_DIR}/src/scripts/generate_api_layer_manifest.py
|
||||||
|
COMMENT "Generating API Layer JSON ${filename} using -f ${filename} -n ${layername} -l ${libfile} -a ${MAJOR}.${MINOR} -v ${version} ${genbad} -d ${desc}"
|
||||||
|
)
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# Custom target for generated dispatch table sources, used by several targets.
|
||||||
|
set(GENERATED_OUTPUT)
|
||||||
|
run_xr_xml_generate(utility_source_generator.py xr_generated_dispatch_table.h)
|
||||||
|
run_xr_xml_generate(utility_source_generator.py xr_generated_dispatch_table.c)
|
||||||
|
run_xr_xml_generate(utility_source_generator.py xr_generated_utilities.h)
|
||||||
|
run_xr_xml_generate(utility_source_generator.py xr_generated_utilities.c)
|
||||||
|
add_custom_target(xr_global_generated_files DEPENDS
|
||||||
|
${GENERATED_DEPENDS}
|
||||||
|
)
|
||||||
|
set_target_properties(xr_global_generated_files PROPERTIES FOLDER ${CODEGEN_FOLDER})
|
||||||
|
|
||||||
|
set(COMMON_GENERATED_OUTPUT ${GENERATED_OUTPUT})
|
||||||
|
|
||||||
|
if(BUILD_LOADER)
|
||||||
|
add_subdirectory(loader)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_API_LAYERS)
|
||||||
|
add_subdirectory(api_layers)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_TESTS)
|
||||||
|
add_subdirectory(tests)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_CONFORMANCE_TESTS)
|
||||||
|
add_subdirectory(conformance)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
103
extern/openxr/src/api_layers/CMakeLists.txt
vendored
Normal file
103
extern/openxr/src/api_layers/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
# Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
# Author:
|
||||||
|
#
|
||||||
|
|
||||||
|
# Force all compilers to output to binary folder without additional output (like Windows adds "Debug" and "Release" folders)
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES})
|
||||||
|
string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
endforeach(OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES)
|
||||||
|
|
||||||
|
# Copy the api_layer_platform_defines.h file and place it in the binary (build) directory.
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/api_layer_platform_defines.h ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)
|
||||||
|
|
||||||
|
# Basics for core_validation API Layer
|
||||||
|
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/XrApiLayer_core_validation.json ${CMAKE_CURRENT_BINARY_DIR}/XrApiLayer_core_validation.json COPYONLY)
|
||||||
|
|
||||||
|
add_library(XrApiLayer_core_validation SHARED
|
||||||
|
core_validation.cpp
|
||||||
|
${OPENXR_ROOT_DIR}/src/common/hex_and_handles.cpp
|
||||||
|
${OPENXR_ROOT_DIR}/src/common/hex_and_handles.h
|
||||||
|
${OPENXR_ROOT_DIR}/src/xr_generated_dispatch_table.c
|
||||||
|
${OPENXR_ROOT_DIR}/src/api_layers/xr_generated_core_validation.cpp
|
||||||
|
${OPENXR_ROOT_DIR}/src/api_layers/xr_generated_core_validation.hpp
|
||||||
|
# Included in this list to force generation
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/XrApiLayer_core_validation.json
|
||||||
|
)
|
||||||
|
set_target_properties(XrApiLayer_core_validation PROPERTIES FOLDER ${API_LAYERS_FOLDER})
|
||||||
|
|
||||||
|
add_dependencies(XrApiLayer_core_validation
|
||||||
|
generate_openxr_header
|
||||||
|
xr_global_generated_files
|
||||||
|
)
|
||||||
|
target_include_directories(XrApiLayer_core_validation
|
||||||
|
PRIVATE ${OPENXR_ROOT_DIR}/src/common
|
||||||
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
PRIVATE ${CMAKE_BINARY_DIR}/include
|
||||||
|
PRIVATE ${CMAKE_BINARY_DIR}/src
|
||||||
|
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
)
|
||||||
|
if(VulkanHeaders_FOUND)
|
||||||
|
target_include_directories(XrApiLayer_core_validation
|
||||||
|
PRIVATE ${Vulkan_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Flag generated files
|
||||||
|
set_source_files_properties(
|
||||||
|
${CMAKE_BINARY_DIR}/src/xr_generated_dispatch_table.c
|
||||||
|
PROPERTIES GENERATED TRUE
|
||||||
|
)
|
||||||
|
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
# Windows core_validation-specific information
|
||||||
|
target_compile_definitions(XrApiLayer_core_validation PRIVATE _CRT_SECURE_NO_WARNINGS)
|
||||||
|
# Turn off transitional "changed behavior" warning message for Visual Studio versions prior to 2015.
|
||||||
|
# The changed behavior is that constructor initializers are now fixed to clear the struct members.
|
||||||
|
target_compile_options(XrApiLayer_core_validation PRIVATE "$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<VERSION_LESS:$<CXX_COMPILER_VERSION>,19>>:/wd4351>")
|
||||||
|
|
||||||
|
FILE(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/XrApiLayer_core_validation.def DEF_FILE)
|
||||||
|
add_custom_target(copy-core_validation-def-file ALL
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${DEF_FILE} ${CMAKE_CURRENT_BINARY_DIR}/XrApiLayer_core_validation.def
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
set_target_properties(copy-core_validation-def-file PROPERTIES FOLDER ${HELPER_FOLDER})
|
||||||
|
elseif(APPLE)
|
||||||
|
# Apple core_validation-specific information
|
||||||
|
target_compile_options(XrApiLayer_core_validation PRIVATE -Wpointer-arith -Wno-unused-function -Wno-sign-compare)
|
||||||
|
set_target_properties(XrApiLayer_core_validation PROPERTIES LINK_FLAGS "-Wl")
|
||||||
|
|
||||||
|
else()
|
||||||
|
# Linux core_validation-specific information
|
||||||
|
target_compile_options(XrApiLayer_core_validation PRIVATE -Wpointer-arith -Wno-unused-function -Wno-sign-compare)
|
||||||
|
set_target_properties(XrApiLayer_core_validation PROPERTIES LINK_FLAGS "-Wl,-Bsymbolic,--exclude-libs,ALL")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Install explicit layers on Linux
|
||||||
|
set(TARGET_NAMES
|
||||||
|
XrApiLayer_core_validation)
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
foreach(TARGET_NAME ${TARGET_NAMES})
|
||||||
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.json DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/openxr/${MAJOR}/api_layers/explicit.d)
|
||||||
|
install(TARGETS ${TARGET_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
27
extern/openxr/src/api_layers/XrApiLayer_core_validation.def
vendored
Normal file
27
extern/openxr/src/api_layers/XrApiLayer_core_validation.def
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
;;;; Begin Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;
|
||||||
|
; Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
; Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
; Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
;
|
||||||
|
; Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
; you may not use this file except in compliance with the License.
|
||||||
|
; You may obtain a copy of the License at
|
||||||
|
;
|
||||||
|
; http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
;
|
||||||
|
; Unless required by applicable law or agreed to in writing, software
|
||||||
|
; distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
; See the License for the specific language governing permissions and
|
||||||
|
; limitations under the License.
|
||||||
|
;
|
||||||
|
; Author: Mark Young <marky@lunarg.com>
|
||||||
|
;
|
||||||
|
;;;; End Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
LIBRARY XrApiLayer_core_validation
|
||||||
|
EXPORTS
|
||||||
|
xrNegotiateLoaderApiLayerInterface
|
||||||
|
|
||||||
10
extern/openxr/src/api_layers/XrApiLayer_core_validation.json
vendored
Normal file
10
extern/openxr/src/api_layers/XrApiLayer_core_validation.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"file_format_version": "1.0.0",
|
||||||
|
"api_layer": {
|
||||||
|
"name": "XR_APILAYER_LUNARG_core_validation",
|
||||||
|
"library_path": "libXrApiLayer_core_validation.dll",
|
||||||
|
"api_version": "1.0",
|
||||||
|
"implementation_version": "1",
|
||||||
|
"description": "API Layer to perform validation of api calls and parameters as they occur"
|
||||||
|
}
|
||||||
|
}
|
||||||
48
extern/openxr/src/api_layers/api_layer_platform_defines.h
vendored
Normal file
48
extern/openxr/src/api_layers/api_layer_platform_defines.h
vendored
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// Copyright (c) 2018-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2018-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2018-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef API_LAYER_PLATFORM_DEFINES_H_
|
||||||
|
#define API_LAYER_PLATFORM_DEFINES_H_ 1
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define XR_USE_PLATFORM_WIN32 1 // Win32 platform
|
||||||
|
#endif // _WIN32
|
||||||
|
#if defined(OS_LINUX_XLIB)
|
||||||
|
#define XR_USE_PLATFORM_XLIB 1 // Xlib platform
|
||||||
|
#endif // OS_LINUX_XLIB
|
||||||
|
#if defined(OS_LINUX_XCB) || defined(OS_LINUX_XCB_GLX)
|
||||||
|
#define XR_USE_PLATFORM_XCB 1 // Xcb platform
|
||||||
|
#endif // OS_LINUX_XCB || OS_LINUX_XCB_GLX
|
||||||
|
#if defined(OS_LINUX_WAYLAND)
|
||||||
|
#define XR_USE_PLATFORM_WAYLAND 1 // Wayland platform
|
||||||
|
#endif // OS_LINUX_WAYLAND
|
||||||
|
#if defined(XR_OS_APPLE_IOS)
|
||||||
|
#define XR_USE_PLATFORM_IOS 1 // iOS platform
|
||||||
|
#define XR_USE_GRAPHICS_API_OPENGL_ES 1 // OpenGLES exists
|
||||||
|
#define XR_USE_GRAPHICS_API_METAL 1 // Metal exists
|
||||||
|
#endif // XR_OS_APPLE_IOS
|
||||||
|
#if defined(XR_OS_APPLE_MACOS)
|
||||||
|
#define XR_USE_PLATFORM_MACOS 1 // MacOS platform
|
||||||
|
#define XR_USE_GRAPHICS_API_OPENGL 1 // OpenGL exists
|
||||||
|
#define XR_USE_GRAPHICS_API_METAL 1 // Metal exists
|
||||||
|
#endif // XR_OS_APPLE_MACOS
|
||||||
|
|
||||||
|
#include "xr_dependencies.h" // IWYU pragma: export
|
||||||
|
|
||||||
|
#endif // API_LAYER_PLATFORM_DEFINES_H_
|
||||||
932
extern/openxr/src/api_layers/core_validation.cpp
vendored
Normal file
932
extern/openxr/src/api_layers/core_validation.cpp
vendored
Normal file
@@ -0,0 +1,932 @@
|
|||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "api_layer_platform_defines.h"
|
||||||
|
#include "extra_algorithms.h"
|
||||||
|
#include "hex_and_handles.h"
|
||||||
|
#include "loader_interfaces.h"
|
||||||
|
#include "platform_utils.hpp"
|
||||||
|
#include "validation_utils.h"
|
||||||
|
#include "xr_generated_core_validation.hpp"
|
||||||
|
#include "xr_generated_dispatch_table.h"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
|
#include <cstring>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && __GNUC__ >= 4
|
||||||
|
#define LAYER_EXPORT __attribute__((visibility("default")))
|
||||||
|
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
|
||||||
|
#define LAYER_EXPORT __attribute__((visibility("default")))
|
||||||
|
#else
|
||||||
|
#define LAYER_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Log recording information
|
||||||
|
enum CoreValidationRecordType {
|
||||||
|
RECORD_NONE = 0,
|
||||||
|
RECORD_TEXT_COUT,
|
||||||
|
RECORD_TEXT_FILE,
|
||||||
|
RECORD_HTML_FILE,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CoreValidationRecordInfo {
|
||||||
|
bool initialized;
|
||||||
|
CoreValidationRecordType type;
|
||||||
|
std::string file_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
static CoreValidationRecordInfo g_record_info = {};
|
||||||
|
static std::mutex g_record_mutex = {};
|
||||||
|
|
||||||
|
// HTML utilities
|
||||||
|
bool CoreValidationWriteHtmlHeader() {
|
||||||
|
try {
|
||||||
|
std::unique_lock<std::mutex> mlock(g_record_mutex);
|
||||||
|
std::ofstream html_file;
|
||||||
|
html_file.open(g_record_info.file_name, std::ios::out);
|
||||||
|
html_file
|
||||||
|
<< "<!doctype html>\n"
|
||||||
|
"<html>\n"
|
||||||
|
" <head>\n"
|
||||||
|
" <title>OpenXR Core Validation</title>\n"
|
||||||
|
" <style type='text/css'>\n"
|
||||||
|
" html {\n"
|
||||||
|
" background-color: #0b1e48;\n"
|
||||||
|
" background-image: url('https://vulkan.lunarg.com/img/bg-starfield.jpg');\n"
|
||||||
|
" background-position: center;\n"
|
||||||
|
" -webkit-background-size: cover;\n"
|
||||||
|
" -moz-background-size: cover;\n"
|
||||||
|
" -o-background-size: cover;\n"
|
||||||
|
" background-size: cover;\n"
|
||||||
|
" background-attachment: fixed;\n"
|
||||||
|
" background-repeat: no-repeat;\n"
|
||||||
|
" height: 100%;\n"
|
||||||
|
" }\n"
|
||||||
|
" #header {\n"
|
||||||
|
" z-index: -1;\n"
|
||||||
|
" }\n"
|
||||||
|
" #header>img {\n"
|
||||||
|
" position: absolute;\n"
|
||||||
|
" width: 160px;\n"
|
||||||
|
" margin-left: -280px;\n"
|
||||||
|
" top: -10px;\n"
|
||||||
|
" left: 50%;\n"
|
||||||
|
" }\n"
|
||||||
|
" #header>h1 {\n"
|
||||||
|
" font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif;\n"
|
||||||
|
" font-size: 48px;\n"
|
||||||
|
" font-weight: 200;\n"
|
||||||
|
" text-shadow: 4px 4px 5px #000;\n"
|
||||||
|
" color: #eee;\n"
|
||||||
|
" position: absolute;\n"
|
||||||
|
" width: 600px;\n"
|
||||||
|
" margin-left: -80px;\n"
|
||||||
|
" top: 8px;\n"
|
||||||
|
" left: 50%;\n"
|
||||||
|
" }\n"
|
||||||
|
" body {\n"
|
||||||
|
" font-family: Consolas, monaco, monospace;\n"
|
||||||
|
" font-size: 14px;\n"
|
||||||
|
" line-height: 20px;\n"
|
||||||
|
" color: #eee;\n"
|
||||||
|
" height: 100%;\n"
|
||||||
|
" margin: 0;\n"
|
||||||
|
" overflow: hidden;\n"
|
||||||
|
" }\n"
|
||||||
|
" #wrapper {\n"
|
||||||
|
" background-color: rgba(0, 0, 0, 0.7);\n"
|
||||||
|
" border: 1px solid #446;\n"
|
||||||
|
" box-shadow: 0px 0px 10px #000;\n"
|
||||||
|
" padding: 8px 12px;\n"
|
||||||
|
" display: inline-block;\n"
|
||||||
|
" position: absolute;\n"
|
||||||
|
" top: 80px;\n"
|
||||||
|
" bottom: 25px;\n"
|
||||||
|
" left: 50px;\n"
|
||||||
|
" right: 50px;\n"
|
||||||
|
" overflow: auto;\n"
|
||||||
|
" }\n"
|
||||||
|
" details>*:not(summary) {\n"
|
||||||
|
" margin-left: 22px;\n"
|
||||||
|
" }\n"
|
||||||
|
" summary:only-child {\n"
|
||||||
|
" display: block;\n"
|
||||||
|
" padding-left: 15px;\n"
|
||||||
|
" }\n"
|
||||||
|
" details>summary:only-child::-webkit-details-marker {\n"
|
||||||
|
" display: none;\n"
|
||||||
|
" padding-left: 15px;\n"
|
||||||
|
" }\n"
|
||||||
|
" .headervar, .generalheadertype, .warningheadertype, .errorheadertype, .debugheadertype, .headerval {\n"
|
||||||
|
" display: inline;\n"
|
||||||
|
" margin: 0 9px;\n"
|
||||||
|
" }\n"
|
||||||
|
" .var, .type, .val {\n"
|
||||||
|
" display: inline;\n"
|
||||||
|
" margin: 0 6px;\n"
|
||||||
|
" }\n"
|
||||||
|
" .warningheadertype, .type {\n"
|
||||||
|
" color: #dce22f;\n"
|
||||||
|
" }\n"
|
||||||
|
" .errorheadertype, .type {\n"
|
||||||
|
" color: #ff1616;\n"
|
||||||
|
" }\n"
|
||||||
|
" .debugheadertype, .type {\n"
|
||||||
|
" color: #888;\n"
|
||||||
|
" }\n"
|
||||||
|
" .generalheadertype, .type {\n"
|
||||||
|
" color: #acf;\n"
|
||||||
|
" }\n"
|
||||||
|
" .headerval, .val {\n"
|
||||||
|
" color: #afa;\n"
|
||||||
|
" text-align: right;\n"
|
||||||
|
" }\n"
|
||||||
|
" .thd {\n"
|
||||||
|
" color: #888;\n"
|
||||||
|
" }\n"
|
||||||
|
" </style>\n"
|
||||||
|
" </head>\n"
|
||||||
|
" <body>\n"
|
||||||
|
" <div id='header'>\n"
|
||||||
|
" <img src='https://lunarg.com/wp-content/uploads/2016/02/LunarG-wReg-150.png' />\n"
|
||||||
|
" <h1>OpenXR Core Validation</h1>\n"
|
||||||
|
" </div>\n"
|
||||||
|
" <div id='wrapper'>\n";
|
||||||
|
return true;
|
||||||
|
} catch (...) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CoreValidationWriteHtmlFooter() {
|
||||||
|
try {
|
||||||
|
std::unique_lock<std::mutex> mlock(g_record_mutex);
|
||||||
|
std::ofstream html_file;
|
||||||
|
html_file.open(g_record_info.file_name, std::ios::out | std::ios::app);
|
||||||
|
html_file << " </div>\n"
|
||||||
|
" </body>\n"
|
||||||
|
"</html>";
|
||||||
|
|
||||||
|
// Writing the footer means we're done.
|
||||||
|
if (g_record_info.initialized) {
|
||||||
|
g_record_info.initialized = false;
|
||||||
|
g_record_info.type = RECORD_NONE;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (...) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to record all the core validation information
|
||||||
|
void CoreValidLogMessage(GenValidUsageXrInstanceInfo *instance_info, const std::string &message_id,
|
||||||
|
GenValidUsageDebugSeverity message_severity, const std::string &command_name,
|
||||||
|
std::vector<GenValidUsageXrObjectInfo> objects_info, const std::string &message) {
|
||||||
|
if (g_record_info.initialized) {
|
||||||
|
std::unique_lock<std::mutex> mlock(g_record_mutex);
|
||||||
|
|
||||||
|
// Debug Utils items (in case we need them)
|
||||||
|
XrDebugUtilsMessageSeverityFlagsEXT debug_utils_severity = 0;
|
||||||
|
std::vector<XrDebugUtilsObjectNameInfoEXT> debug_utils_objects;
|
||||||
|
std::vector<XrDebugUtilsLabelEXT> session_labels;
|
||||||
|
|
||||||
|
std::string severity_string;
|
||||||
|
switch (message_severity) {
|
||||||
|
case VALID_USAGE_DEBUG_SEVERITY_DEBUG:
|
||||||
|
severity_string = "VALID_DEBUG";
|
||||||
|
debug_utils_severity = XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
|
||||||
|
break;
|
||||||
|
case VALID_USAGE_DEBUG_SEVERITY_INFO:
|
||||||
|
severity_string = "VALID_INFO";
|
||||||
|
debug_utils_severity = XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
|
||||||
|
break;
|
||||||
|
case VALID_USAGE_DEBUG_SEVERITY_WARNING:
|
||||||
|
severity_string = "VALID_WARNING";
|
||||||
|
debug_utils_severity = XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
|
||||||
|
break;
|
||||||
|
case VALID_USAGE_DEBUG_SEVERITY_ERROR:
|
||||||
|
severity_string = "VALID_ERROR";
|
||||||
|
debug_utils_severity = XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
severity_string = "VALID_UNKNOWN";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have instance information, see if we need to log this information out to a debug messenger
|
||||||
|
// callback.
|
||||||
|
if (nullptr != instance_info) {
|
||||||
|
if (!objects_info.empty()) {
|
||||||
|
for (auto &obj : objects_info) {
|
||||||
|
XrDebugUtilsObjectNameInfoEXT obj_name_info = {};
|
||||||
|
obj_name_info.next = nullptr;
|
||||||
|
obj_name_info.objectType = obj.type;
|
||||||
|
obj_name_info.objectHandle = obj.handle;
|
||||||
|
// If there's a session in the list, see if it has labels
|
||||||
|
if (XR_OBJECT_TYPE_SESSION == obj.type) {
|
||||||
|
XrSession session = TreatIntegerAsHandle<XrSession>(obj.handle);
|
||||||
|
auto session_label_iterator = g_xr_session_labels.find(session);
|
||||||
|
if (session_label_iterator != g_xr_session_labels.end()) {
|
||||||
|
auto rev_iter = session_label_iterator->second->rbegin();
|
||||||
|
for (; rev_iter != session_label_iterator->second->rend(); ++rev_iter) {
|
||||||
|
session_labels.push_back((*rev_iter)->debug_utils_label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Loop through all object names and see if any match
|
||||||
|
for (auto &object_name : instance_info->object_names) {
|
||||||
|
if (object_name->objectType == obj.type && object_name->objectHandle == obj.handle) {
|
||||||
|
obj_name_info.objectName = object_name->objectName;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug_utils_objects.push_back(obj_name_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!instance_info->debug_messengers.empty()) {
|
||||||
|
// Setup our callback data once
|
||||||
|
XrDebugUtilsMessengerCallbackDataEXT callback_data = {};
|
||||||
|
callback_data.type = XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
|
||||||
|
callback_data.messageId = message_id.c_str();
|
||||||
|
callback_data.functionName = command_name.c_str();
|
||||||
|
callback_data.message = message.c_str();
|
||||||
|
callback_data.objectCount = static_cast<uint8_t>(debug_utils_objects.size());
|
||||||
|
if (debug_utils_objects.empty()) {
|
||||||
|
callback_data.objects = nullptr;
|
||||||
|
} else {
|
||||||
|
callback_data.objects = debug_utils_objects.data();
|
||||||
|
}
|
||||||
|
callback_data.sessionLabelCount = static_cast<uint8_t>(session_labels.size());
|
||||||
|
if (session_labels.empty()) {
|
||||||
|
callback_data.sessionLabels = nullptr;
|
||||||
|
} else {
|
||||||
|
callback_data.sessionLabels = session_labels.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through all active messengers and give each a chance to output information
|
||||||
|
for (auto &debug_messenger : instance_info->debug_messengers) {
|
||||||
|
CoreValidationMessengerInfo *validation_messenger_info = debug_messenger.get();
|
||||||
|
XrDebugUtilsMessengerCreateInfoEXT *messenger_create_info = validation_messenger_info->create_info;
|
||||||
|
// If a callback exists, and the message is of a type this callback cares about, call it.
|
||||||
|
if (nullptr != messenger_create_info->userCallback &&
|
||||||
|
0 != (messenger_create_info->messageSeverities & debug_utils_severity) &&
|
||||||
|
0 != (messenger_create_info->messageTypes & XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT)) {
|
||||||
|
XrBool32 ret_val = messenger_create_info->userCallback(debug_utils_severity,
|
||||||
|
XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
|
||||||
|
&callback_data, messenger_create_info->userData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (g_record_info.type) {
|
||||||
|
case RECORD_TEXT_COUT: {
|
||||||
|
std::cout << "[" << severity_string << " | " << message_id << " | " << command_name << "]: " << message
|
||||||
|
<< std::endl;
|
||||||
|
if (!objects_info.empty()) {
|
||||||
|
std::cout << " Objects:" << std::endl;
|
||||||
|
uint32_t count = 0;
|
||||||
|
for (auto object_info : objects_info) {
|
||||||
|
std::string object_type = GenValidUsageXrObjectTypeToString(object_info.type);
|
||||||
|
std::ostringstream oss_object_handle;
|
||||||
|
std::cout << " [" << std::to_string(count++) << "] - " << object_type << " ("
|
||||||
|
<< Uint64ToHexString(object_info.handle) << ")";
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!session_labels.empty()) {
|
||||||
|
std::cout << " Session Labels:" << std::endl;
|
||||||
|
uint32_t count = 0;
|
||||||
|
for (auto session_label : session_labels) {
|
||||||
|
std::cout << " [" << std::to_string(count++) << "] - " << session_label.labelName << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << std::flush;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RECORD_TEXT_FILE: {
|
||||||
|
std::ofstream text_file;
|
||||||
|
text_file.open(g_record_info.file_name, std::ios::out | std::ios::app);
|
||||||
|
text_file << "[" << severity_string << " | " << message_id << " | " << command_name << "]: " << message
|
||||||
|
<< std::endl;
|
||||||
|
if (!objects_info.empty()) {
|
||||||
|
text_file << " Objects:" << std::endl;
|
||||||
|
uint32_t count = 0;
|
||||||
|
for (auto object_info : objects_info) {
|
||||||
|
std::string object_type = GenValidUsageXrObjectTypeToString(object_info.type);
|
||||||
|
text_file << " [" << std::to_string(count++) << "] - " << object_type << " ("
|
||||||
|
<< Uint64ToHexString(object_info.handle) << ")";
|
||||||
|
text_file << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!session_labels.empty()) {
|
||||||
|
text_file << " Session Labels:" << std::endl;
|
||||||
|
uint32_t count = 0;
|
||||||
|
for (auto session_label : session_labels) {
|
||||||
|
text_file << " [" << std::to_string(count++) << "] - " << session_label.labelName << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text_file << std::flush;
|
||||||
|
text_file.close();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RECORD_HTML_FILE: {
|
||||||
|
std::ofstream text_file;
|
||||||
|
text_file.open(g_record_info.file_name, std::ios::out | std::ios::app);
|
||||||
|
text_file << "<details class='data'>\n";
|
||||||
|
std::string header_type = "generalheadertype";
|
||||||
|
switch (message_severity) {
|
||||||
|
case VALID_USAGE_DEBUG_SEVERITY_DEBUG:
|
||||||
|
header_type = "debugheadertype";
|
||||||
|
severity_string = "Debug Message";
|
||||||
|
break;
|
||||||
|
case VALID_USAGE_DEBUG_SEVERITY_INFO:
|
||||||
|
severity_string = "Info Message";
|
||||||
|
break;
|
||||||
|
case VALID_USAGE_DEBUG_SEVERITY_WARNING:
|
||||||
|
header_type = "warningheadertype";
|
||||||
|
severity_string = "Warning Message";
|
||||||
|
break;
|
||||||
|
case VALID_USAGE_DEBUG_SEVERITY_ERROR:
|
||||||
|
header_type = "errorheadertype";
|
||||||
|
severity_string = "Error Message";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
severity_string = "Unknown Message";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
text_file << " <summary>\n"
|
||||||
|
<< " <div class='" << header_type << "'>" << severity_string << "</div>\n"
|
||||||
|
<< " <div class='headerval'>" << command_name << "</div>\n"
|
||||||
|
<< " <div class='headervar'>" << message_id << "</div>\n"
|
||||||
|
<< " </summary>\n";
|
||||||
|
text_file << " <div class='data'>\n";
|
||||||
|
text_file << " <div class='val'>" << message << "</div>\n";
|
||||||
|
if (!objects_info.empty()) {
|
||||||
|
text_file << " <details class='data'>\n";
|
||||||
|
text_file << " <summary>\n";
|
||||||
|
text_file << " <div class='type'>Relevant OpenXR Objects</div>\n";
|
||||||
|
text_file << " </summary>\n";
|
||||||
|
uint32_t count = 0;
|
||||||
|
for (auto object_info : objects_info) {
|
||||||
|
std::string object_type = GenValidUsageXrObjectTypeToString(object_info.type);
|
||||||
|
text_file << " <div class='data'>\n";
|
||||||
|
text_file << " <div class='var'>[" << count++ << "]</div>\n";
|
||||||
|
text_file << " <div class='type'>" << object_type << "</div>\n";
|
||||||
|
text_file << " <div class='val'>" << Uint64ToHexString(object_info.handle) << "</div>\n";
|
||||||
|
text_file << " </div>\n";
|
||||||
|
}
|
||||||
|
text_file << " </details>\n";
|
||||||
|
text_file << std::flush;
|
||||||
|
}
|
||||||
|
if (!session_labels.empty()) {
|
||||||
|
text_file << " <details class='data'>\n";
|
||||||
|
text_file << " <summary>\n";
|
||||||
|
text_file << " <div class='type'>Relevant Session Labels</div>\n";
|
||||||
|
text_file << " </summary>\n";
|
||||||
|
uint32_t count = 0;
|
||||||
|
for (auto session_label : session_labels) {
|
||||||
|
text_file << " <div class='data'>\n";
|
||||||
|
text_file << " <div class='var'>[" << count++ << "]</div>\n";
|
||||||
|
text_file << " <div class='type'>" << session_label.labelName << "</div>\n";
|
||||||
|
text_file << " </div>\n";
|
||||||
|
}
|
||||||
|
text_file << " </details>\n";
|
||||||
|
}
|
||||||
|
text_file << " </div>\n";
|
||||||
|
text_file << "</details>\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reportInternalError(std::string const &message) {
|
||||||
|
std::cerr << "INTERNAL VALIDATION LAYER ERROR: " << message << std::endl;
|
||||||
|
throw std::runtime_error("Internal validation layer error: " + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InvalidStructureType(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
|
||||||
|
std::vector<GenValidUsageXrObjectInfo> &objects_info, const char *structure_name, XrStructureType type,
|
||||||
|
const char *vuid, XrStructureType expected, const char *expected_name) {
|
||||||
|
std::ostringstream oss_type;
|
||||||
|
oss_type << structure_name << " has an invalid XrStructureType ";
|
||||||
|
oss_type << Uint32ToHexString(static_cast<uint32_t>(type));
|
||||||
|
if (expected != 0) {
|
||||||
|
oss_type << ", expected " << Uint32ToHexString(static_cast<uint32_t>(type));
|
||||||
|
oss_type << " (" << expected_name << ")";
|
||||||
|
}
|
||||||
|
if (vuid != nullptr) {
|
||||||
|
CoreValidLogMessage(instance_info, vuid, VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info, oss_type.str());
|
||||||
|
} else {
|
||||||
|
CoreValidLogMessage(instance_info, "VUID-" + std::string(structure_name) + "-type-type", VALID_USAGE_DEBUG_SEVERITY_ERROR,
|
||||||
|
command_name, objects_info, oss_type.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Can't validate the following VUIDs since the command never enters a layer:
|
||||||
|
// Command: xrEnumerateApiLayerProperties
|
||||||
|
// VUIDs: "VUID-xrEnumerateApiLayerProperties-propertyCountOutput-parameter"
|
||||||
|
// "VUID-xrEnumerateApiLayerProperties-properties-parameter"
|
||||||
|
// Command: xrEnumerateInstanceExtensionProperties
|
||||||
|
// VUIDs: "VUID-xrEnumerateInstanceExtensionProperties-layerName-parameter"
|
||||||
|
// "VUID-xrEnumerateInstanceExtensionProperties-propertyCountOutput-parameter"
|
||||||
|
// "VUID-xrEnumerateInstanceExtensionProperties-properties-parameter"
|
||||||
|
|
||||||
|
XrResult CoreValidationXrCreateInstance(const XrInstanceCreateInfo * /*info*/, XrInstance * /*instance*/) {
|
||||||
|
// Shouldn't be called, coreValidationXrCreateApiLayerInstance should called instead
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
GenValidUsageXrInstanceInfo::GenValidUsageXrInstanceInfo(XrInstance inst, PFN_xrGetInstanceProcAddr next_get_instance_proc_addr)
|
||||||
|
: instance(inst), dispatch_table(new XrGeneratedDispatchTable()) {
|
||||||
|
/// @todo smart pointer here!
|
||||||
|
|
||||||
|
// Create the dispatch table to the next levels
|
||||||
|
GeneratedXrPopulateDispatchTable(dispatch_table, instance, next_get_instance_proc_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
GenValidUsageXrInstanceInfo::~GenValidUsageXrInstanceInfo() { delete dispatch_table; }
|
||||||
|
|
||||||
|
// See if there is a debug utils create structure in the "next" chain
|
||||||
|
|
||||||
|
XrResult CoreValidationXrCreateApiLayerInstance(const XrInstanceCreateInfo *info, const struct XrApiLayerCreateInfo *apiLayerInfo,
|
||||||
|
XrInstance *instance) {
|
||||||
|
try {
|
||||||
|
XrApiLayerCreateInfo new_api_layer_info = {};
|
||||||
|
XrResult validation_result = XR_SUCCESS;
|
||||||
|
bool user_defined_output = false;
|
||||||
|
bool first_time = !g_record_info.initialized;
|
||||||
|
|
||||||
|
if (!g_record_info.initialized) {
|
||||||
|
g_record_info.initialized = true;
|
||||||
|
g_record_info.type = RECORD_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *export_type = PlatformUtilsGetEnv("XR_CORE_VALIDATION_EXPORT_TYPE");
|
||||||
|
char *file_name = PlatformUtilsGetEnv("XR_CORE_VALIDATION_FILE_NAME");
|
||||||
|
if (nullptr != file_name) {
|
||||||
|
g_record_info.file_name = file_name;
|
||||||
|
PlatformUtilsFreeEnv(file_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullptr != export_type) {
|
||||||
|
std::string string_export_type = export_type;
|
||||||
|
PlatformUtilsFreeEnv(export_type);
|
||||||
|
std::transform(string_export_type.begin(), string_export_type.end(), string_export_type.begin(),
|
||||||
|
[](unsigned char c) { return std::tolower(c); });
|
||||||
|
|
||||||
|
std::cerr << "Core Validation output type: " << string_export_type << ", first time = " << std::to_string(first_time)
|
||||||
|
<< std::endl;
|
||||||
|
if (string_export_type == "text") {
|
||||||
|
if (!g_record_info.file_name.empty()) {
|
||||||
|
g_record_info.type = RECORD_TEXT_FILE;
|
||||||
|
} else {
|
||||||
|
g_record_info.type = RECORD_TEXT_COUT;
|
||||||
|
}
|
||||||
|
user_defined_output = true;
|
||||||
|
} else if (string_export_type == "html" && first_time) {
|
||||||
|
g_record_info.type = RECORD_HTML_FILE;
|
||||||
|
if (!CoreValidationWriteHtmlHeader()) {
|
||||||
|
return XR_ERROR_INITIALIZATION_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the generated pre valid usage check.
|
||||||
|
validation_result = GenValidUsageInputsXrCreateInstance(info, instance);
|
||||||
|
|
||||||
|
// Copy the contents of the layer info struct, but then move the next info up by
|
||||||
|
// one slot so that the next layer gets information.
|
||||||
|
memcpy(&new_api_layer_info, apiLayerInfo, sizeof(XrApiLayerCreateInfo));
|
||||||
|
new_api_layer_info.nextInfo = apiLayerInfo->nextInfo->next;
|
||||||
|
|
||||||
|
// Get the function pointers we need
|
||||||
|
PFN_xrGetInstanceProcAddr next_get_instance_proc_addr = apiLayerInfo->nextInfo->nextGetInstanceProcAddr;
|
||||||
|
PFN_xrCreateApiLayerInstance next_create_api_layer_instance = apiLayerInfo->nextInfo->nextCreateApiLayerInstance;
|
||||||
|
|
||||||
|
// Create the instance using the layer create instance command for the next layer
|
||||||
|
XrInstance returned_instance = *instance;
|
||||||
|
XrResult next_result = next_create_api_layer_instance(info, &new_api_layer_info, &returned_instance);
|
||||||
|
*instance = returned_instance;
|
||||||
|
|
||||||
|
// Create the instance information
|
||||||
|
std::unique_ptr<GenValidUsageXrInstanceInfo> instance_info(
|
||||||
|
new GenValidUsageXrInstanceInfo(returned_instance, next_get_instance_proc_addr));
|
||||||
|
|
||||||
|
// Save the enabled extensions.
|
||||||
|
for (uint32_t extension = 0; extension < info->enabledExtensionCount; ++extension) {
|
||||||
|
instance_info->enabled_extensions.emplace_back(info->enabledExtensionNames[extension]);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_instance_info.insert(returned_instance, std::move(instance_info));
|
||||||
|
|
||||||
|
// See if a debug utils messenger is supposed to be created as part of the instance
|
||||||
|
// NOTE: We have to wait until after the instance info is added to the map for this
|
||||||
|
// to work properly.
|
||||||
|
const auto *next_header = reinterpret_cast<const XrBaseInStructure *>(info->next);
|
||||||
|
const XrDebugUtilsMessengerCreateInfoEXT *dbg_utils_create_info = nullptr;
|
||||||
|
while (next_header != nullptr) {
|
||||||
|
if (next_header->type == XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
|
||||||
|
dbg_utils_create_info = reinterpret_cast<const XrDebugUtilsMessengerCreateInfoEXT *>(next_header);
|
||||||
|
// Create the debug messenger. We don't have to keep track of it because it will be tracked as part
|
||||||
|
// of the instance info from here on out.
|
||||||
|
XrDebugUtilsMessengerEXT messenger;
|
||||||
|
validation_result = CoreValidationXrCreateDebugUtilsMessengerEXT(*instance, dbg_utils_create_info, &messenger);
|
||||||
|
// If we created a debug messenger, turn off the text output unless a user indicates they wanted it
|
||||||
|
if (XR_SUCCESS == validation_result && !user_defined_output) {
|
||||||
|
g_record_info.type = RECORD_NONE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
next_header = reinterpret_cast<const XrBaseInStructure *>(next_header->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (XR_SUCCESS == validation_result) {
|
||||||
|
return next_result;
|
||||||
|
}
|
||||||
|
return validation_result;
|
||||||
|
|
||||||
|
} catch (std::bad_alloc &) {
|
||||||
|
return XR_ERROR_OUT_OF_MEMORY;
|
||||||
|
} catch (...) {
|
||||||
|
return XR_ERROR_INITIALIZATION_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EraseAllInstanceTableMapElements(GenValidUsageXrInstanceInfo *search_value) {
|
||||||
|
typedef typename InstanceHandleInfo::value_t value_t;
|
||||||
|
auto map_with_lock = g_instance_info.lockMap();
|
||||||
|
auto &map = map_with_lock.second;
|
||||||
|
|
||||||
|
map_erase_if(map, [=](value_t const &data) { return data.second.get() == search_value; });
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult CoreValidationXrDestroyInstance(XrInstance instance) {
|
||||||
|
GenValidUsageInputsXrDestroyInstance(instance);
|
||||||
|
if (XR_NULL_HANDLE != instance) {
|
||||||
|
auto info_with_lock = g_instance_info.getWithLock(instance);
|
||||||
|
GenValidUsageXrInstanceInfo *gen_instance_info = info_with_lock.second;
|
||||||
|
if (nullptr != gen_instance_info) {
|
||||||
|
gen_instance_info->object_names.clear();
|
||||||
|
gen_instance_info->debug_messengers.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XrResult result = GenValidUsageNextXrDestroyInstance(instance);
|
||||||
|
if (!g_instance_info.empty() && g_record_info.type == RECORD_HTML_FILE) {
|
||||||
|
CoreValidationWriteHtmlFooter();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult CoreValidationXrCreateSession(XrInstance instance, const XrSessionCreateInfo *createInfo, XrSession *session) {
|
||||||
|
try {
|
||||||
|
XrResult test_result = GenValidUsageInputsXrCreateSession(instance, createInfo, session);
|
||||||
|
if (XR_SUCCESS != test_result) {
|
||||||
|
return test_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
|
||||||
|
|
||||||
|
// Check the next chain for a graphics binding structure, we need at least one.
|
||||||
|
uint32_t num_graphics_bindings_found = 0;
|
||||||
|
const auto *cur_ptr = reinterpret_cast<const XrBaseInStructure *>(createInfo->next);
|
||||||
|
while (nullptr != cur_ptr) {
|
||||||
|
switch (cur_ptr->type) {
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
#ifdef XR_USE_PLATFORM_WIN32
|
||||||
|
case XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR:
|
||||||
|
num_graphics_bindings_found++;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef XR_USE_PLATFORM_XLIB
|
||||||
|
case XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR:
|
||||||
|
num_graphics_bindings_found++;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef XR_USE_PLATFORM_XCB
|
||||||
|
case XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR:
|
||||||
|
num_graphics_bindings_found++;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef XR_USE_PLATFORM_WAYLAND
|
||||||
|
case XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR:
|
||||||
|
num_graphics_bindings_found++;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
cur_ptr = reinterpret_cast<const XrBaseInStructure *>(cur_ptr->next);
|
||||||
|
}
|
||||||
|
auto const &enabled_extensions = gen_instance_info->enabled_extensions;
|
||||||
|
#ifdef XR_KHR_headless
|
||||||
|
bool has_headless = (enabled_extensions.end() !=
|
||||||
|
std::find(enabled_extensions.begin(), enabled_extensions.end(), XR_KHR_HEADLESS_EXTENSION_NAME));
|
||||||
|
#else
|
||||||
|
bool has_headless = false;
|
||||||
|
#endif // XR_KHR_headless
|
||||||
|
bool got_right_graphics_binding_count = (num_graphics_bindings_found == 1);
|
||||||
|
if (!got_right_graphics_binding_count && has_headless) {
|
||||||
|
// This permits 0 as well.
|
||||||
|
got_right_graphics_binding_count = (num_graphics_bindings_found == 0);
|
||||||
|
}
|
||||||
|
if (!got_right_graphics_binding_count) {
|
||||||
|
std::vector<GenValidUsageXrObjectInfo> objects_info;
|
||||||
|
objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
|
||||||
|
std::ostringstream error_stream;
|
||||||
|
error_stream << "Invalid number of graphics binding structures provided. ";
|
||||||
|
error_stream << "Expected ";
|
||||||
|
if (has_headless) {
|
||||||
|
error_stream << "0 or 1";
|
||||||
|
} else {
|
||||||
|
error_stream << "1";
|
||||||
|
}
|
||||||
|
error_stream << ", but received ";
|
||||||
|
error_stream << num_graphics_bindings_found;
|
||||||
|
error_stream << ".";
|
||||||
|
// TODO: This needs to be updated with the actual VUID once we generate it.
|
||||||
|
CoreValidLogMessage(gen_instance_info, "VUID-xrCreateSession-next-parameter", VALID_USAGE_DEBUG_SEVERITY_ERROR,
|
||||||
|
"xrCreateSession", objects_info, error_stream.str());
|
||||||
|
return XR_ERROR_GRAPHICS_DEVICE_INVALID;
|
||||||
|
}
|
||||||
|
return GenValidUsageNextXrCreateSession(instance, createInfo, session);
|
||||||
|
} catch (...) {
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- XR_EXT_debug_utils extension commands
|
||||||
|
XrResult CoreValidationXrSetDebugUtilsObjectNameEXT(XrInstance instance, const XrDebugUtilsObjectNameInfoEXT *nameInfo) {
|
||||||
|
try {
|
||||||
|
XrResult result = GenValidUsageInputsXrSetDebugUtilsObjectNameEXT(instance, nameInfo);
|
||||||
|
if (!XR_UNQUALIFIED_SUCCESS(result)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = GenValidUsageNextXrSetDebugUtilsObjectNameEXT(instance, nameInfo);
|
||||||
|
if (!XR_UNQUALIFIED_SUCCESS(result)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
auto info_with_lock = g_instance_info.getWithLock(instance);
|
||||||
|
GenValidUsageXrInstanceInfo *gen_instance_info = info_with_lock.second;
|
||||||
|
if (nullptr != gen_instance_info) {
|
||||||
|
// Create a copy of the base object name info (no next items)
|
||||||
|
auto len = strlen(nameInfo->objectName);
|
||||||
|
char *name_string = new char[len + 1];
|
||||||
|
strncpy(name_string, nameInfo->objectName, len);
|
||||||
|
bool found = false;
|
||||||
|
for (auto &object_name : gen_instance_info->object_names) {
|
||||||
|
if (object_name->objectHandle == nameInfo->objectHandle && object_name->objectType == nameInfo->objectType) {
|
||||||
|
delete[] object_name->objectName;
|
||||||
|
object_name->objectName = name_string;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
UniqueXrDebugUtilsObjectNameInfoEXT new_object_name(new XrDebugUtilsObjectNameInfoEXT(*nameInfo));
|
||||||
|
new_object_name->next = nullptr;
|
||||||
|
new_object_name->objectName = name_string;
|
||||||
|
gen_instance_info->object_names.push_back(std::move(new_object_name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (...) {
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult CoreValidationXrCreateDebugUtilsMessengerEXT(XrInstance instance, const XrDebugUtilsMessengerCreateInfoEXT *createInfo,
|
||||||
|
XrDebugUtilsMessengerEXT *messenger) {
|
||||||
|
try {
|
||||||
|
XrResult result = GenValidUsageInputsXrCreateDebugUtilsMessengerEXT(instance, createInfo, messenger);
|
||||||
|
if (!XR_UNQUALIFIED_SUCCESS(result)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = GenValidUsageNextXrCreateDebugUtilsMessengerEXT(instance, createInfo, messenger);
|
||||||
|
if (!XR_UNQUALIFIED_SUCCESS(result)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
auto info_with_lock = g_instance_info.getWithLock(instance);
|
||||||
|
GenValidUsageXrInstanceInfo *gen_instance_info = info_with_lock.second;
|
||||||
|
if (nullptr != gen_instance_info) {
|
||||||
|
auto *new_create_info = new XrDebugUtilsMessengerCreateInfoEXT(*createInfo);
|
||||||
|
new_create_info->next = nullptr;
|
||||||
|
UniqueCoreValidationMessengerInfo new_messenger_info(new CoreValidationMessengerInfo);
|
||||||
|
new_messenger_info->messenger = *messenger;
|
||||||
|
new_messenger_info->create_info = new_create_info;
|
||||||
|
gen_instance_info->debug_messengers.push_back(std::move(new_messenger_info));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (...) {
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult CoreValidationXrDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT messenger) {
|
||||||
|
try {
|
||||||
|
XrResult result = GenValidUsageInputsXrDestroyDebugUtilsMessengerEXT(messenger);
|
||||||
|
if (!XR_UNQUALIFIED_SUCCESS(result)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = GenValidUsageNextXrDestroyDebugUtilsMessengerEXT(messenger);
|
||||||
|
if (!XR_UNQUALIFIED_SUCCESS(result)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (XR_NULL_HANDLE == messenger) {
|
||||||
|
return XR_ERROR_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
auto info_with_lock = g_debugutilsmessengerext_info.getWithLock(messenger);
|
||||||
|
GenValidUsageXrHandleInfo *gen_handle_info = info_with_lock.second;
|
||||||
|
if (nullptr != gen_handle_info) {
|
||||||
|
auto &debug_messengers = gen_handle_info->instance_info->debug_messengers;
|
||||||
|
vector_remove_if_and_erase(debug_messengers,
|
||||||
|
[=](UniqueCoreValidationMessengerInfo const &msg) { return msg->messenger == messenger; });
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (...) {
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We always want to remove the old individual label before we do anything else.
|
||||||
|
// So, do that in it's own method
|
||||||
|
void CoreValidationRemoveIndividualLabel(std::vector<GenValidUsageXrInternalSessionLabel *> *label_vec) {
|
||||||
|
if (!label_vec->empty()) {
|
||||||
|
GenValidUsageXrInternalSessionLabel *cur_label = label_vec->back();
|
||||||
|
if (cur_label->is_individual_label) {
|
||||||
|
label_vec->pop_back();
|
||||||
|
delete cur_label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoreValidationBeginLabelRegion(XrSession session, const XrDebugUtilsLabelEXT *label_info) {
|
||||||
|
std::vector<GenValidUsageXrInternalSessionLabel *> *vec_ptr = nullptr;
|
||||||
|
auto session_label_iterator = g_xr_session_labels.find(session);
|
||||||
|
if (session_label_iterator == g_xr_session_labels.end()) {
|
||||||
|
vec_ptr = new std::vector<GenValidUsageXrInternalSessionLabel *>;
|
||||||
|
g_xr_session_labels[session] = vec_ptr;
|
||||||
|
} else {
|
||||||
|
vec_ptr = session_label_iterator->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Individual labels do not stay around in the transition into a new label region
|
||||||
|
CoreValidationRemoveIndividualLabel(vec_ptr);
|
||||||
|
|
||||||
|
// Start the new label region
|
||||||
|
auto *new_session_label = new GenValidUsageXrInternalSessionLabel;
|
||||||
|
new_session_label->label_name = label_info->labelName;
|
||||||
|
new_session_label->debug_utils_label = *label_info;
|
||||||
|
new_session_label->debug_utils_label.labelName = new_session_label->label_name.c_str();
|
||||||
|
new_session_label->is_individual_label = false;
|
||||||
|
vec_ptr->push_back(new_session_label);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoreValidationEndLabelRegion(XrSession session) {
|
||||||
|
auto session_label_iterator = g_xr_session_labels.find(session);
|
||||||
|
if (session_label_iterator == g_xr_session_labels.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<GenValidUsageXrInternalSessionLabel *> *vec_ptr = session_label_iterator->second;
|
||||||
|
|
||||||
|
// Individual labels do not stay around in the transition out of label region
|
||||||
|
CoreValidationRemoveIndividualLabel(vec_ptr);
|
||||||
|
|
||||||
|
// Remove the last label region
|
||||||
|
if (!vec_ptr->empty()) {
|
||||||
|
GenValidUsageXrInternalSessionLabel *cur_label = vec_ptr->back();
|
||||||
|
vec_ptr->pop_back();
|
||||||
|
delete cur_label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoreValidationInsertLabel(XrSession session, const XrDebugUtilsLabelEXT *label_info) {
|
||||||
|
std::vector<GenValidUsageXrInternalSessionLabel *> *vec_ptr = nullptr;
|
||||||
|
auto session_label_iterator = g_xr_session_labels.find(session);
|
||||||
|
if (session_label_iterator == g_xr_session_labels.end()) {
|
||||||
|
vec_ptr = new std::vector<GenValidUsageXrInternalSessionLabel *>;
|
||||||
|
g_xr_session_labels[session] = vec_ptr;
|
||||||
|
} else {
|
||||||
|
vec_ptr = session_label_iterator->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove any individual layer that might already be there
|
||||||
|
CoreValidationRemoveIndividualLabel(vec_ptr);
|
||||||
|
|
||||||
|
// Insert a new individual label
|
||||||
|
auto *new_session_label = new GenValidUsageXrInternalSessionLabel;
|
||||||
|
new_session_label->label_name = label_info->labelName;
|
||||||
|
new_session_label->debug_utils_label = *label_info;
|
||||||
|
new_session_label->debug_utils_label.labelName = new_session_label->label_name.c_str();
|
||||||
|
new_session_label->is_individual_label = true;
|
||||||
|
vec_ptr->push_back(new_session_label);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called during xrDestroySession. We need to delete all session related labels.
|
||||||
|
void CoreValidationDeleteSessionLabels(XrSession session) {
|
||||||
|
std::vector<GenValidUsageXrInternalSessionLabel *> *vec_ptr = nullptr;
|
||||||
|
auto session_label_iterator = g_xr_session_labels.find(session);
|
||||||
|
if (session_label_iterator == g_xr_session_labels.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_ptr = session_label_iterator->second;
|
||||||
|
while (!vec_ptr->empty()) {
|
||||||
|
delete vec_ptr->back();
|
||||||
|
vec_ptr->pop_back();
|
||||||
|
}
|
||||||
|
delete vec_ptr;
|
||||||
|
g_xr_session_labels.erase(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult CoreValidationXrSessionBeginDebugUtilsLabelRegionEXT(XrSession session, const XrDebugUtilsLabelEXT *labelInfo) {
|
||||||
|
XrResult test_result = GenValidUsageInputsXrSessionBeginDebugUtilsLabelRegionEXT(session, labelInfo);
|
||||||
|
if (XR_SUCCESS != test_result) {
|
||||||
|
return test_result;
|
||||||
|
}
|
||||||
|
CoreValidationBeginLabelRegion(session, labelInfo);
|
||||||
|
return GenValidUsageNextXrSessionBeginDebugUtilsLabelRegionEXT(session, labelInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult CoreValidationXrSessionEndDebugUtilsLabelRegionEXT(XrSession session) {
|
||||||
|
XrResult test_result = GenValidUsageInputsXrSessionEndDebugUtilsLabelRegionEXT(session);
|
||||||
|
if (XR_SUCCESS != test_result) {
|
||||||
|
return test_result;
|
||||||
|
}
|
||||||
|
CoreValidationEndLabelRegion(session);
|
||||||
|
return GenValidUsageNextXrSessionEndDebugUtilsLabelRegionEXT(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult CoreValidationXrSessionInsertDebugUtilsLabelEXT(XrSession session, const XrDebugUtilsLabelEXT *labelInfo) {
|
||||||
|
XrResult test_result = GenValidUsageInputsXrSessionInsertDebugUtilsLabelEXT(session, labelInfo);
|
||||||
|
if (XR_SUCCESS != test_result) {
|
||||||
|
return test_result;
|
||||||
|
}
|
||||||
|
CoreValidationInsertLabel(session, labelInfo);
|
||||||
|
return GenValidUsageNextXrSessionInsertDebugUtilsLabelEXT(session, labelInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ############################################################
|
||||||
|
// NOTE: Add new validation checking above this comment block
|
||||||
|
// ############################################################
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
// Function used to negotiate an interface betewen the loader and an API layer. Each library exposing one or
|
||||||
|
// more API layers needs to expose at least this function.
|
||||||
|
LAYER_EXPORT XrResult xrNegotiateLoaderApiLayerInterface(const XrNegotiateLoaderInfo *loaderInfo, const char * /*apiLayerName*/,
|
||||||
|
XrNegotiateApiLayerRequest *apiLayerRequest) {
|
||||||
|
if (nullptr == loaderInfo || nullptr == apiLayerRequest || loaderInfo->structType != XR_LOADER_INTERFACE_STRUCT_LOADER_INFO ||
|
||||||
|
loaderInfo->structVersion != XR_LOADER_INFO_STRUCT_VERSION || loaderInfo->structSize != sizeof(XrNegotiateLoaderInfo) ||
|
||||||
|
apiLayerRequest->structType != XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST ||
|
||||||
|
apiLayerRequest->structVersion != XR_API_LAYER_INFO_STRUCT_VERSION ||
|
||||||
|
apiLayerRequest->structSize != sizeof(XrNegotiateApiLayerRequest) ||
|
||||||
|
loaderInfo->minInterfaceVersion > XR_CURRENT_LOADER_API_LAYER_VERSION ||
|
||||||
|
loaderInfo->maxInterfaceVersion < XR_CURRENT_LOADER_API_LAYER_VERSION ||
|
||||||
|
loaderInfo->maxInterfaceVersion > XR_CURRENT_LOADER_API_LAYER_VERSION ||
|
||||||
|
loaderInfo->maxApiVersion < XR_CORE_VALIDATION_API_VERSION || loaderInfo->minApiVersion > XR_CORE_VALIDATION_API_VERSION) {
|
||||||
|
return XR_ERROR_INITIALIZATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
apiLayerRequest->layerInterfaceVersion = XR_CURRENT_LOADER_API_LAYER_VERSION;
|
||||||
|
apiLayerRequest->layerApiVersion = XR_CORE_VALIDATION_API_VERSION;
|
||||||
|
apiLayerRequest->getInstanceProcAddr = reinterpret_cast<PFN_xrGetInstanceProcAddr>(GenValidUsageXrGetInstanceProcAddr);
|
||||||
|
apiLayerRequest->createApiLayerInstance =
|
||||||
|
reinterpret_cast<PFN_xrCreateApiLayerInstance>(CoreValidationXrCreateApiLayerInstance);
|
||||||
|
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // extern "C"
|
||||||
324
extern/openxr/src/api_layers/validation_utils.h
vendored
Normal file
324
extern/openxr/src/api_layers/validation_utils.h
vendored
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
// Copyright (c) 2018-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2018-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2018-2019 LunarG, Inc.
|
||||||
|
// Copyright (c) 2019, Collabora, Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||||
|
// Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VALIDATION_UTILS_H_
|
||||||
|
#define VALIDATION_UTILS_H_ 1
|
||||||
|
|
||||||
|
#include "api_layer_platform_defines.h"
|
||||||
|
#include "hex_and_handles.h"
|
||||||
|
#include "extra_algorithms.h"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
#include <openxr/openxr_platform.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <string>
|
||||||
|
#include <mutex>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
/// Prints a message to stderr then throws an exception.
|
||||||
|
///
|
||||||
|
/// The printing of the message is because the exception will probably be caught and silently turned into a validation error.
|
||||||
|
[[noreturn]] void reportInternalError(std::string const &message);
|
||||||
|
|
||||||
|
// Structure used for storing the instance information we need for validating
|
||||||
|
// various aspects of the OpenXR API.
|
||||||
|
|
||||||
|
// Debug Utils items
|
||||||
|
struct CoreValidationMessengerInfo {
|
||||||
|
XrDebugUtilsMessengerEXT messenger;
|
||||||
|
XrDebugUtilsMessengerCreateInfoEXT *create_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct XrGeneratedDispatchTable;
|
||||||
|
|
||||||
|
struct CoreValidationMessengerInfoDeleter {
|
||||||
|
void operator()(CoreValidationMessengerInfo *ptr) const {
|
||||||
|
delete ptr->create_info;
|
||||||
|
delete ptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct XrDebugUtilsObjectNameInfoEXTDeleter {
|
||||||
|
void operator()(XrDebugUtilsObjectNameInfoEXT *ptr) const {
|
||||||
|
delete ptr->objectName;
|
||||||
|
delete ptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::unique_ptr<XrDebugUtilsObjectNameInfoEXT, XrDebugUtilsObjectNameInfoEXTDeleter> UniqueXrDebugUtilsObjectNameInfoEXT;
|
||||||
|
|
||||||
|
typedef std::unique_ptr<CoreValidationMessengerInfo, CoreValidationMessengerInfoDeleter> UniqueCoreValidationMessengerInfo;
|
||||||
|
|
||||||
|
// Define the instance struct used for passing information around.
|
||||||
|
// This information includes things like the dispatch table as well as the
|
||||||
|
// enabled extensions.
|
||||||
|
struct GenValidUsageXrInstanceInfo {
|
||||||
|
GenValidUsageXrInstanceInfo(XrInstance inst, PFN_xrGetInstanceProcAddr next_get_instance_proc_addr);
|
||||||
|
~GenValidUsageXrInstanceInfo();
|
||||||
|
const XrInstance instance;
|
||||||
|
XrGeneratedDispatchTable *dispatch_table;
|
||||||
|
std::vector<std::string> enabled_extensions;
|
||||||
|
std::vector<UniqueCoreValidationMessengerInfo> debug_messengers;
|
||||||
|
std::vector<UniqueXrDebugUtilsObjectNameInfoEXT> object_names;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Structure used for storing information for other handles
|
||||||
|
struct GenValidUsageXrHandleInfo {
|
||||||
|
GenValidUsageXrInstanceInfo *instance_info;
|
||||||
|
XrObjectType direct_parent_type;
|
||||||
|
uint64_t direct_parent_handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Structure used for storing session label information
|
||||||
|
struct GenValidUsageXrInternalSessionLabel {
|
||||||
|
XrDebugUtilsLabelEXT debug_utils_label;
|
||||||
|
std::string label_name;
|
||||||
|
bool is_individual_label;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Enum used for indicating handle validation status.
|
||||||
|
enum ValidateXrHandleResult {
|
||||||
|
VALIDATE_XR_HANDLE_NULL,
|
||||||
|
VALIDATE_XR_HANDLE_INVALID,
|
||||||
|
VALIDATE_XR_HANDLE_SUCCESS,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Unordered Map associating pointer to a vector of session label information to a session's handle
|
||||||
|
extern std::unordered_map<XrSession, std::vector<GenValidUsageXrInternalSessionLabel *> *> g_xr_session_labels;
|
||||||
|
|
||||||
|
// This function is used to delete session labels when a session is destroyed
|
||||||
|
extern void CoreValidationDeleteSessionLabels(XrSession session);
|
||||||
|
|
||||||
|
// Object information used for logging.
|
||||||
|
struct GenValidUsageXrObjectInfo {
|
||||||
|
uint64_t handle;
|
||||||
|
XrObjectType type;
|
||||||
|
GenValidUsageXrObjectInfo() = default;
|
||||||
|
template <typename T>
|
||||||
|
GenValidUsageXrObjectInfo(T h, XrObjectType t) : handle(MakeHandleGeneric(h)), type(t) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Debug message severity levels for logging.
|
||||||
|
enum GenValidUsageDebugSeverity {
|
||||||
|
VALID_USAGE_DEBUG_SEVERITY_DEBUG = 0,
|
||||||
|
VALID_USAGE_DEBUG_SEVERITY_INFO = 7,
|
||||||
|
VALID_USAGE_DEBUG_SEVERITY_WARNING = 14,
|
||||||
|
VALID_USAGE_DEBUG_SEVERITY_ERROR = 21,
|
||||||
|
};
|
||||||
|
|
||||||
|
// in core_validation.cpp
|
||||||
|
void EraseAllInstanceTableMapElements(GenValidUsageXrInstanceInfo *search_value);
|
||||||
|
|
||||||
|
typedef std::unique_lock<std::mutex> UniqueLock;
|
||||||
|
template <typename HandleType, typename InfoType>
|
||||||
|
class HandleInfoBase {
|
||||||
|
public:
|
||||||
|
typedef InfoType info_t;
|
||||||
|
typedef HandleType handle_t;
|
||||||
|
typedef std::unordered_map<HandleType, std::unique_ptr<InfoType>> map_t;
|
||||||
|
typedef typename map_t::value_type value_t;
|
||||||
|
|
||||||
|
/// Validate a handle.
|
||||||
|
///
|
||||||
|
/// Returns an enum indicating null, invalid (not found), or success.
|
||||||
|
ValidateXrHandleResult verifyHandle(HandleType const *handle_to_check);
|
||||||
|
|
||||||
|
/// Lookup a handle.
|
||||||
|
/// Throws if not found.
|
||||||
|
InfoType *get(HandleType handle);
|
||||||
|
|
||||||
|
/// Lookup a handle, returning a pointer (if found) as well as a lock for this object's dispatch mutex.
|
||||||
|
std::pair<UniqueLock, InfoType *> getWithLock(HandleType handle);
|
||||||
|
|
||||||
|
bool empty() const { return info_map_.empty(); }
|
||||||
|
|
||||||
|
/// Insert an info for the supplied handle.
|
||||||
|
/// Throws if it's already there.
|
||||||
|
void insert(HandleType handle, std::unique_ptr<InfoType> &&info);
|
||||||
|
|
||||||
|
/// Remove the info associated with the supplied handle.
|
||||||
|
/// Throws if not found.
|
||||||
|
void erase(HandleType handle);
|
||||||
|
|
||||||
|
/// Get a constant reference to the whole map as well as a lock for this object's dispatch mutex.
|
||||||
|
std::pair<UniqueLock, map_t const &> lockMapConst();
|
||||||
|
|
||||||
|
/// Get a reference to the whole map as well as a lock for this object's dispatch mutex.
|
||||||
|
std::pair<UniqueLock, map_t &> lockMap();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
map_t info_map_;
|
||||||
|
std::mutex dispatch_mutex_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Subclass used exclusively for instances.
|
||||||
|
class InstanceHandleInfo : public HandleInfoBase<XrInstance, GenValidUsageXrInstanceInfo> {
|
||||||
|
public:
|
||||||
|
typedef HandleInfoBase<XrInstance, GenValidUsageXrInstanceInfo> base_t;
|
||||||
|
typedef typename base_t::info_t info_t;
|
||||||
|
typedef typename base_t::handle_t handle_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Generic handle info for everything-except-instance handles.
|
||||||
|
template <typename HandleType>
|
||||||
|
class HandleInfo : public HandleInfoBase<HandleType, GenValidUsageXrHandleInfo> {
|
||||||
|
public:
|
||||||
|
typedef HandleInfoBase<HandleType, GenValidUsageXrHandleInfo> base_t;
|
||||||
|
typedef typename base_t::info_t info_t;
|
||||||
|
typedef typename base_t::handle_t handle_t;
|
||||||
|
|
||||||
|
/// Lookup a handle and its instance info
|
||||||
|
/// Throws if not found.
|
||||||
|
std::pair<GenValidUsageXrHandleInfo *, GenValidUsageXrInstanceInfo *> getWithInstanceInfo(HandleType handle);
|
||||||
|
|
||||||
|
/// Removes handles associated with an instance.
|
||||||
|
void removeHandlesForInstance(GenValidUsageXrInstanceInfo *search_value);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Function to record all the core validation information
|
||||||
|
void CoreValidLogMessage(GenValidUsageXrInstanceInfo *instance_info, const std::string &message_id,
|
||||||
|
GenValidUsageDebugSeverity message_severity, const std::string &command_name,
|
||||||
|
std::vector<GenValidUsageXrObjectInfo> objects_info, const std::string &message);
|
||||||
|
|
||||||
|
void InvalidStructureType(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
|
||||||
|
std::vector<GenValidUsageXrObjectInfo> &objects_info, const char *structure_name, XrStructureType type,
|
||||||
|
const char *vuid = nullptr, XrStructureType expected = XrStructureType(0),
|
||||||
|
const char *expected_name = "");
|
||||||
|
|
||||||
|
// -- Only implementations of templates follow --//
|
||||||
|
|
||||||
|
template <typename HT, typename IT>
|
||||||
|
inline std::pair<UniqueLock, typename HandleInfoBase<HT, IT>::map_t const &> HandleInfoBase<HT, IT>::lockMapConst() {
|
||||||
|
return {UniqueLock(dispatch_mutex_), info_map_};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename HT, typename IT>
|
||||||
|
inline std::pair<UniqueLock, typename HandleInfoBase<HT, IT>::map_t &> HandleInfoBase<HT, IT>::lockMap() {
|
||||||
|
return {UniqueLock(dispatch_mutex_), info_map_};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename HandleType, typename InfoType>
|
||||||
|
inline ValidateXrHandleResult HandleInfoBase<HandleType, InfoType>::verifyHandle(HandleType const *handle_to_check) {
|
||||||
|
try {
|
||||||
|
if (nullptr == handle_to_check) {
|
||||||
|
return VALIDATE_XR_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
// XR_NULL_HANDLE is valid in some cases, so we want to return that we found that value
|
||||||
|
// and let the calling function decide what to do with it.
|
||||||
|
if (*handle_to_check == XR_NULL_HANDLE) {
|
||||||
|
return VALIDATE_XR_HANDLE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to find the handle in the appropriate map
|
||||||
|
UniqueLock lock(dispatch_mutex_);
|
||||||
|
auto entry_returned = info_map_.find(*handle_to_check);
|
||||||
|
// If it is not a valid handle, it should return the end of the map.
|
||||||
|
if (info_map_.end() == entry_returned) {
|
||||||
|
return VALIDATE_XR_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
return VALIDATE_XR_HANDLE_SUCCESS;
|
||||||
|
} catch (...) {
|
||||||
|
return VALIDATE_XR_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename HandleType, typename InfoType>
|
||||||
|
inline InfoType *HandleInfoBase<HandleType, InfoType>::get(HandleType handle) {
|
||||||
|
if (handle == XR_NULL_HANDLE) {
|
||||||
|
reportInternalError("Null handle passed to HandleInfoBase::get()");
|
||||||
|
}
|
||||||
|
// Try to find the handle in the appropriate map
|
||||||
|
UniqueLock lock(dispatch_mutex_);
|
||||||
|
auto entry_returned = info_map_.find(handle);
|
||||||
|
if (entry_returned == info_map_.end()) {
|
||||||
|
reportInternalError("Handle passed to HandleInfoBase::insert() not inserted");
|
||||||
|
}
|
||||||
|
return entry_returned->second.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename HandleType, typename InfoType>
|
||||||
|
inline std::pair<UniqueLock, InfoType *> HandleInfoBase<HandleType, InfoType>::getWithLock(HandleType handle) {
|
||||||
|
if (handle == XR_NULL_HANDLE) {
|
||||||
|
reportInternalError("Null handle passed to HandleInfoBase::getWithLock()");
|
||||||
|
}
|
||||||
|
// Try to find the handle in the appropriate map
|
||||||
|
UniqueLock lock(dispatch_mutex_);
|
||||||
|
auto it = info_map_.find(handle);
|
||||||
|
// If it is not a valid handle, it should return the end of the map.
|
||||||
|
if (info_map_.end() == it) {
|
||||||
|
return {std::move(lock), nullptr};
|
||||||
|
}
|
||||||
|
return {std::move(lock), it->second.get()};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename HandleType, typename InfoType>
|
||||||
|
inline void HandleInfoBase<HandleType, InfoType>::insert(HandleType handle, std::unique_ptr<InfoType> &&info) {
|
||||||
|
if (handle == XR_NULL_HANDLE) {
|
||||||
|
reportInternalError("Null handle passed to HandleInfoBase::insert()");
|
||||||
|
}
|
||||||
|
UniqueLock lock(dispatch_mutex_);
|
||||||
|
auto entry_returned = info_map_.find(handle);
|
||||||
|
if (entry_returned != info_map_.end()) {
|
||||||
|
reportInternalError("Handle passed to HandleInfoBase::insert() already inserted");
|
||||||
|
}
|
||||||
|
info_map_[handle] = std::move(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename HandleType, typename InfoType>
|
||||||
|
inline void HandleInfoBase<HandleType, InfoType>::erase(HandleType handle) {
|
||||||
|
if (handle == XR_NULL_HANDLE) {
|
||||||
|
reportInternalError("Null handle passed to HandleInfoBase::erase()");
|
||||||
|
}
|
||||||
|
UniqueLock lock(dispatch_mutex_);
|
||||||
|
auto entry_returned = info_map_.find(handle);
|
||||||
|
if (entry_returned == info_map_.end()) {
|
||||||
|
reportInternalError("Handle passed to HandleInfoBase::insert() not inserted");
|
||||||
|
}
|
||||||
|
info_map_.erase(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename HandleType>
|
||||||
|
inline std::pair<GenValidUsageXrHandleInfo *, GenValidUsageXrInstanceInfo *> HandleInfo<HandleType>::getWithInstanceInfo(
|
||||||
|
HandleType handle) {
|
||||||
|
if (handle == XR_NULL_HANDLE) {
|
||||||
|
reportInternalError("Null handle passed to HandleInfoBase::getWithInstanceInfo()");
|
||||||
|
}
|
||||||
|
// Try to find the handle in the appropriate map
|
||||||
|
UniqueLock lock(this->dispatch_mutex_);
|
||||||
|
auto entry_returned = this->info_map_.find(handle);
|
||||||
|
if (entry_returned == this->info_map_.end()) {
|
||||||
|
reportInternalError("Handle passed to HandleInfoBase::getWithInstanceInfo() not inserted");
|
||||||
|
}
|
||||||
|
GenValidUsageXrHandleInfo *info = entry_returned->second.get();
|
||||||
|
GenValidUsageXrInstanceInfo *instance_info = info->instance_info;
|
||||||
|
return {info, instance_info};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename HandleType>
|
||||||
|
inline void HandleInfo<HandleType>::removeHandlesForInstance(GenValidUsageXrInstanceInfo *search_value) {
|
||||||
|
typedef typename base_t::value_t value_t;
|
||||||
|
UniqueLock lock(this->dispatch_mutex_);
|
||||||
|
map_erase_if(this->info_map_, [=](value_t const &data) { return data.second && data.second->instance_info == search_value; });
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // VALIDATION_UTILS_H_
|
||||||
15407
extern/openxr/src/api_layers/xr_generated_core_validation.cpp
vendored
Normal file
15407
extern/openxr/src/api_layers/xr_generated_core_validation.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
156
extern/openxr/src/api_layers/xr_generated_core_validation.hpp
vendored
Normal file
156
extern/openxr/src/api_layers/xr_generated_core_validation.hpp
vendored
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
|
||||||
|
// See validation_layer_generator.py for modifications
|
||||||
|
// ************************************************************
|
||||||
|
|
||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "xr_generated_dispatch_table.h"
|
||||||
|
#include "validation_utils.h"
|
||||||
|
#include "api_layer_platform_defines.h"
|
||||||
|
#include "xr_dependencies.h"
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
#include <openxr/openxr_platform.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
|
||||||
|
// Unordered Map associating pointer to a vector of session label information to a session's handle
|
||||||
|
extern std::unordered_map<XrSession, std::vector<GenValidUsageXrInternalSessionLabel*>*> g_xr_session_labels;
|
||||||
|
|
||||||
|
|
||||||
|
// ---- Core 1.0 commands
|
||||||
|
XrResult GenValidUsageXrGetInstanceProcAddr(
|
||||||
|
XrInstance instance,
|
||||||
|
const char* name,
|
||||||
|
PFN_xrVoidFunction* function);
|
||||||
|
XrResult CoreValidationXrCreateInstance(
|
||||||
|
const XrInstanceCreateInfo* createInfo,
|
||||||
|
XrInstance* instance);
|
||||||
|
XrResult GenValidUsageInputsXrCreateInstance(const XrInstanceCreateInfo* createInfo, XrInstance* instance);
|
||||||
|
XrResult GenValidUsageNextXrCreateInstance(
|
||||||
|
const XrInstanceCreateInfo* createInfo,
|
||||||
|
XrInstance* instance);
|
||||||
|
XrResult CoreValidationXrDestroyInstance(
|
||||||
|
XrInstance instance);
|
||||||
|
XrResult GenValidUsageInputsXrDestroyInstance(XrInstance instance);
|
||||||
|
XrResult GenValidUsageNextXrDestroyInstance(
|
||||||
|
XrInstance instance);
|
||||||
|
XrResult CoreValidationXrCreateSession(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrSessionCreateInfo* createInfo,
|
||||||
|
XrSession* session);
|
||||||
|
XrResult GenValidUsageInputsXrCreateSession(XrInstance instance, const XrSessionCreateInfo* createInfo, XrSession* session);
|
||||||
|
XrResult GenValidUsageNextXrCreateSession(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrSessionCreateInfo* createInfo,
|
||||||
|
XrSession* session);
|
||||||
|
|
||||||
|
// ---- XR_KHR_android_thread_settings extension commands
|
||||||
|
|
||||||
|
// ---- XR_KHR_android_surface_swapchain extension commands
|
||||||
|
|
||||||
|
// ---- XR_KHR_opengl_enable extension commands
|
||||||
|
|
||||||
|
// ---- XR_KHR_opengl_es_enable extension commands
|
||||||
|
|
||||||
|
// ---- XR_KHR_vulkan_enable extension commands
|
||||||
|
|
||||||
|
// ---- XR_KHR_D3D11_enable extension commands
|
||||||
|
|
||||||
|
// ---- XR_KHR_D3D12_enable extension commands
|
||||||
|
|
||||||
|
// ---- XR_KHR_visibility_mask extension commands
|
||||||
|
|
||||||
|
// ---- XR_KHR_win32_convert_performance_counter_time extension commands
|
||||||
|
|
||||||
|
// ---- XR_KHR_convert_timespec_time extension commands
|
||||||
|
|
||||||
|
// ---- XR_EXT_performance_settings extension commands
|
||||||
|
|
||||||
|
// ---- XR_EXT_thermal_query extension commands
|
||||||
|
|
||||||
|
// ---- XR_EXT_debug_utils extension commands
|
||||||
|
XrResult CoreValidationXrSetDebugUtilsObjectNameEXT(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrDebugUtilsObjectNameInfoEXT* nameInfo);
|
||||||
|
XrResult GenValidUsageInputsXrSetDebugUtilsObjectNameEXT(XrInstance instance, const XrDebugUtilsObjectNameInfoEXT* nameInfo);
|
||||||
|
XrResult GenValidUsageNextXrSetDebugUtilsObjectNameEXT(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrDebugUtilsObjectNameInfoEXT* nameInfo);
|
||||||
|
XrResult CoreValidationXrCreateDebugUtilsMessengerEXT(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrDebugUtilsMessengerCreateInfoEXT* createInfo,
|
||||||
|
XrDebugUtilsMessengerEXT* messenger);
|
||||||
|
XrResult GenValidUsageInputsXrCreateDebugUtilsMessengerEXT(XrInstance instance, const XrDebugUtilsMessengerCreateInfoEXT* createInfo, XrDebugUtilsMessengerEXT* messenger);
|
||||||
|
XrResult GenValidUsageNextXrCreateDebugUtilsMessengerEXT(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrDebugUtilsMessengerCreateInfoEXT* createInfo,
|
||||||
|
XrDebugUtilsMessengerEXT* messenger);
|
||||||
|
XrResult CoreValidationXrDestroyDebugUtilsMessengerEXT(
|
||||||
|
XrDebugUtilsMessengerEXT messenger);
|
||||||
|
XrResult GenValidUsageInputsXrDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT messenger);
|
||||||
|
XrResult GenValidUsageNextXrDestroyDebugUtilsMessengerEXT(
|
||||||
|
XrDebugUtilsMessengerEXT messenger);
|
||||||
|
XrResult CoreValidationXrSessionBeginDebugUtilsLabelRegionEXT(
|
||||||
|
XrSession session,
|
||||||
|
const XrDebugUtilsLabelEXT* labelInfo);
|
||||||
|
XrResult GenValidUsageInputsXrSessionBeginDebugUtilsLabelRegionEXT(XrSession session, const XrDebugUtilsLabelEXT* labelInfo);
|
||||||
|
XrResult GenValidUsageNextXrSessionBeginDebugUtilsLabelRegionEXT(
|
||||||
|
XrSession session,
|
||||||
|
const XrDebugUtilsLabelEXT* labelInfo);
|
||||||
|
XrResult CoreValidationXrSessionEndDebugUtilsLabelRegionEXT(
|
||||||
|
XrSession session);
|
||||||
|
XrResult GenValidUsageInputsXrSessionEndDebugUtilsLabelRegionEXT(XrSession session);
|
||||||
|
XrResult GenValidUsageNextXrSessionEndDebugUtilsLabelRegionEXT(
|
||||||
|
XrSession session);
|
||||||
|
XrResult CoreValidationXrSessionInsertDebugUtilsLabelEXT(
|
||||||
|
XrSession session,
|
||||||
|
const XrDebugUtilsLabelEXT* labelInfo);
|
||||||
|
XrResult GenValidUsageInputsXrSessionInsertDebugUtilsLabelEXT(XrSession session, const XrDebugUtilsLabelEXT* labelInfo);
|
||||||
|
XrResult GenValidUsageNextXrSessionInsertDebugUtilsLabelEXT(
|
||||||
|
XrSession session,
|
||||||
|
const XrDebugUtilsLabelEXT* labelInfo);
|
||||||
|
|
||||||
|
// Current API version of the Core Validation API Layer
|
||||||
|
#define XR_CORE_VALIDATION_API_VERSION XR_CURRENT_API_VERSION
|
||||||
|
|
||||||
|
// Externs for Core Validation
|
||||||
|
extern InstanceHandleInfo g_instance_info;
|
||||||
|
extern HandleInfo<XrSession> g_session_info;
|
||||||
|
extern HandleInfo<XrSpace> g_space_info;
|
||||||
|
extern HandleInfo<XrAction> g_action_info;
|
||||||
|
extern HandleInfo<XrSwapchain> g_swapchain_info;
|
||||||
|
extern HandleInfo<XrActionSet> g_actionset_info;
|
||||||
|
extern HandleInfo<XrDebugUtilsMessengerEXT> g_debugutilsmessengerext_info;void GenValidUsageCleanUpMaps(GenValidUsageXrInstanceInfo *instance_info);
|
||||||
|
|
||||||
|
|
||||||
|
// Function to convert XrObjectType to string
|
||||||
|
std::string GenValidUsageXrObjectTypeToString(const XrObjectType& type);
|
||||||
|
|
||||||
|
// Function to record all the core validation information
|
||||||
|
extern void CoreValidLogMessage(GenValidUsageXrInstanceInfo *instance_info, const std::string &message_id,
|
||||||
|
GenValidUsageDebugSeverity message_severity, const std::string &command_name,
|
||||||
|
std::vector<GenValidUsageXrObjectInfo> objects_info, const std::string &message);
|
||||||
|
|
||||||
86
extern/openxr/src/cmake/FindVulkanHeaders.cmake
vendored
Normal file
86
extern/openxr/src/cmake/FindVulkanHeaders.cmake
vendored
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
# ~~~
|
||||||
|
# Copyright (c) 2018-2019 Valve Corporation
|
||||||
|
# Copyright (c) 2018-2019 LunarG, Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
# ~~~
|
||||||
|
|
||||||
|
#.rst:
|
||||||
|
# FindVulkanHeaders
|
||||||
|
# -----------------
|
||||||
|
#
|
||||||
|
# Try to find Vulkan Headers and Registry.
|
||||||
|
#
|
||||||
|
# This module is intended to be used by projects that build Vulkan
|
||||||
|
# "system" components such as the loader and layers.
|
||||||
|
# Vulkan applications should instead use the FindVulkan (or similar)
|
||||||
|
# find module that locates the headers and the loader library.
|
||||||
|
#
|
||||||
|
# When using this find module to locate the headers and registry
|
||||||
|
# in a Vulkan-Headers repository, the Vulkan-Headers repository
|
||||||
|
# should be built with 'install' target and the following environment
|
||||||
|
# or CMake variable set to the location of the install directory.
|
||||||
|
#
|
||||||
|
# VULKAN_HEADERS_INSTALL_DIR
|
||||||
|
#
|
||||||
|
# IMPORTED Targets
|
||||||
|
# ^^^^^^^^^^^^^^^^
|
||||||
|
#
|
||||||
|
# This module defines no IMPORTED targets
|
||||||
|
#
|
||||||
|
# Result Variables
|
||||||
|
# ^^^^^^^^^^^^^^^^
|
||||||
|
#
|
||||||
|
# This module defines the following variables::
|
||||||
|
#
|
||||||
|
# VulkanHeaders_FOUND - True if VulkanHeaders was found
|
||||||
|
# VulkanHeaders_INCLUDE_DIRS - include directories for VulkanHeaders
|
||||||
|
#
|
||||||
|
# VulkanRegistry_FOUND - True if VulkanRegistry was found
|
||||||
|
# VulkanRegistry_DIRS - directories for VulkanRegistry
|
||||||
|
#
|
||||||
|
# The module will also define two cache variables::
|
||||||
|
#
|
||||||
|
# VulkanHeaders_INCLUDE_DIR - the VulkanHeaders include directory
|
||||||
|
# VulkanRegistry_DIR - the VulkanRegistry directory
|
||||||
|
#
|
||||||
|
|
||||||
|
# Use HINTS instead of PATH to search these locations before
|
||||||
|
# searching system environment variables like $PATH that may
|
||||||
|
# contain SDK directories.
|
||||||
|
find_path(VulkanHeaders_INCLUDE_DIR
|
||||||
|
NAMES vulkan/vulkan.h
|
||||||
|
HINTS
|
||||||
|
${VULKAN_HEADERS_INSTALL_DIR}/include
|
||||||
|
"$ENV{VULKAN_HEADERS_INSTALL_DIR}/include"
|
||||||
|
"$ENV{VULKAN_SDK}/include")
|
||||||
|
|
||||||
|
if(VulkanHeaders_INCLUDE_DIR)
|
||||||
|
get_filename_component(VULKAN_REGISTRY_PATH_HINT ${VulkanHeaders_INCLUDE_DIR} DIRECTORY)
|
||||||
|
find_path(VulkanRegistry_DIR
|
||||||
|
NAMES vk.xml
|
||||||
|
HINTS "${VULKAN_REGISTRY_PATH_HINT}/share/vulkan/registry")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(VulkanHeaders_INCLUDE_DIRS ${VulkanHeaders_INCLUDE_DIR})
|
||||||
|
set(VulkanRegistry_DIRS ${VulkanRegistry_DIR})
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(VulkanHeaders
|
||||||
|
DEFAULT_MSG
|
||||||
|
VulkanHeaders_INCLUDE_DIR)
|
||||||
|
find_package_handle_standard_args(VulkanRegistry
|
||||||
|
DEFAULT_MSG
|
||||||
|
VulkanRegistry_DIR)
|
||||||
|
|
||||||
|
mark_as_advanced(VulkanHeaders_INCLUDE_DIR VulkanRegistry_DIR)
|
||||||
21
extern/openxr/src/cmake/cmake_uninstall.cmake.in
vendored
Normal file
21
extern/openxr/src/cmake/cmake_uninstall.cmake.in
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||||
|
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||||
|
endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||||
|
|
||||||
|
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
|
||||||
|
string(REGEX REPLACE "\n" ";" files "${files}")
|
||||||
|
foreach(file ${files})
|
||||||
|
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
|
||||||
|
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||||
|
exec_program(
|
||||||
|
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
||||||
|
OUTPUT_VARIABLE rm_out
|
||||||
|
RETURN_VALUE rm_retval
|
||||||
|
)
|
||||||
|
if(NOT "${rm_retval}" STREQUAL 0)
|
||||||
|
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
|
||||||
|
endif(NOT "${rm_retval}" STREQUAL 0)
|
||||||
|
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||||
|
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
|
||||||
|
endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||||
|
endforeach(file)
|
||||||
101
extern/openxr/src/cmake/presentation.cmake
vendored
Normal file
101
extern/openxr/src/cmake/presentation.cmake
vendored
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
set(PRESENTATION_BACKENDS xlib xcb wayland)
|
||||||
|
set(PRESENTATION_BACKEND xlib CACHE STRING
|
||||||
|
"Presentation backend chosen at configure time")
|
||||||
|
set_property(CACHE PRESENTATION_BACKEND PROPERTY STRINGS
|
||||||
|
${PRESENTATION_BACKENDS})
|
||||||
|
|
||||||
|
list(FIND PRESENTATION_BACKENDS ${PRESENTATION_BACKEND} index)
|
||||||
|
if(index EQUAL -1)
|
||||||
|
message(FATAL_ERROR "Presentation backend must be one of
|
||||||
|
${PRESENTATION_BACKENDS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Using presentation backend: ${PRESENTATION_BACKEND}")
|
||||||
|
|
||||||
|
|
||||||
|
if( PRESENTATION_BACKEND MATCHES "xlib" )
|
||||||
|
find_package(X11 REQUIRED)
|
||||||
|
if ((NOT X11_Xxf86vm_LIB) OR (NOT X11_Xrandr_LIB))
|
||||||
|
message(FATAL_ERROR "OpenXR xlib backend requires Xxf86vm and Xrandr")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_definitions( -DSUPPORT_X )
|
||||||
|
add_definitions( -DOS_LINUX_XLIB )
|
||||||
|
set( XLIB_LIBRARIES
|
||||||
|
${X11_LIBRARIES}
|
||||||
|
${X11_Xxf86vm_LIB}
|
||||||
|
${X11_Xrandr_LIB} )
|
||||||
|
|
||||||
|
elseif( PRESENTATION_BACKEND MATCHES "xcb" )
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
# XCB + XCB GLX is limited to OpenGL 2.1
|
||||||
|
# add_definitions( -DOS_LINUX_XCB )
|
||||||
|
# XCB + Xlib GLX 1.3
|
||||||
|
add_definitions( -DOS_LINUX_XCB_GLX )
|
||||||
|
|
||||||
|
pkg_search_module(X11 REQUIRED x11)
|
||||||
|
pkg_search_module(XCB REQUIRED xcb)
|
||||||
|
pkg_search_module(XCB_RANDR REQUIRED xcb-randr)
|
||||||
|
pkg_search_module(XCB_KEYSYMS REQUIRED xcb-keysyms)
|
||||||
|
pkg_search_module(XCB_GLX REQUIRED xcb-glx)
|
||||||
|
pkg_search_module(XCB_DRI2 REQUIRED xcb-dri2)
|
||||||
|
pkg_search_module(XCB_ICCCM REQUIRED xcb-icccm)
|
||||||
|
|
||||||
|
set( XCB_LIBRARIES
|
||||||
|
${XCB_LIBRARIES}
|
||||||
|
${XCB_KEYSYMS_LIBRARIES}
|
||||||
|
${XCB_RANDR_LIBRARIES}
|
||||||
|
${XCB_GLX_LIBRARIES}
|
||||||
|
${XCB_DRI2_LIBRARIES}
|
||||||
|
${X11_LIBRARIES} )
|
||||||
|
|
||||||
|
elseif( PRESENTATION_BACKEND MATCHES "wayland" )
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_search_module(WAYLAND_CLIENT REQUIRED wayland-client)
|
||||||
|
pkg_search_module(WAYLAND_EGL REQUIRED wayland-egl)
|
||||||
|
pkg_search_module(WAYLAND_SCANNER REQUIRED wayland-scanner)
|
||||||
|
pkg_search_module(WAYLAND_PROTOCOLS REQUIRED wayland-protocols>=1.7)
|
||||||
|
pkg_search_module(EGL REQUIRED egl)
|
||||||
|
|
||||||
|
add_definitions( -DOS_LINUX_WAYLAND )
|
||||||
|
set( WAYLAND_LIBRARIES
|
||||||
|
${EGL_LIBRARIES}
|
||||||
|
${WAYLAND_CLIENT_LIBRARIES}
|
||||||
|
${WAYLAND_EGL_LIBRARIES} )
|
||||||
|
|
||||||
|
# generate wayland protocols
|
||||||
|
set(WAYLAND_PROTOCOLS_DIR ${CMAKE_SOURCE_DIR}/wayland-protocols/)
|
||||||
|
file(MAKE_DIRECTORY ${WAYLAND_PROTOCOLS_DIR})
|
||||||
|
|
||||||
|
pkg_get_variable(WAYLAND_PROTOCOLS_DATADIR wayland-protocols pkgdatadir)
|
||||||
|
pkg_get_variable(WAYLAND_SCANNER wayland-scanner wayland_scanner)
|
||||||
|
|
||||||
|
set(PROTOCOL xdg-shell-unstable-v6)
|
||||||
|
set(PROTOCOL_XML
|
||||||
|
${WAYLAND_PROTOCOLS_DATADIR}/unstable/xdg-shell/${PROTOCOL}.xml)
|
||||||
|
|
||||||
|
if( EXISTS ${PROTOCOL_XML} )
|
||||||
|
execute_process(COMMAND
|
||||||
|
${WAYLAND_SCANNER}
|
||||||
|
code
|
||||||
|
${PROTOCOL_XML}
|
||||||
|
${WAYLAND_PROTOCOLS_DIR}/${PROTOCOL}.c)
|
||||||
|
execute_process(COMMAND
|
||||||
|
${WAYLAND_SCANNER}
|
||||||
|
client-header
|
||||||
|
${PROTOCOL_XML}
|
||||||
|
${WAYLAND_PROTOCOLS_DIR}/${PROTOCOL}.h)
|
||||||
|
|
||||||
|
set( WAYLAND_PROTOCOL_SRC
|
||||||
|
${WAYLAND_PROTOCOLS_DIR}/${PROTOCOL}.c
|
||||||
|
${WAYLAND_PROTOCOLS_DIR}/${PROTOCOL}.h )
|
||||||
|
|
||||||
|
include_directories(${WAYLAND_PROTOCOLS_DIR})
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"xdg-shell-unstable-v6.xml not found in "
|
||||||
|
${WAYLAND_PROTOCOLS_DATADIR}
|
||||||
|
"\nYour wayland-protocols package does not "
|
||||||
|
"contain xdg-shell-unstable-v6.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
57
extern/openxr/src/common/extra_algorithms.h
vendored
Normal file
57
extern/openxr/src/common/extra_algorithms.h
vendored
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
// Copyright (c) 2019 Collabora, Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* Additional functions along the lines of the standard library algorithms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/// Like std::remove_if, except it works on associative containers and it actually removes this.
|
||||||
|
///
|
||||||
|
/// The iterator stuff in here is subtle - .erase() invalidates only that iterator, but it returns a non-invalidated iterator to the
|
||||||
|
/// next valid element which we can use instead of incrementing.
|
||||||
|
template <typename T, typename Pred>
|
||||||
|
static inline void map_erase_if(T &container, Pred &&predicate) {
|
||||||
|
for (auto it = container.begin(); it != container.end();) {
|
||||||
|
if (predicate(*it)) {
|
||||||
|
it = container.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Moves all elements matching the predicate to the end of the vector then erases them.
|
||||||
|
*
|
||||||
|
* Combines the two parts of the erase-remove idiom to simplify things and avoid accidentally using the wrong erase overload.
|
||||||
|
*/
|
||||||
|
template <typename T, typename Alloc, typename Pred>
|
||||||
|
static inline void vector_remove_if_and_erase(std::vector<T, Alloc> &vec, Pred &&predicate) {
|
||||||
|
auto b = vec.begin();
|
||||||
|
auto e = vec.end();
|
||||||
|
vec.erase(std::remove_if(b, e, std::forward<Pred>(predicate)), e);
|
||||||
|
}
|
||||||
330
extern/openxr/src/common/filesystem_utils.cpp
vendored
Normal file
330
extern/openxr/src/common/filesystem_utils.cpp
vendored
Normal file
@@ -0,0 +1,330 @@
|
|||||||
|
// Copyright (c) 2017 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017 Valve Corporation
|
||||||
|
// Copyright (c) 2017 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Authors: Mark Young <marky@lunarg.com>
|
||||||
|
// Nat Brown <natb@valvesoftware.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "filesystem_utils.hpp"
|
||||||
|
|
||||||
|
#include "platform_utils.hpp"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include "xr_dependencies.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#if defined DISABLE_STD_FILESYSTEM
|
||||||
|
#define USE_EXPERIMENTAL_FS 0
|
||||||
|
#define USE_FINAL_FS 0
|
||||||
|
|
||||||
|
#else
|
||||||
|
// If the C++ macro is set to the version containing C++17, it must support
|
||||||
|
// the final C++17 package
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
#define USE_EXPERIMENTAL_FS 0
|
||||||
|
#define USE_FINAL_FS 1
|
||||||
|
|
||||||
|
#elif defined(_MSC_VER) && _MSC_VER >= 1900
|
||||||
|
|
||||||
|
#if defined(_HAS_CXX17) && _HAS_CXX17
|
||||||
|
// When MSC supports c++17 use <filesystem> package.
|
||||||
|
#define USE_EXPERIMENTAL_FS 0
|
||||||
|
#define USE_FINAL_FS 1
|
||||||
|
#endif // !_HAS_CXX17
|
||||||
|
|
||||||
|
// Right now, GCC still only supports the experimental filesystem items starting in GCC 6
|
||||||
|
#elif (__GNUC__ >= 6)
|
||||||
|
#define USE_EXPERIMENTAL_FS 1
|
||||||
|
#define USE_FINAL_FS 0
|
||||||
|
|
||||||
|
// If Clang, check for feature support
|
||||||
|
#elif defined(__clang__) && (__cpp_lib_filesystem || __cpp_lib_experimental_filesystem)
|
||||||
|
#if __cpp_lib_filesystem
|
||||||
|
#define USE_EXPERIMENTAL_FS 0
|
||||||
|
#define USE_FINAL_FS 1
|
||||||
|
#else
|
||||||
|
#define USE_EXPERIMENTAL_FS 1
|
||||||
|
#define USE_FINAL_FS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// If all above fails, fall back to standard C++ and OS-specific items
|
||||||
|
#else
|
||||||
|
#define USE_EXPERIMENTAL_FS 0
|
||||||
|
#define USE_FINAL_FS 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USE_FINAL_FS == 1
|
||||||
|
#include <filesystem>
|
||||||
|
#define FS_PREFIX std::filesystem
|
||||||
|
#elif USE_EXPERIMENTAL_FS == 1
|
||||||
|
#include <experimental/filesystem>
|
||||||
|
#define FS_PREFIX std::experimental::filesystem
|
||||||
|
#elif defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
// Windows fallback includes
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <direct.h>
|
||||||
|
#else
|
||||||
|
// Linux/Apple fallback includes
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
#define PATH_SEPARATOR ';'
|
||||||
|
#define DIRECTORY_SYMBOL '\\'
|
||||||
|
#else
|
||||||
|
#define PATH_SEPARATOR ':'
|
||||||
|
#define DIRECTORY_SYMBOL '/'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (USE_FINAL_FS == 1) || (USE_EXPERIMENTAL_FS == 1)
|
||||||
|
// We can use one of the C++ filesystem packages
|
||||||
|
|
||||||
|
bool FileSysUtilsIsRegularFile(const std::string& path) { return FS_PREFIX::is_regular_file(path); }
|
||||||
|
|
||||||
|
bool FileSysUtilsIsDirectory(const std::string& path) { return FS_PREFIX::is_directory(path); }
|
||||||
|
|
||||||
|
bool FileSysUtilsPathExists(const std::string& path) { return FS_PREFIX::exists(path); }
|
||||||
|
|
||||||
|
bool FileSysUtilsIsAbsolutePath(const std::string& path) {
|
||||||
|
FS_PREFIX::path file_path(path);
|
||||||
|
return file_path.is_absolute();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsGetCurrentPath(std::string& path) {
|
||||||
|
FS_PREFIX::path cur_path = FS_PREFIX::current_path();
|
||||||
|
path = cur_path.string();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsGetParentPath(const std::string& file_path, std::string& parent_path) {
|
||||||
|
FS_PREFIX::path path_var(file_path);
|
||||||
|
parent_path = path_var.parent_path().string();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsGetAbsolutePath(const std::string& path, std::string& absolute) {
|
||||||
|
absolute = FS_PREFIX::absolute(path).string();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsCombinePaths(const std::string& parent, const std::string& child, std::string& combined) {
|
||||||
|
FS_PREFIX::path parent_path(parent);
|
||||||
|
FS_PREFIX::path child_path(child);
|
||||||
|
FS_PREFIX::path full_path = parent_path / child_path;
|
||||||
|
combined = full_path.string();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsParsePathList(std::string& path_list, std::vector<std::string>& paths) {
|
||||||
|
std::string::size_type start = 0;
|
||||||
|
std::string::size_type location = path_list.find(PATH_SEPARATOR);
|
||||||
|
while (location != std::string::npos) {
|
||||||
|
paths.push_back(path_list.substr(start, location));
|
||||||
|
start = location + 1;
|
||||||
|
location = path_list.find(PATH_SEPARATOR, start);
|
||||||
|
}
|
||||||
|
paths.push_back(path_list.substr(start, location));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsFindFilesInPath(const std::string& path, std::vector<std::string>& files) {
|
||||||
|
for (auto& dir_iter : FS_PREFIX::directory_iterator(path)) {
|
||||||
|
files.push_back(dir_iter.path().filename().string());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(XR_OS_WINDOWS)
|
||||||
|
|
||||||
|
// For pre C++17 compiler that doesn't support experimental filesystem
|
||||||
|
#include <shlwapi.h>
|
||||||
|
|
||||||
|
bool FileSysUtilsIsRegularFile(const std::string& path) { return (1 != PathIsDirectoryW(utf8_to_wide(path).c_str())); }
|
||||||
|
|
||||||
|
bool FileSysUtilsIsDirectory(const std::string& path) { return (1 == PathIsDirectoryW(utf8_to_wide(path).c_str())); }
|
||||||
|
|
||||||
|
bool FileSysUtilsPathExists(const std::string& path) { return (1 == PathFileExistsW(utf8_to_wide(path).c_str())); }
|
||||||
|
|
||||||
|
bool FileSysUtilsIsAbsolutePath(const std::string& path) {
|
||||||
|
if ((path[0] == '\\') || (path[1] == ':' && (path[2] == '\\' || path[2] == '/'))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsGetCurrentPath(std::string& path) {
|
||||||
|
wchar_t tmp_path[MAX_PATH];
|
||||||
|
if (nullptr != _wgetcwd(tmp_path, MAX_PATH - 1)) {
|
||||||
|
path = wide_to_utf8(tmp_path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsGetParentPath(const std::string& file_path, std::string& parent_path) {
|
||||||
|
std::string full_path;
|
||||||
|
if (FileSysUtilsGetAbsolutePath(file_path, full_path)) {
|
||||||
|
std::string::size_type lastSeperator = full_path.find_last_of(DIRECTORY_SYMBOL);
|
||||||
|
parent_path = (lastSeperator == 0) ? full_path : full_path.substr(0, lastSeperator);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsGetAbsolutePath(const std::string& path, std::string& absolute) {
|
||||||
|
wchar_t tmp_path[MAX_PATH];
|
||||||
|
if (0 != GetFullPathNameW(utf8_to_wide(path).c_str(), MAX_PATH, tmp_path, NULL)) {
|
||||||
|
absolute = wide_to_utf8(tmp_path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsCombinePaths(const std::string& parent, const std::string& child, std::string& combined) {
|
||||||
|
std::string::size_type parent_len = parent.length();
|
||||||
|
if (0 == parent_len || "." == parent || ".\\" == parent || "./" == parent) {
|
||||||
|
combined = child;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
char last_char = parent[parent_len - 1];
|
||||||
|
if (last_char == DIRECTORY_SYMBOL) {
|
||||||
|
parent_len--;
|
||||||
|
}
|
||||||
|
combined = parent.substr(0, parent_len) + DIRECTORY_SYMBOL + child;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsParsePathList(std::string& path_list, std::vector<std::string>& paths) {
|
||||||
|
std::string::size_type start = 0;
|
||||||
|
std::string::size_type location = path_list.find(PATH_SEPARATOR);
|
||||||
|
while (location != std::string::npos) {
|
||||||
|
paths.push_back(path_list.substr(start, location));
|
||||||
|
start = location + 1;
|
||||||
|
location = path_list.find(PATH_SEPARATOR, start);
|
||||||
|
}
|
||||||
|
paths.push_back(path_list.substr(start, location));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsFindFilesInPath(const std::string& path, std::vector<std::string>& files) {
|
||||||
|
WIN32_FIND_DATAW file_data;
|
||||||
|
HANDLE file_handle = FindFirstFileW(utf8_to_wide(path).c_str(), &file_data);
|
||||||
|
if (file_handle != INVALID_HANDLE_VALUE) {
|
||||||
|
do {
|
||||||
|
if (!(file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||||
|
files.push_back(wide_to_utf8(file_data.cFileName));
|
||||||
|
}
|
||||||
|
} while (FindNextFileW(file_handle, &file_data));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // XR_OS_LINUX/XR_OS_APPLE fallback
|
||||||
|
|
||||||
|
// simple POSIX-compatible implementation of the <filesystem> pieces used by OpenXR
|
||||||
|
|
||||||
|
bool FileSysUtilsIsRegularFile(const std::string& path) {
|
||||||
|
struct stat path_stat;
|
||||||
|
stat(path.c_str(), &path_stat);
|
||||||
|
return S_ISREG(path_stat.st_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsIsDirectory(const std::string& path) {
|
||||||
|
struct stat path_stat;
|
||||||
|
stat(path.c_str(), &path_stat);
|
||||||
|
return S_ISDIR(path_stat.st_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsPathExists(const std::string& path) { return (access(path.c_str(), F_OK) != -1); }
|
||||||
|
|
||||||
|
bool FileSysUtilsIsAbsolutePath(const std::string& path) { return (path[0] == DIRECTORY_SYMBOL); }
|
||||||
|
|
||||||
|
bool FileSysUtilsGetCurrentPath(std::string& path) {
|
||||||
|
char tmp_path[PATH_MAX];
|
||||||
|
if (nullptr != getcwd(tmp_path, PATH_MAX - 1)) {
|
||||||
|
path = tmp_path;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsGetParentPath(const std::string& file_path, std::string& parent_path) {
|
||||||
|
std::string full_path;
|
||||||
|
if (FileSysUtilsGetAbsolutePath(file_path, full_path)) {
|
||||||
|
std::string::size_type lastSeperator = full_path.find_last_of(DIRECTORY_SYMBOL);
|
||||||
|
parent_path = (lastSeperator == 0) ? full_path : full_path.substr(0, lastSeperator);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsGetAbsolutePath(const std::string& path, std::string& absolute) {
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
if (nullptr != realpath(path.c_str(), buf)) {
|
||||||
|
absolute = buf;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsCombinePaths(const std::string& parent, const std::string& child, std::string& combined) {
|
||||||
|
std::string::size_type parent_len = parent.length();
|
||||||
|
if (0 == parent_len || "." == parent || "./" == parent) {
|
||||||
|
combined = child;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
char last_char = parent[parent_len - 1];
|
||||||
|
if (last_char == DIRECTORY_SYMBOL) {
|
||||||
|
parent_len--;
|
||||||
|
}
|
||||||
|
combined = parent.substr(0, parent_len) + DIRECTORY_SYMBOL + child;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsParsePathList(std::string& path_list, std::vector<std::string>& paths) {
|
||||||
|
std::string::size_type start = 0;
|
||||||
|
std::string::size_type location = path_list.find(PATH_SEPARATOR);
|
||||||
|
while (location != std::string::npos) {
|
||||||
|
paths.push_back(path_list.substr(start, location));
|
||||||
|
start = location + 1;
|
||||||
|
location = path_list.find(PATH_SEPARATOR, start);
|
||||||
|
}
|
||||||
|
paths.push_back(path_list.substr(start, location));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsFindFilesInPath(const std::string& path, std::vector<std::string>& files) {
|
||||||
|
DIR* dir = opendir(path.c_str());
|
||||||
|
if (dir == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
struct dirent* entry;
|
||||||
|
while ((entry = readdir(dir)) != nullptr) {
|
||||||
|
files.emplace_back(entry->d_name);
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
53
extern/openxr/src/common/filesystem_utils.hpp
vendored
Normal file
53
extern/openxr/src/common/filesystem_utils.hpp
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
// Copyright (c) 2017 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017 Valve Corporation
|
||||||
|
// Copyright (c) 2017 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Determine if the path indicates a regular file (not a directory or symbolic link)
|
||||||
|
bool FileSysUtilsIsRegularFile(const std::string& path);
|
||||||
|
|
||||||
|
// Determine if the path indicates a directory
|
||||||
|
bool FileSysUtilsIsDirectory(const std::string& path);
|
||||||
|
|
||||||
|
// Determine if the provided path exists on the filesystem
|
||||||
|
bool FileSysUtilsPathExists(const std::string& path);
|
||||||
|
|
||||||
|
// Get the current directory of the executable
|
||||||
|
bool FileSysUtilsGetCurrentPath(std::string& path);
|
||||||
|
|
||||||
|
// Get the parent path of a file
|
||||||
|
bool FileSysUtilsGetParentPath(const std::string& file_path, std::string& parent_path);
|
||||||
|
|
||||||
|
// Determine if the provided path is an absolute path
|
||||||
|
bool FileSysUtilsIsAbsolutePath(const std::string& path);
|
||||||
|
|
||||||
|
// Get the absolute path for a provided file
|
||||||
|
bool FileSysUtilsGetAbsolutePath(const std::string& path, std::string& absolute);
|
||||||
|
|
||||||
|
// Combine a parent and child directory
|
||||||
|
bool FileSysUtilsCombinePaths(const std::string& parent, const std::string& child, std::string& combined);
|
||||||
|
|
||||||
|
// Parse out individual paths in a path list
|
||||||
|
bool FileSysUtilsParsePathList(std::string& path_list, std::vector<std::string>& paths);
|
||||||
|
|
||||||
|
// Record all the filenames for files found in the provided path.
|
||||||
|
bool FileSysUtilsFindFilesInPath(const std::string& path, std::vector<std::string>& files);
|
||||||
44
extern/openxr/src/common/hex_and_handles.cpp
vendored
Normal file
44
extern/openxr/src/common/hex_and_handles.cpp
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
// Copyright (c) 2019 Collabora, Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* Implementations of the include-requiring hex conversion functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hex_and_handles.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
std::string Uint64ToHexString(uint64_t val) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "0x";
|
||||||
|
oss << std::hex << std::setw(16) << std::setfill('0') << val;
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Uint32ToHexString(uint32_t val) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "0x";
|
||||||
|
oss << std::hex << std::setw(8) << std::setfill('0') << val;
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
108
extern/openxr/src/common/hex_and_handles.h
vendored
Normal file
108
extern/openxr/src/common/hex_and_handles.h
vendored
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
// Copyright (c) 2019 Collabora, Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* Some utilities, primarily for working with OpenXR handles in a generic way.
|
||||||
|
*
|
||||||
|
* Most are trivial and inlined by default, but a few involve some non-trivial standard headers:
|
||||||
|
* the various `...ToHexString`functions.
|
||||||
|
* If you want those, make sure your build includes the corresponding hex_and_handles.cpp file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#if XR_PTR_SIZE == 8
|
||||||
|
/// Convert a handle into a same-sized integer.
|
||||||
|
template <typename T>
|
||||||
|
static inline uint64_t MakeHandleGeneric(T handle) {
|
||||||
|
return reinterpret_cast<uint64_t>(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Treat an integer as a handle
|
||||||
|
template <typename T>
|
||||||
|
static inline T& TreatIntegerAsHandle(uint64_t& handle) {
|
||||||
|
return reinterpret_cast<T&>(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @overload
|
||||||
|
template <typename T>
|
||||||
|
static inline T const& TreatIntegerAsHandle(uint64_t const& handle) {
|
||||||
|
return reinterpret_cast<T const&>(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Does a correctly-sized integer represent a null handle?
|
||||||
|
static inline bool IsIntegerNullHandle(uint64_t handle) { return XR_NULL_HANDLE == reinterpret_cast<void*>(handle); }
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/// Convert a handle into a same-sized integer: no-op on 32-bit systems
|
||||||
|
static inline uint64_t MakeHandleGeneric(uint64_t handle) { return handle; }
|
||||||
|
|
||||||
|
/// Treat an integer as a handle: no-op on 32-bit systems
|
||||||
|
template <typename T>
|
||||||
|
static inline T& TreatIntegerAsHandle(uint64_t& handle) {
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @overload
|
||||||
|
template <typename T>
|
||||||
|
static inline T const& TreatIntegerAsHandle(uint64_t const& handle) {
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Does a correctly-sized integer represent a null handle?
|
||||||
|
static inline bool IsIntegerNullHandle(uint64_t handle) { return XR_NULL_HANDLE == handle; }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Turns a uint64_t into a string formatted as hex.
|
||||||
|
///
|
||||||
|
/// The core of the HandleToHexString implementation is in here.
|
||||||
|
std::string Uint64ToHexString(uint64_t val);
|
||||||
|
|
||||||
|
/// Turns a uint32_t into a string formatted as hex.
|
||||||
|
std::string Uint32ToHexString(uint32_t val);
|
||||||
|
|
||||||
|
/// Turns an OpenXR handle into a string formatted as hex.
|
||||||
|
template <typename T>
|
||||||
|
static inline std::string HandleToHexString(T handle) {
|
||||||
|
return Uint64ToHexString(MakeHandleGeneric(handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if XR_PTR_SIZE == 8
|
||||||
|
/// Turns a pointer-sized integer into a string formatted as hex.
|
||||||
|
static inline std::string UintptrToHexString(uintptr_t val) { return Uint64ToHexString(val); }
|
||||||
|
#else
|
||||||
|
/// Turns a pointer-sized integer into a string formatted as hex.
|
||||||
|
static inline std::string UintptrToHexString(uintptr_t val) { return Uint32ToHexString(val); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Convert a pointer to a string formatted as hex.
|
||||||
|
template <typename T>
|
||||||
|
static inline std::string PointerToHexString(T const* ptr) {
|
||||||
|
return UintptrToHexString(reinterpret_cast<uintptr_t>(ptr));
|
||||||
|
}
|
||||||
122
extern/openxr/src/common/loader_interfaces.h
vendored
Normal file
122
extern/openxr/src/common/loader_interfaces.h
vendored
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
// Copyright (c) 2017 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017 Valve Corporation
|
||||||
|
// Copyright (c) 2017 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Forward declare.
|
||||||
|
typedef struct XrApiLayerCreateInfo XrApiLayerCreateInfo;
|
||||||
|
|
||||||
|
// Function pointer prototype for the xrCreateApiLayerInstance function used in place of xrCreateInstance.
|
||||||
|
// This function allows us to pass special API layer information to each layer during the process of creating an Instance.
|
||||||
|
typedef XrResult(XRAPI_PTR *PFN_xrCreateApiLayerInstance)(const XrInstanceCreateInfo *info,
|
||||||
|
const XrApiLayerCreateInfo *apiLayerInfo, XrInstance *instance);
|
||||||
|
|
||||||
|
// Loader/API Layer Interface versions
|
||||||
|
// 1 - First version, introduces negotiation structure and functions
|
||||||
|
#define XR_CURRENT_LOADER_API_LAYER_VERSION 1
|
||||||
|
|
||||||
|
// Loader/Runtime Interface versions
|
||||||
|
// 1 - First version, introduces negotiation structure and functions
|
||||||
|
#define XR_CURRENT_LOADER_RUNTIME_VERSION 1
|
||||||
|
|
||||||
|
// Version negotiation values
|
||||||
|
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;
|
||||||
|
|
||||||
|
#define XR_LOADER_INFO_STRUCT_VERSION 1
|
||||||
|
typedef struct 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;
|
||||||
|
} XrNegotiateLoaderInfo;
|
||||||
|
|
||||||
|
#define XR_API_LAYER_INFO_STRUCT_VERSION 1
|
||||||
|
typedef struct XrNegotiateApiLayerRequest {
|
||||||
|
XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST
|
||||||
|
uint32_t structVersion; // XR_API_LAYER_INFO_STRUCT_VERSION
|
||||||
|
size_t structSize; // sizeof(XrNegotiateApiLayerRequest)
|
||||||
|
uint32_t layerInterfaceVersion; // CURRENT_LOADER_API_LAYER_VERSION
|
||||||
|
XrVersion layerApiVersion;
|
||||||
|
PFN_xrGetInstanceProcAddr getInstanceProcAddr;
|
||||||
|
PFN_xrCreateApiLayerInstance createApiLayerInstance;
|
||||||
|
} XrNegotiateApiLayerRequest;
|
||||||
|
|
||||||
|
#define XR_RUNTIME_INFO_STRUCT_VERSION 1
|
||||||
|
typedef struct 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;
|
||||||
|
} XrNegotiateRuntimeRequest;
|
||||||
|
|
||||||
|
// Function used to negotiate an interface betewen the loader and an API layer. Each library exposing one or
|
||||||
|
// more API layers needs to expose at least this function.
|
||||||
|
typedef XrResult(XRAPI_PTR *PFN_xrNegotiateLoaderApiLayerInterface)(const XrNegotiateLoaderInfo *loaderInfo,
|
||||||
|
const char *apiLayerName,
|
||||||
|
XrNegotiateApiLayerRequest *apiLayerRequest);
|
||||||
|
|
||||||
|
// Function used to negotiate an interface betewen the loader and a runtime. Each runtime should expose
|
||||||
|
// at least this function.
|
||||||
|
typedef XrResult(XRAPI_PTR *PFN_xrNegotiateLoaderRuntimeInterface)(const XrNegotiateLoaderInfo *loaderInfo,
|
||||||
|
XrNegotiateRuntimeRequest *runtimeRequest);
|
||||||
|
|
||||||
|
// Forward declare.
|
||||||
|
typedef struct XrApiLayerNextInfo XrApiLayerNextInfo;
|
||||||
|
|
||||||
|
#define XR_API_LAYER_NEXT_INFO_STRUCT_VERSION 1
|
||||||
|
struct XrApiLayerNextInfo {
|
||||||
|
XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO
|
||||||
|
uint32_t structVersion; // XR_API_LAYER_NEXT_INFO_STRUCT_VERSION
|
||||||
|
size_t structSize; // sizeof(XrApiLayerNextInfo)
|
||||||
|
char layerName[XR_MAX_API_LAYER_NAME_SIZE]; // Name of API layer which should receive this info
|
||||||
|
PFN_xrGetInstanceProcAddr nextGetInstanceProcAddr; // Pointer to next API layer's xrGetInstanceProcAddr
|
||||||
|
PFN_xrCreateApiLayerInstance nextCreateApiLayerInstance; // Pointer to next API layer's xrCreateApiLayerInstance
|
||||||
|
XrApiLayerNextInfo *next; // Pointer to the next API layer info in the sequence
|
||||||
|
};
|
||||||
|
|
||||||
|
#define XR_API_LAYER_MAX_SETTINGS_PATH_SIZE 512
|
||||||
|
#define XR_API_LAYER_CREATE_INFO_STRUCT_VERSION 1
|
||||||
|
typedef struct XrApiLayerCreateInfo {
|
||||||
|
XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO
|
||||||
|
uint32_t structVersion; // XR_API_LAYER_CREATE_INFO_STRUCT_VERSION
|
||||||
|
size_t structSize; // sizeof(XrApiLayerCreateInfo)
|
||||||
|
void *loaderInstance; // Pointer to the LoaderInstance class
|
||||||
|
char settings_file_location[XR_API_LAYER_MAX_SETTINGS_PATH_SIZE]; // Location to the found settings file (or empty '\0')
|
||||||
|
XrApiLayerNextInfo *nextInfo; // Pointer to the next API layer's Info
|
||||||
|
} XrApiLayerCreateInfo;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
221
extern/openxr/src/common/platform_utils.hpp
vendored
Normal file
221
extern/openxr/src/common/platform_utils.hpp
vendored
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
// Copyright (c) 2017 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017 Valve Corporation
|
||||||
|
// Copyright (c) 2017 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "xr_dependencies.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#if defined(XR_OS_LINUX)
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <iostream>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// This is a CMake generated file with #defines for any functions/includes
|
||||||
|
// that it found present. This is currently necessary to properly determine
|
||||||
|
// if secure_getenv or __secure_getenv are present
|
||||||
|
#if !defined(OPENXR_NON_CMAKE_BUILD)
|
||||||
|
#include "common_cmake_config.h"
|
||||||
|
#endif // !defined(OPENXR_NON_CMAKE_BUILD)
|
||||||
|
|
||||||
|
// Environment variables
|
||||||
|
#if defined(XR_OS_LINUX)
|
||||||
|
|
||||||
|
static inline char* PlatformUtilsGetEnv(const char* name) { return getenv(name); }
|
||||||
|
|
||||||
|
static inline char* PlatformUtilsGetSecureEnv(const char* name) {
|
||||||
|
#ifdef HAVE_SECURE_GETENV
|
||||||
|
return secure_getenv(name);
|
||||||
|
#elif defined(HAVE___SECURE_GETENV)
|
||||||
|
return __secure_getenv(name);
|
||||||
|
#else
|
||||||
|
#pragma message( \
|
||||||
|
"Warning: Falling back to non-secure getenv for environmental" \
|
||||||
|
"lookups! Consider updating to a different libc.")
|
||||||
|
|
||||||
|
return PlatformUtilsGetEnv(name);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void PlatformUtilsFreeEnv(const char* val) {
|
||||||
|
// No freeing of memory necessary for Linux, but we should at least touch
|
||||||
|
// the val and inst pointers to get rid of compiler warnings.
|
||||||
|
(void)val;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(XR_OS_APPLE)
|
||||||
|
|
||||||
|
static inline char *PlatformUtilsGetEnv(const char *name) { return getenv(name); }
|
||||||
|
|
||||||
|
static inline char *PlatformUtilsGetSecureEnv(const char *name) {
|
||||||
|
#ifdef HAVE_SECURE_GETENV
|
||||||
|
return secure_getenv(name);
|
||||||
|
#elif defined(HAVE___SECURE_GETENV)
|
||||||
|
return __secure_getenv(name);
|
||||||
|
#else
|
||||||
|
#pragma message( \
|
||||||
|
"Warning: Falling back to non-secure getenv for environmental" \
|
||||||
|
"lookups! Consider updating to a different libc.")
|
||||||
|
|
||||||
|
return PlatformUtilsGetEnv(name);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void PlatformUtilsFreeEnv(char *val) {
|
||||||
|
// No freeing of memory necessary for Linux, but we should at least touch
|
||||||
|
// the val and inst pointers to get rid of compiler warnings.
|
||||||
|
(void)val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prefix for the Apple global runtime JSON file name
|
||||||
|
static const std::string rt_dir_prefix = "/usr/local/share/openxr/";
|
||||||
|
static const std::string rt_filename = "/active_runtime.json";
|
||||||
|
|
||||||
|
static inline bool PlatformGetGlobalRuntimeFileName(uint16_t major_version, std::string &file_name) {
|
||||||
|
file_name = rt_dir_prefix;
|
||||||
|
file_name += std::to_string(major_version);
|
||||||
|
file_name += rt_filename;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(XR_OS_WINDOWS)
|
||||||
|
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
inline void LogError(const std::string& error) { OutputDebugStringA(error.c_str()); }
|
||||||
|
#else
|
||||||
|
#define LogError(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline std::wstring utf8_to_wide(const std::string& utf8Text) {
|
||||||
|
if (utf8Text.empty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring wideText;
|
||||||
|
const int wideLength = ::MultiByteToWideChar(CP_UTF8, 0, utf8Text.data(), (int)utf8Text.size(), nullptr, 0);
|
||||||
|
if (wideLength == 0) {
|
||||||
|
LogError("utf8_to_wide get size error: " + std::to_string(::GetLastError()));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// MultiByteToWideChar returns number of chars of the input buffer, regardless of null terminitor
|
||||||
|
wideText.resize(wideLength, 0);
|
||||||
|
wchar_t* wideString = const_cast<wchar_t*>(wideText.data()); // mutable data() only exists in c++17
|
||||||
|
const int length = ::MultiByteToWideChar(CP_UTF8, 0, utf8Text.data(), (int)utf8Text.size(), wideString, wideLength);
|
||||||
|
if (length != wideLength) {
|
||||||
|
LogError("utf8_to_wide convert string error: " + std::to_string(::GetLastError()));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return wideText;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string wide_to_utf8(const std::wstring& wideText) {
|
||||||
|
if (wideText.empty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string narrowText;
|
||||||
|
int narrowLength = ::WideCharToMultiByte(CP_UTF8, 0, wideText.data(), (int)wideText.size(), nullptr, 0, nullptr, nullptr);
|
||||||
|
if (narrowLength == 0) {
|
||||||
|
LogError("wide_to_utf8 get size error: " + std::to_string(::GetLastError()));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// WideCharToMultiByte returns number of chars of the input buffer, regardless of null terminitor
|
||||||
|
narrowText.resize(narrowLength, 0);
|
||||||
|
char* narrowString = const_cast<char*>(narrowText.data()); // mutable data() only exists in c++17
|
||||||
|
const int length =
|
||||||
|
::WideCharToMultiByte(CP_UTF8, 0, wideText.data(), (int)wideText.size(), narrowString, narrowLength, nullptr, nullptr);
|
||||||
|
if (length != narrowLength) {
|
||||||
|
LogError("wide_to_utf8 convert string error: " + std::to_string(::GetLastError()));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return narrowText;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline char* PlatformUtilsGetEnv(const char* name) {
|
||||||
|
const std::wstring wname = utf8_to_wide(name);
|
||||||
|
const DWORD valSize = ::GetEnvironmentVariableW(wname.c_str(), nullptr, 0);
|
||||||
|
|
||||||
|
// GetEnvironmentVariable returns 0 when environment variable does not exist
|
||||||
|
if (valSize == 0) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEnvironmentVariable returns size including null terminator for "query size" call.
|
||||||
|
std::wstring wValue(valSize, 0);
|
||||||
|
wchar_t* wValueData = const_cast<wchar_t*>(wValue.data()); // mutable data() only exists in c++17
|
||||||
|
|
||||||
|
// GetEnvironmentVariable returns string length, excluding null terminator for "get value" call.
|
||||||
|
const int length = ::GetEnvironmentVariableW(wname.c_str(), wValueData, (DWORD)wValue.size());
|
||||||
|
if (!length) {
|
||||||
|
LogError("GetEnvironmentVariable get value error: " + std::to_string(::GetLastError()));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string value = wide_to_utf8(wValue);
|
||||||
|
|
||||||
|
// Allocate the space necessary for the result
|
||||||
|
char* retVal = new char[value.size() + 1]{};
|
||||||
|
value.copy(retVal, value.size());
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline char* PlatformUtilsGetSecureEnv(const char* name) {
|
||||||
|
// No secure version for Windows as far as I know
|
||||||
|
return PlatformUtilsGetEnv(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void PlatformUtilsFreeEnv(char* val) {
|
||||||
|
if (nullptr != val) {
|
||||||
|
delete[] val;
|
||||||
|
val = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // Not Linux or Windows
|
||||||
|
|
||||||
|
static inline char *PlatformUtilsGetEnv(const char *name) {
|
||||||
|
// Stub func
|
||||||
|
(void)name;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline char *PlatformUtilsGetSecureEnv(const char *name) {
|
||||||
|
// Stub func
|
||||||
|
(void)name;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void PlatformUtilsFreeEnv(char *val) {
|
||||||
|
// Stub func
|
||||||
|
(void)val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool PlatformGetGlobalRuntimeFileName(uint16_t major_version, std::string &file_name) {
|
||||||
|
// Stub func
|
||||||
|
(void)major_version;
|
||||||
|
(void)file_name;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
78
extern/openxr/src/common/xr_dependencies.h
vendored
Normal file
78
extern/openxr/src/common/xr_dependencies.h
vendored
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
// Copyright (c) 2018-2019 The Khronos Group Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// This file includes headers with types which openxr.h depends on in order
|
||||||
|
// to compile when platforms, graphics apis, and the like are enabled.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_ANDROID
|
||||||
|
#include <android/native_window.h>
|
||||||
|
#endif // XR_USE_PLATFORM_ANDROID
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_WIN32
|
||||||
|
|
||||||
|
#include <winapifamily.h>
|
||||||
|
#if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM))
|
||||||
|
// Enable desktop partition APIs, such as RegOpenKeyEx, LoadLibraryEx, PathFileExists etc.
|
||||||
|
#undef WINAPI_PARTITION_DESKTOP
|
||||||
|
#define WINAPI_PARTITION_DESKTOP 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NOMINMAX
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#endif // XR_USE_PLATFORM_WIN32
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_D3D11
|
||||||
|
#include <d3d11.h>
|
||||||
|
#endif // XR_USE_GRAPHICS_API_D3D11
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_D3D12
|
||||||
|
#include <d3d12.h>
|
||||||
|
#endif // XR_USE_GRAPHICS_API_D3D12
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_XLIB
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
#endif // XR_USE_PLATFORM_XLIB
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_XCB
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
#endif // XR_USE_PLATFORM_XCB
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_OPENGL
|
||||||
|
#if defined(XR_USE_PLATFORM_XLIB) || defined(XR_USE_PLATFORM_XCB)
|
||||||
|
#include <GL/glx.h>
|
||||||
|
#endif // (XR_USE_PLATFORM_XLIB || XR_USE_PLATFORM_XCB)
|
||||||
|
#ifdef XR_USE_PLATFORM_XCB
|
||||||
|
#include <xcb/glx.h>
|
||||||
|
#endif // XR_USE_PLATFORM_XCB
|
||||||
|
#ifdef XR_USE_PLATFORM_MACOS
|
||||||
|
#include <CL/cl_gl_ext.h>
|
||||||
|
#endif // XR_USE_PLATFORM_MACOS
|
||||||
|
#endif // XR_USE_GRAPHICS_API_OPENGL
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#endif // XR_USE_GRAPHICS_API_OPENGL_ES
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
#endif // XR_USE_GRAPHICS_API_VULKAN
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_WAYLAND
|
||||||
|
#include "wayland-client.h"
|
||||||
|
#endif // XR_USE_PLATFORM_WAYLAND
|
||||||
773
extern/openxr/src/common/xr_linear.h
vendored
Normal file
773
extern/openxr/src/common/xr_linear.h
vendored
Normal file
@@ -0,0 +1,773 @@
|
|||||||
|
// Copyright (c) 2017 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2016 Oculus VR, LLC.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: J.M.P. van Waveren
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef XR_LINEAR_H_
|
||||||
|
#define XR_LINEAR_H_
|
||||||
|
|
||||||
|
#if defined(OS_LINUX_XCB) || defined(OS_LINUX_XCB_GLX) || defined(OS_LINUX_WAYLAND)
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||||
|
#pragma clang diagnostic ignored "-Wunused-function"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
================================================================================================
|
||||||
|
|
||||||
|
Description : Vector, matrix and quaternion math.
|
||||||
|
Author : J.M.P. van Waveren
|
||||||
|
Date : 12/10/2016
|
||||||
|
Language : C99
|
||||||
|
Format : Indent 4 spaces - no tabs.
|
||||||
|
Copyright : Copyright (c) 2016 Oculus VR, LLC. All Rights reserved.
|
||||||
|
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
===========
|
||||||
|
|
||||||
|
All matrices are column-major.
|
||||||
|
|
||||||
|
INTERFACE
|
||||||
|
=========
|
||||||
|
|
||||||
|
XrVector2f
|
||||||
|
XrVector3f
|
||||||
|
XrVector4f
|
||||||
|
XrQuaternionf
|
||||||
|
XrMatrix4x4f
|
||||||
|
|
||||||
|
inline static void XrVector3f_Set(XrVector3f* v, const float value);
|
||||||
|
inline static void XrVector3f_Add(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
|
||||||
|
inline static void XrVector3f_Sub(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
|
||||||
|
inline static void XrVector3f_Min(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
|
||||||
|
inline static void XrVector3f_Max(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
|
||||||
|
inline static void XrVector3f_Decay(XrVector3f* result, const XrVector3f* a, const float value);
|
||||||
|
inline static void XrVector3f_Lerp(XrVector3f* result, const XrVector3f* a, const XrVector3f* b, const float fraction);
|
||||||
|
inline static void XrVector3f_Normalize(XrVector3f* v);
|
||||||
|
inline static float XrVector3f_Length(const XrVector3f* v);
|
||||||
|
|
||||||
|
inline static void XrQuaternionf_Lerp(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b, const float fraction);
|
||||||
|
|
||||||
|
inline static void XrMatrix4x4f_CreateIdentity(XrMatrix4x4f* result);
|
||||||
|
inline static void XrMatrix4x4f_CreateTranslation(XrMatrix4x4f* result, const float x, const float y, const float z);
|
||||||
|
inline static void XrMatrix4x4f_CreateRotation(XrMatrix4x4f* result, const float degreesX, const float degreesY,
|
||||||
|
const float degreesZ);
|
||||||
|
inline static void XrMatrix4x4f_CreateScale(XrMatrix4x4f* result, const float x, const float y, const float z);
|
||||||
|
inline static void XrMatrix4x4f_CreateTranslationRotationScale(XrMatrix4x4f* result, const XrVector3f* translation,
|
||||||
|
const XrQuaternionf* rotation, const XrVector3f* scale);
|
||||||
|
inline static void XrMatrix4x4f_CreateProjection(XrMatrix4x4f* result, const float tanAngleLeft, const float tanAngleRight,
|
||||||
|
const float tanAngleUp, float const tanAngleDown, const float nearZ,
|
||||||
|
const float farZ);
|
||||||
|
inline static void XrMatrix4x4f_CreateProjectionFov(XrMatrix4x4f* result, const float fovDegreesLeft, const float fovDegreesRight,
|
||||||
|
const float fovDegreeUp, const float fovDegreesDown, const float nearZ,
|
||||||
|
const float farZ);
|
||||||
|
inline static void XrMatrix4x4f_CreateFromQuaternion(XrMatrix4x4f* result, const XrQuaternionf* src);
|
||||||
|
inline static void XrMatrix4x4f_CreateOffsetScaleForBounds(XrMatrix4x4f* result, const XrMatrix4x4f* matrix, const XrVector3f* mins,
|
||||||
|
const XrVector3f* maxs);
|
||||||
|
|
||||||
|
inline static bool XrMatrix4x4f_IsAffine(const XrMatrix4x4f* matrix, const float epsilon);
|
||||||
|
inline static bool XrMatrix4x4f_IsOrthogonal(const XrMatrix4x4f* matrix, const float epsilon);
|
||||||
|
inline static bool XrMatrix4x4f_IsOrthonormal(const XrMatrix4x4f* matrix, const float epsilon);
|
||||||
|
inline static bool XrMatrix4x4f_IsRigidBody(const XrMatrix4x4f* matrix, const float epsilon);
|
||||||
|
|
||||||
|
inline static void XrMatrix4x4f_GetTranslation(XrVector3f* result, const XrMatrix4x4f* src);
|
||||||
|
inline static void XrMatrix4x4f_GetRotation(XrQuaternionf* result, const XrMatrix4x4f* src);
|
||||||
|
inline static void XrMatrix4x4f_GetScale(XrVector3f* result, const XrMatrix4x4f* src);
|
||||||
|
|
||||||
|
inline static void XrMatrix4x4f_Multiply(XrMatrix4x4f* result, const XrMatrix4x4f* a, const XrMatrix4x4f* b);
|
||||||
|
inline static void XrMatrix4x4f_Transpose(XrMatrix4x4f* result, const XrMatrix4x4f* src);
|
||||||
|
inline static void XrMatrix4x4f_Invert(XrMatrix4x4f* result, const XrMatrix4x4f* src);
|
||||||
|
inline static void XrMatrix4x4f_InvertRigidBody(XrMatrix4x4f* result, const XrMatrix4x4f* src);
|
||||||
|
|
||||||
|
inline static void XrMatrix4x4f_TransformVector3f(XrVector3f* result, const XrMatrix4x4f* m, const XrVector3f* v);
|
||||||
|
inline static void XrMatrix4x4f_TransformVector4f(XrVector4f* result, const XrMatrix4x4f* m, const XrVector4f* v);
|
||||||
|
|
||||||
|
inline static void XrMatrix4x4f_TransformBounds(XrVector3f* resultMins, XrVector3f* resultMaxs, const XrMatrix4x4f* matrix,
|
||||||
|
const XrVector3f* mins, const XrVector3f* maxs);
|
||||||
|
inline static bool XrMatrix4x4f_CullBounds(const XrMatrix4x4f* mvp, const XrVector3f* mins, const XrVector3f* maxs);
|
||||||
|
|
||||||
|
================================================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define MATH_PI 3.14159265358979323846f
|
||||||
|
|
||||||
|
#define DEFAULT_NEAR_Z 0.015625f // exact floating point representation
|
||||||
|
#define INFINITE_FAR_Z 0.0f
|
||||||
|
|
||||||
|
static const XrColor4f XrColorRed = {1.0f, 0.0f, 0.0f, 1.0f};
|
||||||
|
static const XrColor4f XrColorGreen = {0.0f, 1.0f, 0.0f, 1.0f};
|
||||||
|
static const XrColor4f XrColorBlue = {0.0f, 0.0f, 1.0f, 1.0f};
|
||||||
|
static const XrColor4f XrColorYellow = {1.0f, 1.0f, 0.0f, 1.0f};
|
||||||
|
static const XrColor4f XrColorPurple = {1.0f, 0.0f, 1.0f, 1.0f};
|
||||||
|
static const XrColor4f XrColorCyan = {0.0f, 1.0f, 1.0f, 1.0f};
|
||||||
|
static const XrColor4f XrColorLightGrey = {0.7f, 0.7f, 0.7f, 1.0f};
|
||||||
|
static const XrColor4f XrColorDarkGrey = {0.3f, 0.3f, 0.3f, 1.0f};
|
||||||
|
|
||||||
|
enum GraphicsAPI { GRAPHICS_VULKAN, GRAPHICS_OPENGL, GRAPHICS_OPENGL_ES, GRAPHICS_D3D };
|
||||||
|
|
||||||
|
// Column-major, pre-multiplied. This type does not exist in the OpenXR API and is provided for convenience.
|
||||||
|
struct XrMatrix4x4f {
|
||||||
|
float m[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
inline static float XrRcpSqrt(const float x) {
|
||||||
|
const float SMALLEST_NON_DENORMAL = 1.1754943508222875e-038f; // ( 1U << 23 )
|
||||||
|
const float rcp = (x >= SMALLEST_NON_DENORMAL) ? 1.0f / sqrtf(x) : 1.0f;
|
||||||
|
return rcp;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void XrVector3f_Set(XrVector3f* v, const float value) {
|
||||||
|
v->x = value;
|
||||||
|
v->y = value;
|
||||||
|
v->z = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void XrVector3f_Add(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
|
||||||
|
result->x = a->x + b->x;
|
||||||
|
result->y = a->y + b->y;
|
||||||
|
result->z = a->z + b->z;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void XrVector3f_Sub(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
|
||||||
|
result->x = a->x - b->x;
|
||||||
|
result->y = a->y - b->y;
|
||||||
|
result->z = a->z - b->z;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void XrVector3f_Min(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
|
||||||
|
result->x = (a->x < b->x) ? a->x : b->x;
|
||||||
|
result->y = (a->y < b->y) ? a->y : b->y;
|
||||||
|
result->z = (a->z < b->z) ? a->z : b->z;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void XrVector3f_Max(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
|
||||||
|
result->x = (a->x > b->x) ? a->x : b->x;
|
||||||
|
result->y = (a->y > b->y) ? a->y : b->y;
|
||||||
|
result->z = (a->z > b->z) ? a->z : b->z;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void XrVector3f_Decay(XrVector3f* result, const XrVector3f* a, const float value) {
|
||||||
|
result->x = (fabsf(a->x) > value) ? ((a->x > 0.0f) ? (a->x - value) : (a->x + value)) : 0.0f;
|
||||||
|
result->y = (fabsf(a->y) > value) ? ((a->y > 0.0f) ? (a->y - value) : (a->y + value)) : 0.0f;
|
||||||
|
result->z = (fabsf(a->z) > value) ? ((a->z > 0.0f) ? (a->z - value) : (a->z + value)) : 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void XrVector3f_Lerp(XrVector3f* result, const XrVector3f* a, const XrVector3f* b, const float fraction) {
|
||||||
|
result->x = a->x + fraction * (b->x - a->x);
|
||||||
|
result->y = a->y + fraction * (b->y - a->y);
|
||||||
|
result->z = a->z + fraction * (b->z - a->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static float XrVector3f_Dot(const XrVector3f* a, const XrVector3f* b) { return a->x * b->x + a->y * b->y + a->z * b->z; }
|
||||||
|
|
||||||
|
// Compute cross product, which generates a normal vector.
|
||||||
|
// Direction vector can be determined by right-hand rule: Pointing index finder in
|
||||||
|
// direction a and middle finger in direction b, thumb will point in Cross(a, b).
|
||||||
|
inline static void XrVector3f_Cross(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
|
||||||
|
result->x = a->y * b->z - a->z * b->y;
|
||||||
|
result->y = a->z * b->x - a->x * b->z;
|
||||||
|
result->x = a->x * b->y - a->y * b->x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void XrVector3f_Normalize(XrVector3f* v) {
|
||||||
|
const float lengthRcp = XrRcpSqrt(v->x * v->x + v->y * v->y + v->z * v->z);
|
||||||
|
v->x *= lengthRcp;
|
||||||
|
v->y *= lengthRcp;
|
||||||
|
v->z *= lengthRcp;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static float XrVector3f_Length(const XrVector3f* v) { return sqrtf(v->x * v->x + v->y * v->y + v->z * v->z); }
|
||||||
|
|
||||||
|
inline static void XrQuaternionf_CreateFromAxisAngle(XrQuaternionf* result, const XrVector3f* axis, const float angleInRadians) {
|
||||||
|
float s = sinf(angleInRadians / 2.0f);
|
||||||
|
float lengthRcp = XrRcpSqrt(axis->x * axis->x + axis->y * axis->y + axis->z * axis->z);
|
||||||
|
result->x = s * axis->x * lengthRcp;
|
||||||
|
result->y = s * axis->y * lengthRcp;
|
||||||
|
result->z = s * axis->z * lengthRcp;
|
||||||
|
result->w = cosf(angleInRadians / 2.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void XrQuaternionf_Lerp(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b, const float fraction) {
|
||||||
|
const float s = a->x * b->x + a->y * b->y + a->z * b->z + a->w * b->w;
|
||||||
|
const float fa = 1.0f - fraction;
|
||||||
|
const float fb = (s < 0.0f) ? -fraction : fraction;
|
||||||
|
const float x = a->x * fa + b->x * fb;
|
||||||
|
const float y = a->y * fa + b->y * fb;
|
||||||
|
const float z = a->z * fa + b->z * fb;
|
||||||
|
const float w = a->w * fa + b->w * fb;
|
||||||
|
const float lengthRcp = XrRcpSqrt(x * x + y * y + z * z + w * w);
|
||||||
|
result->x = x * lengthRcp;
|
||||||
|
result->y = y * lengthRcp;
|
||||||
|
result->z = z * lengthRcp;
|
||||||
|
result->w = w * lengthRcp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use left-multiplication to accumulate transformations.
|
||||||
|
inline static void XrMatrix4x4f_Multiply(XrMatrix4x4f* result, const XrMatrix4x4f* a, const XrMatrix4x4f* b) {
|
||||||
|
result->m[0] = a->m[0] * b->m[0] + a->m[4] * b->m[1] + a->m[8] * b->m[2] + a->m[12] * b->m[3];
|
||||||
|
result->m[1] = a->m[1] * b->m[0] + a->m[5] * b->m[1] + a->m[9] * b->m[2] + a->m[13] * b->m[3];
|
||||||
|
result->m[2] = a->m[2] * b->m[0] + a->m[6] * b->m[1] + a->m[10] * b->m[2] + a->m[14] * b->m[3];
|
||||||
|
result->m[3] = a->m[3] * b->m[0] + a->m[7] * b->m[1] + a->m[11] * b->m[2] + a->m[15] * b->m[3];
|
||||||
|
|
||||||
|
result->m[4] = a->m[0] * b->m[4] + a->m[4] * b->m[5] + a->m[8] * b->m[6] + a->m[12] * b->m[7];
|
||||||
|
result->m[5] = a->m[1] * b->m[4] + a->m[5] * b->m[5] + a->m[9] * b->m[6] + a->m[13] * b->m[7];
|
||||||
|
result->m[6] = a->m[2] * b->m[4] + a->m[6] * b->m[5] + a->m[10] * b->m[6] + a->m[14] * b->m[7];
|
||||||
|
result->m[7] = a->m[3] * b->m[4] + a->m[7] * b->m[5] + a->m[11] * b->m[6] + a->m[15] * b->m[7];
|
||||||
|
|
||||||
|
result->m[8] = a->m[0] * b->m[8] + a->m[4] * b->m[9] + a->m[8] * b->m[10] + a->m[12] * b->m[11];
|
||||||
|
result->m[9] = a->m[1] * b->m[8] + a->m[5] * b->m[9] + a->m[9] * b->m[10] + a->m[13] * b->m[11];
|
||||||
|
result->m[10] = a->m[2] * b->m[8] + a->m[6] * b->m[9] + a->m[10] * b->m[10] + a->m[14] * b->m[11];
|
||||||
|
result->m[11] = a->m[3] * b->m[8] + a->m[7] * b->m[9] + a->m[11] * b->m[10] + a->m[15] * b->m[11];
|
||||||
|
|
||||||
|
result->m[12] = a->m[0] * b->m[12] + a->m[4] * b->m[13] + a->m[8] * b->m[14] + a->m[12] * b->m[15];
|
||||||
|
result->m[13] = a->m[1] * b->m[12] + a->m[5] * b->m[13] + a->m[9] * b->m[14] + a->m[13] * b->m[15];
|
||||||
|
result->m[14] = a->m[2] * b->m[12] + a->m[6] * b->m[13] + a->m[10] * b->m[14] + a->m[14] * b->m[15];
|
||||||
|
result->m[15] = a->m[3] * b->m[12] + a->m[7] * b->m[13] + a->m[11] * b->m[14] + a->m[15] * b->m[15];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates the transpose of the given matrix.
|
||||||
|
inline static void XrMatrix4x4f_Transpose(XrMatrix4x4f* result, const XrMatrix4x4f* src) {
|
||||||
|
result->m[0] = src->m[0];
|
||||||
|
result->m[1] = src->m[4];
|
||||||
|
result->m[2] = src->m[8];
|
||||||
|
result->m[3] = src->m[12];
|
||||||
|
|
||||||
|
result->m[4] = src->m[1];
|
||||||
|
result->m[5] = src->m[5];
|
||||||
|
result->m[6] = src->m[9];
|
||||||
|
result->m[7] = src->m[13];
|
||||||
|
|
||||||
|
result->m[8] = src->m[2];
|
||||||
|
result->m[9] = src->m[6];
|
||||||
|
result->m[10] = src->m[10];
|
||||||
|
result->m[11] = src->m[14];
|
||||||
|
|
||||||
|
result->m[12] = src->m[3];
|
||||||
|
result->m[13] = src->m[7];
|
||||||
|
result->m[14] = src->m[11];
|
||||||
|
result->m[15] = src->m[15];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a 3x3 minor of a 4x4 matrix.
|
||||||
|
inline static float XrMatrix4x4f_Minor(const XrMatrix4x4f* matrix, int r0, int r1, int r2, int c0, int c1, int c2) {
|
||||||
|
return matrix->m[4 * r0 + c0] *
|
||||||
|
(matrix->m[4 * r1 + c1] * matrix->m[4 * r2 + c2] - matrix->m[4 * r2 + c1] * matrix->m[4 * r1 + c2]) -
|
||||||
|
matrix->m[4 * r0 + c1] *
|
||||||
|
(matrix->m[4 * r1 + c0] * matrix->m[4 * r2 + c2] - matrix->m[4 * r2 + c0] * matrix->m[4 * r1 + c2]) +
|
||||||
|
matrix->m[4 * r0 + c2] *
|
||||||
|
(matrix->m[4 * r1 + c0] * matrix->m[4 * r2 + c1] - matrix->m[4 * r2 + c0] * matrix->m[4 * r1 + c1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculates the inverse of a 4x4 matrix.
|
||||||
|
inline static void XrMatrix4x4f_Invert(XrMatrix4x4f* result, const XrMatrix4x4f* src) {
|
||||||
|
const float rcpDet =
|
||||||
|
1.0f / (src->m[0] * XrMatrix4x4f_Minor(src, 1, 2, 3, 1, 2, 3) - src->m[1] * XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 2, 3) +
|
||||||
|
src->m[2] * XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 3) - src->m[3] * XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 2));
|
||||||
|
|
||||||
|
result->m[0] = XrMatrix4x4f_Minor(src, 1, 2, 3, 1, 2, 3) * rcpDet;
|
||||||
|
result->m[1] = -XrMatrix4x4f_Minor(src, 0, 2, 3, 1, 2, 3) * rcpDet;
|
||||||
|
result->m[2] = XrMatrix4x4f_Minor(src, 0, 1, 3, 1, 2, 3) * rcpDet;
|
||||||
|
result->m[3] = -XrMatrix4x4f_Minor(src, 0, 1, 2, 1, 2, 3) * rcpDet;
|
||||||
|
result->m[4] = -XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 2, 3) * rcpDet;
|
||||||
|
result->m[5] = XrMatrix4x4f_Minor(src, 0, 2, 3, 0, 2, 3) * rcpDet;
|
||||||
|
result->m[6] = -XrMatrix4x4f_Minor(src, 0, 1, 3, 0, 2, 3) * rcpDet;
|
||||||
|
result->m[7] = XrMatrix4x4f_Minor(src, 0, 1, 2, 0, 2, 3) * rcpDet;
|
||||||
|
result->m[8] = XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 3) * rcpDet;
|
||||||
|
result->m[9] = -XrMatrix4x4f_Minor(src, 0, 2, 3, 0, 1, 3) * rcpDet;
|
||||||
|
result->m[10] = XrMatrix4x4f_Minor(src, 0, 1, 3, 0, 1, 3) * rcpDet;
|
||||||
|
result->m[11] = -XrMatrix4x4f_Minor(src, 0, 1, 2, 0, 1, 3) * rcpDet;
|
||||||
|
result->m[12] = -XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 2) * rcpDet;
|
||||||
|
result->m[13] = XrMatrix4x4f_Minor(src, 0, 2, 3, 0, 1, 2) * rcpDet;
|
||||||
|
result->m[14] = -XrMatrix4x4f_Minor(src, 0, 1, 3, 0, 1, 2) * rcpDet;
|
||||||
|
result->m[15] = XrMatrix4x4f_Minor(src, 0, 1, 2, 0, 1, 2) * rcpDet;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculates the inverse of a rigid body transform.
|
||||||
|
inline static void XrMatrix4x4f_InvertRigidBody(XrMatrix4x4f* result, const XrMatrix4x4f* src) {
|
||||||
|
result->m[0] = src->m[0];
|
||||||
|
result->m[1] = src->m[4];
|
||||||
|
result->m[2] = src->m[8];
|
||||||
|
result->m[3] = 0.0f;
|
||||||
|
result->m[4] = src->m[1];
|
||||||
|
result->m[5] = src->m[5];
|
||||||
|
result->m[6] = src->m[9];
|
||||||
|
result->m[7] = 0.0f;
|
||||||
|
result->m[8] = src->m[2];
|
||||||
|
result->m[9] = src->m[6];
|
||||||
|
result->m[10] = src->m[10];
|
||||||
|
result->m[11] = 0.0f;
|
||||||
|
result->m[12] = -(src->m[0] * src->m[12] + src->m[1] * src->m[13] + src->m[2] * src->m[14]);
|
||||||
|
result->m[13] = -(src->m[4] * src->m[12] + src->m[5] * src->m[13] + src->m[6] * src->m[14]);
|
||||||
|
result->m[14] = -(src->m[8] * src->m[12] + src->m[9] * src->m[13] + src->m[10] * src->m[14]);
|
||||||
|
result->m[15] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates an identity matrix.
|
||||||
|
inline static void XrMatrix4x4f_CreateIdentity(XrMatrix4x4f* result) {
|
||||||
|
result->m[0] = 1.0f;
|
||||||
|
result->m[1] = 0.0f;
|
||||||
|
result->m[2] = 0.0f;
|
||||||
|
result->m[3] = 0.0f;
|
||||||
|
result->m[4] = 0.0f;
|
||||||
|
result->m[5] = 1.0f;
|
||||||
|
result->m[6] = 0.0f;
|
||||||
|
result->m[7] = 0.0f;
|
||||||
|
result->m[8] = 0.0f;
|
||||||
|
result->m[9] = 0.0f;
|
||||||
|
result->m[10] = 1.0f;
|
||||||
|
result->m[11] = 0.0f;
|
||||||
|
result->m[12] = 0.0f;
|
||||||
|
result->m[13] = 0.0f;
|
||||||
|
result->m[14] = 0.0f;
|
||||||
|
result->m[15] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a translation matrix.
|
||||||
|
inline static void XrMatrix4x4f_CreateTranslation(XrMatrix4x4f* result, const float x, const float y, const float z) {
|
||||||
|
result->m[0] = 1.0f;
|
||||||
|
result->m[1] = 0.0f;
|
||||||
|
result->m[2] = 0.0f;
|
||||||
|
result->m[3] = 0.0f;
|
||||||
|
result->m[4] = 0.0f;
|
||||||
|
result->m[5] = 1.0f;
|
||||||
|
result->m[6] = 0.0f;
|
||||||
|
result->m[7] = 0.0f;
|
||||||
|
result->m[8] = 0.0f;
|
||||||
|
result->m[9] = 0.0f;
|
||||||
|
result->m[10] = 1.0f;
|
||||||
|
result->m[11] = 0.0f;
|
||||||
|
result->m[12] = x;
|
||||||
|
result->m[13] = y;
|
||||||
|
result->m[14] = z;
|
||||||
|
result->m[15] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a rotation matrix.
|
||||||
|
// If -Z=forward, +Y=up, +X=right, then degreesX=pitch, degreesY=yaw, degreesZ=roll.
|
||||||
|
inline static void XrMatrix4x4f_CreateRotation(XrMatrix4x4f* result, const float degreesX, const float degreesY,
|
||||||
|
const float degreesZ) {
|
||||||
|
const float sinX = sinf(degreesX * (MATH_PI / 180.0f));
|
||||||
|
const float cosX = cosf(degreesX * (MATH_PI / 180.0f));
|
||||||
|
const XrMatrix4x4f rotationX = {{1, 0, 0, 0, 0, cosX, sinX, 0, 0, -sinX, cosX, 0, 0, 0, 0, 1}};
|
||||||
|
const float sinY = sinf(degreesY * (MATH_PI / 180.0f));
|
||||||
|
const float cosY = cosf(degreesY * (MATH_PI / 180.0f));
|
||||||
|
const XrMatrix4x4f rotationY = {{cosY, 0, -sinY, 0, 0, 1, 0, 0, sinY, 0, cosY, 0, 0, 0, 0, 1}};
|
||||||
|
const float sinZ = sinf(degreesZ * (MATH_PI / 180.0f));
|
||||||
|
const float cosZ = cosf(degreesZ * (MATH_PI / 180.0f));
|
||||||
|
const XrMatrix4x4f rotationZ = {{cosZ, sinZ, 0, 0, -sinZ, cosZ, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}};
|
||||||
|
XrMatrix4x4f rotationXY;
|
||||||
|
XrMatrix4x4f_Multiply(&rotationXY, &rotationY, &rotationX);
|
||||||
|
XrMatrix4x4f_Multiply(result, &rotationZ, &rotationXY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a scale matrix.
|
||||||
|
inline static void XrMatrix4x4f_CreateScale(XrMatrix4x4f* result, const float x, const float y, const float z) {
|
||||||
|
result->m[0] = x;
|
||||||
|
result->m[1] = 0.0f;
|
||||||
|
result->m[2] = 0.0f;
|
||||||
|
result->m[3] = 0.0f;
|
||||||
|
result->m[4] = 0.0f;
|
||||||
|
result->m[5] = y;
|
||||||
|
result->m[6] = 0.0f;
|
||||||
|
result->m[7] = 0.0f;
|
||||||
|
result->m[8] = 0.0f;
|
||||||
|
result->m[9] = 0.0f;
|
||||||
|
result->m[10] = z;
|
||||||
|
result->m[11] = 0.0f;
|
||||||
|
result->m[12] = 0.0f;
|
||||||
|
result->m[13] = 0.0f;
|
||||||
|
result->m[14] = 0.0f;
|
||||||
|
result->m[15] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a matrix from a quaternion.
|
||||||
|
inline static void XrMatrix4x4f_CreateFromQuaternion(XrMatrix4x4f* result, const XrQuaternionf* quat) {
|
||||||
|
const float x2 = quat->x + quat->x;
|
||||||
|
const float y2 = quat->y + quat->y;
|
||||||
|
const float z2 = quat->z + quat->z;
|
||||||
|
|
||||||
|
const float xx2 = quat->x * x2;
|
||||||
|
const float yy2 = quat->y * y2;
|
||||||
|
const float zz2 = quat->z * z2;
|
||||||
|
|
||||||
|
const float yz2 = quat->y * z2;
|
||||||
|
const float wx2 = quat->w * x2;
|
||||||
|
const float xy2 = quat->x * y2;
|
||||||
|
const float wz2 = quat->w * z2;
|
||||||
|
const float xz2 = quat->x * z2;
|
||||||
|
const float wy2 = quat->w * y2;
|
||||||
|
|
||||||
|
result->m[0] = 1.0f - yy2 - zz2;
|
||||||
|
result->m[1] = xy2 + wz2;
|
||||||
|
result->m[2] = xz2 - wy2;
|
||||||
|
result->m[3] = 0.0f;
|
||||||
|
|
||||||
|
result->m[4] = xy2 - wz2;
|
||||||
|
result->m[5] = 1.0f - xx2 - zz2;
|
||||||
|
result->m[6] = yz2 + wx2;
|
||||||
|
result->m[7] = 0.0f;
|
||||||
|
|
||||||
|
result->m[8] = xz2 + wy2;
|
||||||
|
result->m[9] = yz2 - wx2;
|
||||||
|
result->m[10] = 1.0f - xx2 - yy2;
|
||||||
|
result->m[11] = 0.0f;
|
||||||
|
|
||||||
|
result->m[12] = 0.0f;
|
||||||
|
result->m[13] = 0.0f;
|
||||||
|
result->m[14] = 0.0f;
|
||||||
|
result->m[15] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a combined translation(rotation(scale(object))) matrix.
|
||||||
|
inline static void XrMatrix4x4f_CreateTranslationRotationScale(XrMatrix4x4f* result, const XrVector3f* translation,
|
||||||
|
const XrQuaternionf* rotation, const XrVector3f* scale) {
|
||||||
|
XrMatrix4x4f scaleMatrix;
|
||||||
|
XrMatrix4x4f_CreateScale(&scaleMatrix, scale->x, scale->y, scale->z);
|
||||||
|
|
||||||
|
XrMatrix4x4f rotationMatrix;
|
||||||
|
XrMatrix4x4f_CreateFromQuaternion(&rotationMatrix, rotation);
|
||||||
|
|
||||||
|
XrMatrix4x4f translationMatrix;
|
||||||
|
XrMatrix4x4f_CreateTranslation(&translationMatrix, translation->x, translation->y, translation->z);
|
||||||
|
|
||||||
|
XrMatrix4x4f combinedMatrix;
|
||||||
|
XrMatrix4x4f_Multiply(&combinedMatrix, &rotationMatrix, &scaleMatrix);
|
||||||
|
XrMatrix4x4f_Multiply(result, &translationMatrix, &combinedMatrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a projection matrix based on the specified dimensions.
|
||||||
|
// The projection matrix transforms -Z=forward, +Y=up, +X=right to the appropriate clip space for the graphics API.
|
||||||
|
// The far plane is placed at infinity if farZ <= nearZ.
|
||||||
|
// An infinite projection matrix is preferred for rasterization because, except for
|
||||||
|
// things *right* up against the near plane, it always provides better precision:
|
||||||
|
// "Tightening the Precision of Perspective Rendering"
|
||||||
|
// Paul Upchurch, Mathieu Desbrun
|
||||||
|
// Journal of Graphics Tools, Volume 16, Issue 1, 2012
|
||||||
|
inline static void XrMatrix4x4f_CreateProjection(XrMatrix4x4f* result, GraphicsAPI graphicsApi, const float tanAngleLeft,
|
||||||
|
const float tanAngleRight, const float tanAngleUp, float const tanAngleDown,
|
||||||
|
const float nearZ, const float farZ) {
|
||||||
|
const float tanAngleWidth = tanAngleRight - tanAngleLeft;
|
||||||
|
|
||||||
|
// Set to tanAngleDown - tanAngleUp for a clip space with positive Y down (Vulkan).
|
||||||
|
// Set to tanAngleUp - tanAngleDown for a clip space with positive Y up (OpenGL / D3D / Metal).
|
||||||
|
const float tanAngleHeight = graphicsApi == GRAPHICS_VULKAN ? (tanAngleDown - tanAngleUp) : (tanAngleUp - tanAngleDown);
|
||||||
|
|
||||||
|
// Set to nearZ for a [-1,1] Z clip space (OpenGL / OpenGL ES).
|
||||||
|
// Set to zero for a [0,1] Z clip space (Vulkan / D3D / Metal).
|
||||||
|
const float offsetZ = (graphicsApi == GRAPHICS_OPENGL || graphicsApi == GRAPHICS_OPENGL_ES) ? nearZ : 0;
|
||||||
|
|
||||||
|
if (farZ <= nearZ) {
|
||||||
|
// place the far plane at infinity
|
||||||
|
result->m[0] = 2 / tanAngleWidth;
|
||||||
|
result->m[4] = 0;
|
||||||
|
result->m[8] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
|
||||||
|
result->m[12] = 0;
|
||||||
|
|
||||||
|
result->m[1] = 0;
|
||||||
|
result->m[5] = 2 / tanAngleHeight;
|
||||||
|
result->m[9] = (tanAngleUp + tanAngleDown) / tanAngleHeight;
|
||||||
|
result->m[13] = 0;
|
||||||
|
|
||||||
|
result->m[2] = 0;
|
||||||
|
result->m[6] = 0;
|
||||||
|
result->m[10] = -1;
|
||||||
|
result->m[14] = -(nearZ + offsetZ);
|
||||||
|
|
||||||
|
result->m[3] = 0;
|
||||||
|
result->m[7] = 0;
|
||||||
|
result->m[11] = -1;
|
||||||
|
result->m[15] = 0;
|
||||||
|
} else {
|
||||||
|
// normal projection
|
||||||
|
result->m[0] = 2 / tanAngleWidth;
|
||||||
|
result->m[4] = 0;
|
||||||
|
result->m[8] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
|
||||||
|
result->m[12] = 0;
|
||||||
|
|
||||||
|
result->m[1] = 0;
|
||||||
|
result->m[5] = 2 / tanAngleHeight;
|
||||||
|
result->m[9] = (tanAngleUp + tanAngleDown) / tanAngleHeight;
|
||||||
|
result->m[13] = 0;
|
||||||
|
|
||||||
|
result->m[2] = 0;
|
||||||
|
result->m[6] = 0;
|
||||||
|
result->m[10] = -(farZ + offsetZ) / (farZ - nearZ);
|
||||||
|
result->m[14] = -(farZ * (nearZ + offsetZ)) / (farZ - nearZ);
|
||||||
|
|
||||||
|
result->m[3] = 0;
|
||||||
|
result->m[7] = 0;
|
||||||
|
result->m[11] = -1;
|
||||||
|
result->m[15] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a projection matrix based on the specified FOV.
|
||||||
|
inline static void XrMatrix4x4f_CreateProjectionFov(XrMatrix4x4f* result, GraphicsAPI graphicsApi, const XrFovf fov,
|
||||||
|
const float nearZ, const float farZ) {
|
||||||
|
const float tanLeft = tanf(fov.angleLeft);
|
||||||
|
const float tanRight = tanf(fov.angleRight);
|
||||||
|
|
||||||
|
const float tanDown = tanf(fov.angleDown);
|
||||||
|
const float tanUp = tanf(fov.angleUp);
|
||||||
|
|
||||||
|
XrMatrix4x4f_CreateProjection(result, graphicsApi, tanLeft, tanRight, tanUp, tanDown, nearZ, farZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a matrix that transforms the -1 to 1 cube to cover the given 'mins' and 'maxs' transformed with the given 'matrix'.
|
||||||
|
inline static void XrMatrix4x4f_CreateOffsetScaleForBounds(XrMatrix4x4f* result, const XrMatrix4x4f* matrix, const XrVector3f* mins,
|
||||||
|
const XrVector3f* maxs) {
|
||||||
|
const XrVector3f offset = {(maxs->x + mins->x) * 0.5f, (maxs->y + mins->y) * 0.5f, (maxs->z + mins->z) * 0.5f};
|
||||||
|
const XrVector3f scale = {(maxs->x - mins->x) * 0.5f, (maxs->y - mins->y) * 0.5f, (maxs->z - mins->z) * 0.5f};
|
||||||
|
|
||||||
|
result->m[0] = matrix->m[0] * scale.x;
|
||||||
|
result->m[1] = matrix->m[1] * scale.x;
|
||||||
|
result->m[2] = matrix->m[2] * scale.x;
|
||||||
|
result->m[3] = matrix->m[3] * scale.x;
|
||||||
|
|
||||||
|
result->m[4] = matrix->m[4] * scale.y;
|
||||||
|
result->m[5] = matrix->m[5] * scale.y;
|
||||||
|
result->m[6] = matrix->m[6] * scale.y;
|
||||||
|
result->m[7] = matrix->m[7] * scale.y;
|
||||||
|
|
||||||
|
result->m[8] = matrix->m[8] * scale.z;
|
||||||
|
result->m[9] = matrix->m[9] * scale.z;
|
||||||
|
result->m[10] = matrix->m[10] * scale.z;
|
||||||
|
result->m[11] = matrix->m[11] * scale.z;
|
||||||
|
|
||||||
|
result->m[12] = matrix->m[12] + matrix->m[0] * offset.x + matrix->m[4] * offset.y + matrix->m[8] * offset.z;
|
||||||
|
result->m[13] = matrix->m[13] + matrix->m[1] * offset.x + matrix->m[5] * offset.y + matrix->m[9] * offset.z;
|
||||||
|
result->m[14] = matrix->m[14] + matrix->m[2] * offset.x + matrix->m[6] * offset.y + matrix->m[10] * offset.z;
|
||||||
|
result->m[15] = matrix->m[15] + matrix->m[3] * offset.x + matrix->m[7] * offset.y + matrix->m[11] * offset.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the given matrix is affine.
|
||||||
|
inline static bool XrMatrix4x4f_IsAffine(const XrMatrix4x4f* matrix, const float epsilon) {
|
||||||
|
return fabsf(matrix->m[3]) <= epsilon && fabsf(matrix->m[7]) <= epsilon && fabsf(matrix->m[11]) <= epsilon &&
|
||||||
|
fabsf(matrix->m[15] - 1.0f) <= epsilon;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the given matrix is orthogonal.
|
||||||
|
inline static bool XrMatrix4x4f_IsOrthogonal(const XrMatrix4x4f* matrix, const float epsilon) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
for (int j = 0; j < 3; j++) {
|
||||||
|
if (i != j) {
|
||||||
|
if (fabsf(matrix->m[4 * i + 0] * matrix->m[4 * j + 0] + matrix->m[4 * i + 1] * matrix->m[4 * j + 1] +
|
||||||
|
matrix->m[4 * i + 2] * matrix->m[4 * j + 2]) > epsilon) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (fabsf(matrix->m[4 * 0 + i] * matrix->m[4 * 0 + j] + matrix->m[4 * 1 + i] * matrix->m[4 * 1 + j] +
|
||||||
|
matrix->m[4 * 2 + i] * matrix->m[4 * 2 + j]) > epsilon) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the given matrix is orthonormal.
|
||||||
|
inline static bool XrMatrix4x4f_IsOrthonormal(const XrMatrix4x4f* matrix, const float epsilon) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
for (int j = 0; j < 3; j++) {
|
||||||
|
const float kd = (i == j) ? 1.0f : 0.0f; // Kronecker delta
|
||||||
|
if (fabsf(kd - (matrix->m[4 * i + 0] * matrix->m[4 * j + 0] + matrix->m[4 * i + 1] * matrix->m[4 * j + 1] +
|
||||||
|
matrix->m[4 * i + 2] * matrix->m[4 * j + 2])) > epsilon) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (fabsf(kd - (matrix->m[4 * 0 + i] * matrix->m[4 * 0 + j] + matrix->m[4 * 1 + i] * matrix->m[4 * 1 + j] +
|
||||||
|
matrix->m[4 * 2 + i] * matrix->m[4 * 2 + j])) > epsilon) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the given matrix is a rigid body transform.
|
||||||
|
inline static bool XrMatrix4x4f_IsRigidBody(const XrMatrix4x4f* matrix, const float epsilon) {
|
||||||
|
return XrMatrix4x4f_IsAffine(matrix, epsilon) && XrMatrix4x4f_IsOrthonormal(matrix, epsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the translation from a combined translation(rotation(scale(object))) matrix.
|
||||||
|
inline static void XrMatrix4x4f_GetTranslation(XrVector3f* result, const XrMatrix4x4f* src) {
|
||||||
|
assert(XrMatrix4x4f_IsAffine(src, 1e-4f));
|
||||||
|
assert(XrMatrix4x4f_IsOrthogonal(src, 1e-4f));
|
||||||
|
|
||||||
|
result->x = src->m[12];
|
||||||
|
result->y = src->m[13];
|
||||||
|
result->z = src->m[14];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the rotation from a combined translation(rotation(scale(object))) matrix.
|
||||||
|
inline static void XrMatrix4x4f_GetRotation(XrQuaternionf* result, const XrMatrix4x4f* src) {
|
||||||
|
assert(XrMatrix4x4f_IsAffine(src, 1e-4f));
|
||||||
|
assert(XrMatrix4x4f_IsOrthogonal(src, 1e-4f));
|
||||||
|
|
||||||
|
const float rcpScaleX = XrRcpSqrt(src->m[0] * src->m[0] + src->m[1] * src->m[1] + src->m[2] * src->m[2]);
|
||||||
|
const float rcpScaleY = XrRcpSqrt(src->m[4] * src->m[4] + src->m[5] * src->m[5] + src->m[6] * src->m[6]);
|
||||||
|
const float rcpScaleZ = XrRcpSqrt(src->m[8] * src->m[8] + src->m[9] * src->m[9] + src->m[10] * src->m[10]);
|
||||||
|
const float m[9] = {src->m[0] * rcpScaleX, src->m[1] * rcpScaleX, src->m[2] * rcpScaleX,
|
||||||
|
src->m[4] * rcpScaleY, src->m[5] * rcpScaleY, src->m[6] * rcpScaleY,
|
||||||
|
src->m[8] * rcpScaleZ, src->m[9] * rcpScaleZ, src->m[10] * rcpScaleZ};
|
||||||
|
if (m[0 * 3 + 0] + m[1 * 3 + 1] + m[2 * 3 + 2] > 0.0f) {
|
||||||
|
float t = +m[0 * 3 + 0] + m[1 * 3 + 1] + m[2 * 3 + 2] + 1.0f;
|
||||||
|
float s = XrRcpSqrt(t) * 0.5f;
|
||||||
|
result->w = s * t;
|
||||||
|
result->z = (m[0 * 3 + 1] - m[1 * 3 + 0]) * s;
|
||||||
|
result->y = (m[2 * 3 + 0] - m[0 * 3 + 2]) * s;
|
||||||
|
result->x = (m[1 * 3 + 2] - m[2 * 3 + 1]) * s;
|
||||||
|
} else if (m[0 * 3 + 0] > m[1 * 3 + 1] && m[0 * 3 + 0] > m[2 * 3 + 2]) {
|
||||||
|
float t = +m[0 * 3 + 0] - m[1 * 3 + 1] - m[2 * 3 + 2] + 1.0f;
|
||||||
|
float s = XrRcpSqrt(t) * 0.5f;
|
||||||
|
result->x = s * t;
|
||||||
|
result->y = (m[0 * 3 + 1] + m[1 * 3 + 0]) * s;
|
||||||
|
result->z = (m[2 * 3 + 0] + m[0 * 3 + 2]) * s;
|
||||||
|
result->w = (m[1 * 3 + 2] - m[2 * 3 + 1]) * s;
|
||||||
|
} else if (m[1 * 3 + 1] > m[2 * 3 + 2]) {
|
||||||
|
float t = -m[0 * 3 + 0] + m[1 * 3 + 1] - m[2 * 3 + 2] + 1.0f;
|
||||||
|
float s = XrRcpSqrt(t) * 0.5f;
|
||||||
|
result->y = s * t;
|
||||||
|
result->x = (m[0 * 3 + 1] + m[1 * 3 + 0]) * s;
|
||||||
|
result->w = (m[2 * 3 + 0] - m[0 * 3 + 2]) * s;
|
||||||
|
result->z = (m[1 * 3 + 2] + m[2 * 3 + 1]) * s;
|
||||||
|
} else {
|
||||||
|
float t = -m[0 * 3 + 0] - m[1 * 3 + 1] + m[2 * 3 + 2] + 1.0f;
|
||||||
|
float s = XrRcpSqrt(t) * 0.5f;
|
||||||
|
result->z = s * t;
|
||||||
|
result->w = (m[0 * 3 + 1] - m[1 * 3 + 0]) * s;
|
||||||
|
result->x = (m[2 * 3 + 0] + m[0 * 3 + 2]) * s;
|
||||||
|
result->y = (m[1 * 3 + 2] + m[2 * 3 + 1]) * s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the scale from a combined translation(rotation(scale(object))) matrix.
|
||||||
|
inline static void XrMatrix4x4f_GetScale(XrVector3f* result, const XrMatrix4x4f* src) {
|
||||||
|
assert(XrMatrix4x4f_IsAffine(src, 1e-4f));
|
||||||
|
assert(XrMatrix4x4f_IsOrthogonal(src, 1e-4f));
|
||||||
|
|
||||||
|
result->x = sqrtf(src->m[0] * src->m[0] + src->m[1] * src->m[1] + src->m[2] * src->m[2]);
|
||||||
|
result->y = sqrtf(src->m[4] * src->m[4] + src->m[5] * src->m[5] + src->m[6] * src->m[6]);
|
||||||
|
result->z = sqrtf(src->m[8] * src->m[8] + src->m[9] * src->m[9] + src->m[10] * src->m[10]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transforms a 3D vector.
|
||||||
|
inline static void XrMatrix4x4f_TransformVector3f(XrVector3f* result, const XrMatrix4x4f* m, const XrVector3f* v) {
|
||||||
|
const float w = m->m[3] * v->x + m->m[7] * v->y + m->m[11] * v->z + m->m[15];
|
||||||
|
const float rcpW = 1.0f / w;
|
||||||
|
result->x = (m->m[0] * v->x + m->m[4] * v->y + m->m[8] * v->z + m->m[12]) * rcpW;
|
||||||
|
result->y = (m->m[1] * v->x + m->m[5] * v->y + m->m[9] * v->z + m->m[13]) * rcpW;
|
||||||
|
result->z = (m->m[2] * v->x + m->m[6] * v->y + m->m[10] * v->z + m->m[14]) * rcpW;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transforms a 4D vector.
|
||||||
|
inline static void XrMatrix4x4f_TransformVector4f(XrVector4f* result, const XrMatrix4x4f* m, const XrVector4f* v) {
|
||||||
|
result->x = m->m[0] * v->x + m->m[4] * v->y + m->m[8] * v->z + m->m[12] * v->w;
|
||||||
|
result->y = m->m[1] * v->x + m->m[5] * v->y + m->m[9] * v->z + m->m[13] * v->w;
|
||||||
|
result->z = m->m[2] * v->x + m->m[6] * v->y + m->m[10] * v->z + m->m[14] * v->w;
|
||||||
|
result->w = m->m[3] * v->x + m->m[7] * v->y + m->m[11] * v->z + m->m[15] * v->w;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transforms the 'mins' and 'maxs' bounds with the given 'matrix'.
|
||||||
|
inline static void XrMatrix4x4f_TransformBounds(XrVector3f* resultMins, XrVector3f* resultMaxs, const XrMatrix4x4f* matrix,
|
||||||
|
const XrVector3f* mins, const XrVector3f* maxs) {
|
||||||
|
assert(XrMatrix4x4f_IsAffine(matrix, 1e-4f));
|
||||||
|
|
||||||
|
const XrVector3f center = {(mins->x + maxs->x) * 0.5f, (mins->y + maxs->y) * 0.5f, (mins->z + maxs->z) * 0.5f};
|
||||||
|
const XrVector3f extents = {maxs->x - center.x, maxs->y - center.y, maxs->z - center.z};
|
||||||
|
const XrVector3f newCenter = {matrix->m[0] * center.x + matrix->m[4] * center.y + matrix->m[8] * center.z + matrix->m[12],
|
||||||
|
matrix->m[1] * center.x + matrix->m[5] * center.y + matrix->m[9] * center.z + matrix->m[13],
|
||||||
|
matrix->m[2] * center.x + matrix->m[6] * center.y + matrix->m[10] * center.z + matrix->m[14]};
|
||||||
|
const XrVector3f newExtents = {
|
||||||
|
fabsf(extents.x * matrix->m[0]) + fabsf(extents.y * matrix->m[4]) + fabsf(extents.z * matrix->m[8]),
|
||||||
|
fabsf(extents.x * matrix->m[1]) + fabsf(extents.y * matrix->m[5]) + fabsf(extents.z * matrix->m[9]),
|
||||||
|
fabsf(extents.x * matrix->m[2]) + fabsf(extents.y * matrix->m[6]) + fabsf(extents.z * matrix->m[10])};
|
||||||
|
XrVector3f_Sub(resultMins, &newCenter, &newExtents);
|
||||||
|
XrVector3f_Add(resultMaxs, &newCenter, &newExtents);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the 'mins' and 'maxs' bounds is completely off to one side of the projection matrix.
|
||||||
|
inline static bool XrMatrix4x4f_CullBounds(const XrMatrix4x4f* mvp, const XrVector3f* mins, const XrVector3f* maxs) {
|
||||||
|
if (maxs->x <= mins->x && maxs->y <= mins->y && maxs->z <= mins->z) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrVector4f c[8];
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
const XrVector4f corner = {(i & 1) ? maxs->x : mins->x, (i & 2) ? maxs->y : mins->y, (i & 4) ? maxs->z : mins->z, 1.0f};
|
||||||
|
XrMatrix4x4f_TransformVector4f(&c[i], mvp, &corner);
|
||||||
|
}
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (c[i].x > -c[i].w) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == 8) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (c[i].x < c[i].w) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == 8) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (c[i].y > -c[i].w) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == 8) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (c[i].y < c[i].w) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == 8) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (c[i].z > -c[i].w) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == 8) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (c[i].z < c[i].w) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == 8) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // XR_LINEAR_H_
|
||||||
3
extern/openxr/src/common_cmake_config.h.in
vendored
Normal file
3
extern/openxr/src/common_cmake_config.h.in
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#cmakedefine HAVE_SECURE_GETENV
|
||||||
|
#cmakedefine HAVE___SECURE_GETENV
|
||||||
|
#cmakedefine XRLOADER_ENABLE_EXCEPTION_HANDLING
|
||||||
183
extern/openxr/src/loader/CMakeLists.txt
vendored
Normal file
183
extern/openxr/src/loader/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
# Copyright (c) 2017 The Khronos Group Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
# Author:
|
||||||
|
#
|
||||||
|
|
||||||
|
#set (CMAKE_VERBOSE_MAKEFILE 1)
|
||||||
|
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
# Use this feature for Windows to automatically generate an exports file for the DLL.
|
||||||
|
# See https://blog.kitware.com/create-dlls-on-windows-without-declspec-using-new-cmake-export-all-feature/
|
||||||
|
include(GenerateExportHeader)
|
||||||
|
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS false)
|
||||||
|
|
||||||
|
set(LOADER_NAME openxr_loader)
|
||||||
|
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
set(FALLBACK_CONFIG_DIRS "/etc/xdg" CACHE STRING
|
||||||
|
"Search path to use when XDG_CONFIG_DIRS is unset or empty or the current process is SUID/SGID. Default is freedesktop compliant.")
|
||||||
|
set(FALLBACK_DATA_DIRS "/usr/local/share:/usr/share" CACHE STRING
|
||||||
|
"Search path to use when XDG_DATA_DIRS is unset or empty or the current process is SUID/SGID. Default is freedesktop compliant.")
|
||||||
|
endif()
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
set(openxr_loader_RESOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/loader.rc)
|
||||||
|
set(LOADER_NAME ${LOADER_NAME}-${MAJOR}_${MINOR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# List of all files externally generated outside of the loader that the loader
|
||||||
|
# needs to build with.
|
||||||
|
SET(LOADER_EXTERNAL_GEN_FILES
|
||||||
|
${COMMON_GENERATED_OUTPUT}
|
||||||
|
)
|
||||||
|
run_xr_xml_generate(loader_source_generator.py xr_generated_loader.hpp)
|
||||||
|
run_xr_xml_generate(loader_source_generator.py xr_generated_loader.cpp)
|
||||||
|
|
||||||
|
if(DYNAMIC_LOADER)
|
||||||
|
add_definitions(-DXRAPI_DLL_EXPORT)
|
||||||
|
set(LIBRARY_TYPE SHARED)
|
||||||
|
else() # build static lib
|
||||||
|
set(LIBRARY_TYPE STATIC)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(JSONCPP_ROOT_DIR ${CMAKE_SOURCE_DIR}/extern/jsoncpp)
|
||||||
|
|
||||||
|
add_library(${LOADER_NAME} ${LIBRARY_TYPE}
|
||||||
|
api_layer_interface.cpp
|
||||||
|
api_layer_interface.hpp
|
||||||
|
loader_core.cpp
|
||||||
|
loader_instance.cpp
|
||||||
|
loader_instance.hpp
|
||||||
|
loader_logger.cpp
|
||||||
|
loader_logger.hpp
|
||||||
|
loader_logger_recorders.cpp
|
||||||
|
loader_logger_recorders.hpp
|
||||||
|
manifest_file.cpp
|
||||||
|
${GENERATED_OUTPUT}
|
||||||
|
manifest_file.hpp
|
||||||
|
runtime_interface.cpp
|
||||||
|
runtime_interface.hpp
|
||||||
|
${OPENXR_ROOT_DIR}/src/common/filesystem_utils.cpp
|
||||||
|
${OPENXR_ROOT_DIR}/src/common/filesystem_utils.hpp
|
||||||
|
${OPENXR_ROOT_DIR}/src/common/hex_and_handles.cpp
|
||||||
|
${OPENXR_ROOT_DIR}/src/common/hex_and_handles.h
|
||||||
|
${JSONCPP_ROOT_DIR}/src/json_reader.cpp
|
||||||
|
${JSONCPP_ROOT_DIR}/src/json_value.cpp
|
||||||
|
${JSONCPP_ROOT_DIR}/src/json_writer.cpp
|
||||||
|
${LOADER_EXTERNAL_GEN_FILES}
|
||||||
|
${openxr_loader_RESOURCE_FILE}
|
||||||
|
)
|
||||||
|
set_target_properties(${LOADER_NAME} PROPERTIES FOLDER ${LOADER_FOLDER})
|
||||||
|
|
||||||
|
set_source_files_properties(
|
||||||
|
${LOADER_EXTERNAL_GEN_FILES}
|
||||||
|
PROPERTIES GENERATED TRUE
|
||||||
|
)
|
||||||
|
add_dependencies(${LOADER_NAME}
|
||||||
|
generate_openxr_header
|
||||||
|
xr_global_generated_files
|
||||||
|
)
|
||||||
|
target_include_directories(${LOADER_NAME}
|
||||||
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
PRIVATE ${CMAKE_BINARY_DIR}/include
|
||||||
|
PRIVATE ${CMAKE_BINARY_DIR}/src
|
||||||
|
PRIVATE ${OPENXR_ROOT_DIR}/src/common
|
||||||
|
PRIVATE ${JSONCPP_ROOT_DIR}/include
|
||||||
|
)
|
||||||
|
if(VulkanHeaders_FOUND)
|
||||||
|
target_include_directories(${LOADER_NAME}
|
||||||
|
PRIVATE ${Vulkan_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_compile_definitions(${LOADER_NAME}
|
||||||
|
PRIVATE API_NAME="OpenXR"
|
||||||
|
)
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
target_compile_definitions(${LOADER_NAME}
|
||||||
|
PRIVATE FALLBACK_CONFIG_DIRS="${FALLBACK_CONFIG_DIRS}"
|
||||||
|
PRIVATE FALLBACK_DATA_DIRS="${FALLBACK_DATA_DIRS}"
|
||||||
|
PRIVATE SYSCONFDIR="${CMAKE_INSTALL_FULL_SYSCONFDIR}"
|
||||||
|
)
|
||||||
|
if(NOT(CMAKE_INSTALL_FULL_SYSCONFDIR STREQUAL "/etc"))
|
||||||
|
target_compile_definitions(openxr_loader PRIVATE EXTRASYSCONFDIR="/etc")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set_target_properties(${LOADER_NAME} PROPERTIES SOVERSION "${MAJOR}" VERSION "${MAJOR}.${MINOR}.${PATCH}")
|
||||||
|
target_link_libraries(${LOADER_NAME} -lstdc++fs -ldl -lpthread -lm)
|
||||||
|
|
||||||
|
add_custom_target(lib${LOADER_NAME}.so.${MAJOR}.${MINOR} ALL
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E create_symlink lib${LOADER_NAME}.so.${MAJOR}.${MINOR}.${PATCH} lib${LOADER_NAME}.so.${MAJOR}.${MINOR})
|
||||||
|
|
||||||
|
install(TARGETS ${LOADER_NAME}
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
set(XR_API_VERSION "${MAJOR}.${MINOR}")
|
||||||
|
configure_file("openxr.pc.in" "openxr.pc" @ONLY)
|
||||||
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/openxr.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||||
|
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
foreach(configuration in CMAKE_C_FLAGS_DEBUG
|
||||||
|
CMAKE_C_FLAGS_RELEASE
|
||||||
|
CMAKE_C_FLAGS_RELWITHDEBINFO
|
||||||
|
CMAKE_CXX_FLAGS_DEBUG
|
||||||
|
CMAKE_CXX_FLAGS_RELEASE
|
||||||
|
CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
||||||
|
# If building DLLs, force static CRT linkage
|
||||||
|
if(DYNAMIC_LOADER)
|
||||||
|
if (${configuration} MATCHES "/MD")
|
||||||
|
# string(REGEX REPLACE "/MD" "/MT" ${configuration} "${${configuration}}")
|
||||||
|
endif()
|
||||||
|
else() # Otherwise for static libs, link the CRT dynamically
|
||||||
|
if (${configuration} MATCHES "/MT")
|
||||||
|
# string(REGEX REPLACE "/MT" "/MD" ${configuration} "${${configuration}}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
target_link_libraries(${LOADER_NAME} shlwapi)
|
||||||
|
target_compile_options(${LOADER_NAME} PRIVATE)
|
||||||
|
generate_export_header(${LOADER_NAME})
|
||||||
|
# set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS false)
|
||||||
|
|
||||||
|
# Need to copy DLL to client directories so clients can easily load it.
|
||||||
|
if( (DYNAMIC_LOADER) AND (CMAKE_GENERATOR MATCHES "^Visual Studio.*") )
|
||||||
|
file( TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>/${LOADER_NAME}.dll COPY_SRC_PATH )
|
||||||
|
# file( TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/../tests/triangle/$<CONFIGURATION>/ COPY_DST_TEST_PATH )
|
||||||
|
file( TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/../tests/hello_xr/$<CONFIGURATION>/ COPY_DST_TEST_PATH )
|
||||||
|
file( TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/../tests/loader_test/$<CONFIGURATION>/ COPY_DST_LOADER_TEST_PATH )
|
||||||
|
add_custom_command( TARGET ${LOADER_NAME} POST_BUILD
|
||||||
|
COMMAND xcopy /Y /I ${COPY_SRC_PATH} ${COPY_DST_TEST_PATH}
|
||||||
|
COMMAND xcopy /Y /I ${COPY_SRC_PATH} ${COPY_DST_LOADER_TEST_PATH}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||||
|
target_compile_options(openxr_loader
|
||||||
|
PRIVATE -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wpointer-arith
|
||||||
|
PRIVATE -fno-strict-aliasing -fno-builtin-memcmp "$<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>"
|
||||||
|
)
|
||||||
|
# For GCC version 7.1 or greater, we need to disable the implicit fallthrough warning since
|
||||||
|
# there's no consistent way to satisfy all compilers until they all accept the C++17 standard
|
||||||
|
if (CMAKE_COMPILER_IS_GNUCC AND NOT (CMAKE_CXX_COMPILER_VERSION LESS 7.1))
|
||||||
|
target_compile_options(openxr_loader PRIVATE -Wimplicit-fallthrough=0)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(TARGETS ${LOADER_NAME} DESTINATION lib)
|
||||||
|
|
||||||
|
# Custom commands to build dependencies for above targets
|
||||||
403
extern/openxr/src/loader/api_layer_interface.cpp
vendored
Normal file
403
extern/openxr/src/loader/api_layer_interface.cpp
vendored
Normal file
@@ -0,0 +1,403 @@
|
|||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "api_layer_interface.hpp"
|
||||||
|
|
||||||
|
#include "loader_interfaces.h"
|
||||||
|
#include "loader_logger.hpp"
|
||||||
|
#include "loader_platform.hpp"
|
||||||
|
#include "manifest_file.hpp"
|
||||||
|
#include "platform_utils.hpp"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#define OPENXR_ENABLE_LAYERS_ENV_VAR "XR_ENABLE_API_LAYERS"
|
||||||
|
|
||||||
|
// Add any layers defined in the loader layer environment variable.
|
||||||
|
static void AddEnvironmentApiLayers(const std::string& openxr_command, std::vector<std::string>& enabled_layers) {
|
||||||
|
char* layer_environment_variable = PlatformUtilsGetEnv(OPENXR_ENABLE_LAYERS_ENV_VAR);
|
||||||
|
if (nullptr != layer_environment_variable) {
|
||||||
|
std::string layers = layer_environment_variable;
|
||||||
|
PlatformUtilsFreeEnv(layer_environment_variable);
|
||||||
|
|
||||||
|
std::size_t last_found = 0;
|
||||||
|
std::size_t found = layers.find_first_of(PATH_SEPARATOR);
|
||||||
|
std::string cur_search;
|
||||||
|
|
||||||
|
// Handle any path listings in the string (separated by the appropriate path separator)
|
||||||
|
while (found != std::string::npos) {
|
||||||
|
cur_search = layers.substr(last_found, found);
|
||||||
|
enabled_layers.push_back(cur_search);
|
||||||
|
last_found = found + 1;
|
||||||
|
found = layers.find_first_of(PATH_SEPARATOR, last_found);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's something remaining in the string, copy it over
|
||||||
|
if (last_found < layers.size()) {
|
||||||
|
cur_search = layers.substr(last_found);
|
||||||
|
enabled_layers.push_back(cur_search);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult ApiLayerInterface::GetApiLayerProperties(const std::string& openxr_command, uint32_t incoming_count,
|
||||||
|
uint32_t* outgoing_count, XrApiLayerProperties* api_layer_properties) {
|
||||||
|
std::vector<std::unique_ptr<ApiLayerManifestFile>> manifest_files;
|
||||||
|
uint32_t manifest_count = 0;
|
||||||
|
|
||||||
|
// Find any implicit layers which we may need to report information for.
|
||||||
|
XrResult result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_IMPLICIT_API_LAYER, manifest_files);
|
||||||
|
if (XR_SUCCESS == result) {
|
||||||
|
// Find any explicit layers which we may need to report information for.
|
||||||
|
result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_EXPLICIT_API_LAYER, manifest_files);
|
||||||
|
}
|
||||||
|
if (XR_SUCCESS != result) {
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command,
|
||||||
|
"ApiLayerInterface::GetApiLayerProperties - failed searching for API layer manifest files");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
manifest_count = static_cast<uint32_t>(manifest_files.size());
|
||||||
|
if (0 == incoming_count) {
|
||||||
|
if (nullptr == outgoing_count) {
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
*outgoing_count = manifest_count;
|
||||||
|
} else if (nullptr != api_layer_properties) {
|
||||||
|
if (incoming_count < manifest_count && nullptr != api_layer_properties) {
|
||||||
|
LoaderLogger::LogErrorMessage(
|
||||||
|
"xrEnumerateInstanceExtensionProperties",
|
||||||
|
"VUID-xrEnumerateApiLayerProperties-propertyCapacityInput-parameter: insufficient space in array");
|
||||||
|
*outgoing_count = manifest_count;
|
||||||
|
return XR_ERROR_SIZE_INSUFFICIENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t prop = 0;
|
||||||
|
bool properties_valid = true;
|
||||||
|
for (; prop < incoming_count && prop < manifest_count; ++prop) {
|
||||||
|
if (XR_TYPE_API_LAYER_PROPERTIES != api_layer_properties[prop].type) {
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command,
|
||||||
|
"VUID-XrApiLayerProperties-type-type: unknown type in api_layer_properties");
|
||||||
|
properties_valid = false;
|
||||||
|
}
|
||||||
|
if (nullptr != api_layer_properties[prop].next) {
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command, "VUID-XrApiLayerProperties-next-next: expected NULL");
|
||||||
|
properties_valid = false;
|
||||||
|
}
|
||||||
|
if (properties_valid) {
|
||||||
|
api_layer_properties[prop] = manifest_files[prop]->GetApiLayerProperties();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!properties_valid) {
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command,
|
||||||
|
"VUID-xrEnumerateApiLayerProperties-properties-parameter: invalid properties");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
if (nullptr != outgoing_count) {
|
||||||
|
*outgoing_count = prop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult ApiLayerInterface::GetInstanceExtensionProperties(const std::string& openxr_command, const char* layer_name,
|
||||||
|
std::vector<XrExtensionProperties>& extension_properties) {
|
||||||
|
std::vector<std::unique_ptr<ApiLayerManifestFile>> manifest_files;
|
||||||
|
|
||||||
|
// If a layer name is supplied, only use the information out of that one layer
|
||||||
|
if (nullptr != layer_name && 0 != strlen(layer_name)) {
|
||||||
|
XrResult result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_IMPLICIT_API_LAYER, manifest_files);
|
||||||
|
if (XR_SUCCESS == result) {
|
||||||
|
// Find any explicit layers which we may need to report information for.
|
||||||
|
result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_EXPLICIT_API_LAYER, manifest_files);
|
||||||
|
if (XR_SUCCESS != result) {
|
||||||
|
LoaderLogger::LogErrorMessage(
|
||||||
|
openxr_command,
|
||||||
|
"ApiLayerInterface::GetInstanceExtensionProperties - failed searching for API layer manifest files");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
auto num_files = static_cast<uint32_t>(manifest_files.size());
|
||||||
|
for (uint32_t man_file = 0; man_file < num_files; ++man_file) {
|
||||||
|
// If a layer with the provided name exists, get it's instance extension information.
|
||||||
|
if (manifest_files[man_file]->LayerName() == layer_name) {
|
||||||
|
manifest_files[man_file]->GetInstanceExtensionProperties(extension_properties);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If nothing found, report 0
|
||||||
|
if (!found) {
|
||||||
|
return XR_ERROR_API_LAYER_NOT_PRESENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Otherwise, we want to add only implicit API layers and explicit API layers enabled using the environment variables
|
||||||
|
} else {
|
||||||
|
XrResult result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_IMPLICIT_API_LAYER, manifest_files);
|
||||||
|
if (XR_SUCCESS == result) {
|
||||||
|
// Find any environmentally enabled explicit layers. If they're present, treat them like implicit layers
|
||||||
|
// since we know that they're going to be enabled.
|
||||||
|
std::vector<std::string> env_enabled_layers;
|
||||||
|
AddEnvironmentApiLayers(openxr_command, env_enabled_layers);
|
||||||
|
if (!env_enabled_layers.empty()) {
|
||||||
|
std::vector<std::unique_ptr<ApiLayerManifestFile>> exp_layer_man_files = {};
|
||||||
|
result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_EXPLICIT_API_LAYER, exp_layer_man_files);
|
||||||
|
if (XR_SUCCESS == result) {
|
||||||
|
for (auto l_iter = exp_layer_man_files.begin();
|
||||||
|
!exp_layer_man_files.empty() && l_iter != exp_layer_man_files.end();
|
||||||
|
/* No iterate */) {
|
||||||
|
for (std::string& enabled_layer : env_enabled_layers) {
|
||||||
|
// If this is an enabled layer, transfer it over to the manifest list.
|
||||||
|
if (enabled_layer == (*l_iter)->LayerName()) {
|
||||||
|
manifest_files.push_back(std::move(*l_iter));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exp_layer_man_files.erase(l_iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grab the layer instance extensions information
|
||||||
|
auto num_files = static_cast<uint32_t>(manifest_files.size());
|
||||||
|
for (uint32_t man_file = 0; man_file < num_files; ++man_file) {
|
||||||
|
manifest_files[man_file]->GetInstanceExtensionProperties(extension_properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult ApiLayerInterface::LoadApiLayers(const std::string& openxr_command, uint32_t enabled_api_layer_count,
|
||||||
|
const char* const* enabled_api_layer_names,
|
||||||
|
std::vector<std::unique_ptr<ApiLayerInterface>>& api_layer_interfaces) {
|
||||||
|
XrResult last_error = XR_SUCCESS;
|
||||||
|
bool any_loaded = false;
|
||||||
|
std::vector<bool> layer_found;
|
||||||
|
std::vector<std::unique_ptr<ApiLayerManifestFile>> layer_manifest_files = {};
|
||||||
|
|
||||||
|
// Find any implicit layers which we may need to report information for.
|
||||||
|
XrResult result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_IMPLICIT_API_LAYER, layer_manifest_files);
|
||||||
|
if (XR_SUCCESS == result) {
|
||||||
|
// Find any explicit layers which we may need to report information for.
|
||||||
|
result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_EXPLICIT_API_LAYER, layer_manifest_files);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put all the enabled layers into a string vector
|
||||||
|
std::vector<std::string> enabled_api_layers = {};
|
||||||
|
AddEnvironmentApiLayers(openxr_command, enabled_api_layers);
|
||||||
|
if (enabled_api_layer_count > 0) {
|
||||||
|
if (nullptr == enabled_api_layer_names) {
|
||||||
|
LoaderLogger::LogErrorMessage(
|
||||||
|
"xrCreateInstance",
|
||||||
|
"VUID-XrInstanceCreateInfo-enabledApiLayerNames-parameter: enabledApiLayerCount is non-0 but array is NULL");
|
||||||
|
LoaderLogger::LogErrorMessage(
|
||||||
|
"xrCreateInstance", "VUID-xrCreateInstance-info-parameter: something wrong with XrInstanceCreateInfo contents");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
auto num_env_api_layers = static_cast<uint32_t>(enabled_api_layers.size());
|
||||||
|
uint32_t total_api_layers = num_env_api_layers + enabled_api_layer_count;
|
||||||
|
enabled_api_layers.resize(total_api_layers);
|
||||||
|
for (uint32_t layer = 0; layer < enabled_api_layer_count; ++layer) {
|
||||||
|
enabled_api_layers[num_env_api_layers + layer] = enabled_api_layer_names[layer];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the layer found vector to false
|
||||||
|
layer_found.resize(enabled_api_layers.size());
|
||||||
|
for (auto&& layer : layer_found) {
|
||||||
|
layer = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::unique_ptr<ApiLayerManifestFile>& manifest_file : layer_manifest_files) {
|
||||||
|
bool enabled = false;
|
||||||
|
|
||||||
|
// Always add implicit layers. They would only be in this list if they were enabled
|
||||||
|
// (i.e. the disable environment variable is not set).
|
||||||
|
if (manifest_file->Type() == MANIFEST_TYPE_IMPLICIT_API_LAYER) {
|
||||||
|
enabled = true;
|
||||||
|
} else {
|
||||||
|
// Only add explicit layers if they are called out by the application
|
||||||
|
for (uint32_t layer = 0; layer < enabled_api_layers.size(); ++layer) {
|
||||||
|
if (enabled_api_layers[layer] == manifest_file->LayerName()) {
|
||||||
|
layer_found[layer] = true;
|
||||||
|
enabled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this layer isn't enabled, skip it.
|
||||||
|
if (!enabled) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoaderPlatformLibraryHandle layer_library = LoaderPlatformLibraryOpen(manifest_file->LibraryPath());
|
||||||
|
if (nullptr == layer_library) {
|
||||||
|
if (!any_loaded) {
|
||||||
|
last_error = XR_ERROR_FILE_ACCESS_ERROR;
|
||||||
|
}
|
||||||
|
std::string library_message = LoaderPlatformLibraryOpenError(manifest_file->LibraryPath());
|
||||||
|
std::string warning_message = "ApiLayerInterface::LoadApiLayers skipping layer ";
|
||||||
|
warning_message += manifest_file->LayerName();
|
||||||
|
warning_message += ", failed to load with message \"";
|
||||||
|
warning_message += library_message;
|
||||||
|
warning_message += "\"";
|
||||||
|
LoaderLogger::LogWarningMessage(openxr_command, warning_message);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get and settle on an layer interface version (using any provided name if required).
|
||||||
|
std::string function_name = manifest_file->GetFunctionName("xrNegotiateLoaderApiLayerInterface");
|
||||||
|
auto negotiate = reinterpret_cast<PFN_xrNegotiateLoaderApiLayerInterface>(
|
||||||
|
LoaderPlatformLibraryGetProcAddr(layer_library, function_name));
|
||||||
|
|
||||||
|
if (nullptr == negotiate) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "ApiLayerInterface::LoadApiLayers skipping layer " << manifest_file->LayerName()
|
||||||
|
<< " because negotiation function " << function_name << " was not found";
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command, oss.str());
|
||||||
|
LoaderPlatformLibraryClose(layer_library);
|
||||||
|
last_error = XR_ERROR_API_LAYER_NOT_PRESENT;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loader info for negotiation
|
||||||
|
XrNegotiateLoaderInfo loader_info = {};
|
||||||
|
loader_info.structType = XR_LOADER_INTERFACE_STRUCT_LOADER_INFO;
|
||||||
|
loader_info.structVersion = XR_LOADER_INFO_STRUCT_VERSION;
|
||||||
|
loader_info.structSize = sizeof(XrNegotiateLoaderInfo);
|
||||||
|
loader_info.minInterfaceVersion = 1;
|
||||||
|
loader_info.maxInterfaceVersion = XR_CURRENT_LOADER_API_LAYER_VERSION;
|
||||||
|
loader_info.minApiVersion = XR_MAKE_VERSION(1, 0, 0);
|
||||||
|
loader_info.maxApiVersion = XR_MAKE_VERSION(1, 0x3ff, 0xfff); // Maximum allowed version for this major version.
|
||||||
|
|
||||||
|
// Set up the layer return structure
|
||||||
|
XrNegotiateApiLayerRequest api_layer_info = {};
|
||||||
|
api_layer_info.structType = XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST;
|
||||||
|
api_layer_info.structVersion = XR_API_LAYER_INFO_STRUCT_VERSION;
|
||||||
|
api_layer_info.structSize = sizeof(XrNegotiateApiLayerRequest);
|
||||||
|
|
||||||
|
XrResult res = negotiate(&loader_info, manifest_file->LayerName().c_str(), &api_layer_info);
|
||||||
|
// If we supposedly succeeded, but got a nullptr for getInstanceProcAddr
|
||||||
|
// then something still went wrong, so return with an error.
|
||||||
|
if (XR_SUCCESS == res && nullptr == api_layer_info.getInstanceProcAddr) {
|
||||||
|
std::string warning_message = "ApiLayerInterface::LoadApiLayers skipping layer ";
|
||||||
|
warning_message += manifest_file->LayerName();
|
||||||
|
warning_message += ", negotiation did not return a valid getInstanceProcAddr";
|
||||||
|
LoaderLogger::LogWarningMessage(openxr_command, warning_message);
|
||||||
|
res = XR_ERROR_FILE_CONTENTS_INVALID;
|
||||||
|
}
|
||||||
|
if (XR_SUCCESS != res) {
|
||||||
|
if (!any_loaded) {
|
||||||
|
last_error = res;
|
||||||
|
}
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "ApiLayerInterface::LoadApiLayers skipping layer " << manifest_file->LayerName()
|
||||||
|
<< " due to failed negotiation with error " << res;
|
||||||
|
LoaderLogger::LogWarningMessage(openxr_command, oss.str());
|
||||||
|
LoaderPlatformLibraryClose(layer_library);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "ApiLayerInterface::LoadApiLayers succeeded loading layer " << manifest_file->LayerName()
|
||||||
|
<< " using interface version " << api_layer_info.layerInterfaceVersion << " and OpenXR API version "
|
||||||
|
<< XR_VERSION_MAJOR(api_layer_info.layerApiVersion) << "." << XR_VERSION_MINOR(api_layer_info.layerApiVersion);
|
||||||
|
LoaderLogger::LogInfoMessage(openxr_command, oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grab the list of extensions this layer supports for easy filtering after the
|
||||||
|
// xrCreateInstance call
|
||||||
|
std::vector<std::string> supported_extensions;
|
||||||
|
std::vector<XrExtensionProperties> extension_properties;
|
||||||
|
manifest_file->GetInstanceExtensionProperties(extension_properties);
|
||||||
|
supported_extensions.reserve(extension_properties.size());
|
||||||
|
for (XrExtensionProperties& ext_prop : extension_properties) {
|
||||||
|
supported_extensions.emplace_back(ext_prop.extensionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add this runtime to the vector
|
||||||
|
api_layer_interfaces.emplace_back(new ApiLayerInterface(manifest_file->LayerName(), layer_library, supported_extensions,
|
||||||
|
api_layer_info.getInstanceProcAddr,
|
||||||
|
api_layer_info.createApiLayerInstance));
|
||||||
|
|
||||||
|
// If we load one, clear all errors.
|
||||||
|
any_loaded = true;
|
||||||
|
last_error = XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If even one of the layers wasn't found, we want to return an error
|
||||||
|
for (uint32_t layer = 0; layer < layer_found.size(); ++layer) {
|
||||||
|
if (!layer_found[layer]) {
|
||||||
|
std::string error_message = "ApiLayerInterface::LoadApiLayers - failed to find layer ";
|
||||||
|
error_message += enabled_api_layers[layer];
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command, error_message);
|
||||||
|
last_error = XR_ERROR_API_LAYER_NOT_PRESENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always clear the manifest file list. Either we use them or we don't.
|
||||||
|
layer_manifest_files.clear();
|
||||||
|
|
||||||
|
// If we failed catastrophically for some reason, clean up everything.
|
||||||
|
if (XR_SUCCESS != last_error) {
|
||||||
|
api_layer_interfaces.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
return last_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ApiLayerInterface::ApiLayerInterface(const std::string& layer_name, LoaderPlatformLibraryHandle layer_library,
|
||||||
|
std::vector<std::string>& supported_extensions,
|
||||||
|
PFN_xrGetInstanceProcAddr get_instant_proc_addr,
|
||||||
|
PFN_xrCreateApiLayerInstance create_api_layer_instance)
|
||||||
|
: _layer_name(layer_name),
|
||||||
|
_layer_library(layer_library),
|
||||||
|
_get_instant_proc_addr(get_instant_proc_addr),
|
||||||
|
_create_api_layer_instance(create_api_layer_instance),
|
||||||
|
_supported_extensions(supported_extensions) {}
|
||||||
|
|
||||||
|
ApiLayerInterface::~ApiLayerInterface() {
|
||||||
|
std::string info_message = "ApiLayerInterface being destroyed for layer ";
|
||||||
|
info_message += _layer_name;
|
||||||
|
LoaderLogger::LogInfoMessage("", info_message);
|
||||||
|
LoaderPlatformLibraryClose(_layer_library);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ApiLayerInterface::SupportsExtension(const std::string& extension_name) {
|
||||||
|
bool found_prop = false;
|
||||||
|
for (const std::string& supported_extension : _supported_extensions) {
|
||||||
|
if (supported_extension == extension_name) {
|
||||||
|
found_prop = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found_prop;
|
||||||
|
}
|
||||||
65
extern/openxr/src/loader/api_layer_interface.hpp
vendored
Normal file
65
extern/openxr/src/loader/api_layer_interface.hpp
vendored
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include "loader_platform.hpp"
|
||||||
|
#include "loader_interfaces.h"
|
||||||
|
|
||||||
|
struct XrGeneratedDispatchTable;
|
||||||
|
|
||||||
|
class ApiLayerInterface {
|
||||||
|
public:
|
||||||
|
// Factory method
|
||||||
|
static XrResult LoadApiLayers(const std::string& openxr_command, uint32_t enabled_api_layer_count,
|
||||||
|
const char* const* enabled_api_layer_names,
|
||||||
|
std::vector<std::unique_ptr<ApiLayerInterface>>& api_layer_interfaces);
|
||||||
|
// Static queries
|
||||||
|
static XrResult GetApiLayerProperties(const std::string& openxr_command, uint32_t incoming_count, uint32_t* outgoing_count,
|
||||||
|
XrApiLayerProperties* api_layer_properties);
|
||||||
|
static XrResult GetInstanceExtensionProperties(const std::string& openxr_command, const char* layer_name,
|
||||||
|
std::vector<XrExtensionProperties>& extension_properties);
|
||||||
|
|
||||||
|
ApiLayerInterface(const std::string& layer_name, LoaderPlatformLibraryHandle layer_library,
|
||||||
|
std::vector<std::string>& supported_extensions, PFN_xrGetInstanceProcAddr get_instant_proc_addr,
|
||||||
|
PFN_xrCreateApiLayerInstance create_api_layer_instance);
|
||||||
|
virtual ~ApiLayerInterface();
|
||||||
|
|
||||||
|
PFN_xrGetInstanceProcAddr GetInstanceProcAddrFuncPointer() { return _get_instant_proc_addr; }
|
||||||
|
PFN_xrCreateApiLayerInstance GetCreateApiLayerInstanceFuncPointer() { return _create_api_layer_instance; }
|
||||||
|
|
||||||
|
std::string LayerName() { return _layer_name; }
|
||||||
|
|
||||||
|
// Generated methods
|
||||||
|
void GenUpdateInstanceDispatchTable(XrInstance instance, std::unique_ptr<XrGeneratedDispatchTable>& table);
|
||||||
|
bool SupportsExtension(const std::string& extension_name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string _layer_name;
|
||||||
|
LoaderPlatformLibraryHandle _layer_library;
|
||||||
|
PFN_xrGetInstanceProcAddr _get_instant_proc_addr;
|
||||||
|
PFN_xrCreateApiLayerInstance _create_api_layer_instance;
|
||||||
|
std::vector<std::string> _supported_extensions;
|
||||||
|
};
|
||||||
45
extern/openxr/src/loader/exception_handling.hpp
vendored
Normal file
45
extern/openxr/src/loader/exception_handling.hpp
vendored
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// Copyright (c) 2019 The Khronos Group Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Ryan Pavlik <ryan.pavlik@collabora.com
|
||||||
|
//
|
||||||
|
// Provides protection for C ABI functions if standard library functions may throw.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common_cmake_config.h"
|
||||||
|
|
||||||
|
#ifdef XRLOADER_ENABLE_EXCEPTION_HANDLING
|
||||||
|
#include <stdexcept>
|
||||||
|
#define XRLOADER_ABI_TRY try
|
||||||
|
#define XRLOADER_ABI_CATCH_BAD_ALLOC_OOM \
|
||||||
|
catch (const std::bad_alloc&) { \
|
||||||
|
LoaderLogger::LogErrorMessage("", "failed allocating memory"); \
|
||||||
|
return XR_ERROR_OUT_OF_MEMORY; \
|
||||||
|
}
|
||||||
|
#define XRLOADER_ABI_CATCH_FALLBACK \
|
||||||
|
catch (const std::exception& e) { \
|
||||||
|
LoaderLogger::LogErrorMessage("", "Unknown failure: " + std::string(e.what())); \
|
||||||
|
return XR_ERROR_RUNTIME_FAILURE; \
|
||||||
|
} \
|
||||||
|
catch (...) { \
|
||||||
|
LoaderLogger::LogErrorMessage("", "Unknown failure"); \
|
||||||
|
return XR_ERROR_RUNTIME_FAILURE; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define XRLOADER_ABI_TRY
|
||||||
|
#define XRLOADER_ABI_CATCH_BAD_ALLOC_OOM
|
||||||
|
#define XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
#endif
|
||||||
98
extern/openxr/src/loader/loader.rc
vendored
Normal file
98
extern/openxr/src/loader/loader.rc
vendored
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2017 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017 Valve Corporation
|
||||||
|
// Copyright (c) 2017 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@LunarG.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Start customize section
|
||||||
|
// Edit this section for your build
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define VERSION_MAJOR 1
|
||||||
|
#define VERSION_MINOR 0
|
||||||
|
#define VERSION_PATCH 1111
|
||||||
|
#define VERSION_BUILDNO 2222
|
||||||
|
|
||||||
|
#define VERSION_BUILD_DESCRIPTION "Dev Build"
|
||||||
|
|
||||||
|
// All builds except release builds should set this to 0.
|
||||||
|
// Release builds should set this to 1.
|
||||||
|
#define VERSION_IS_RELEASEBUILD 0
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// End of customize section
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "winres.h"
|
||||||
|
|
||||||
|
#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_BUILDNO
|
||||||
|
|
||||||
|
#define STRINGIZE2(s) #s
|
||||||
|
#define STRINGIZE(s) STRINGIZE2(s)
|
||||||
|
|
||||||
|
#if VERSION_IS_RELEASEBUILD==1
|
||||||
|
#define VER_FILE_DESCRIPTION_STR "OpenXR Loader"
|
||||||
|
#define VER_FILE_VERSION_STR STRINGIZE(VERSION_MAJOR) \
|
||||||
|
"." STRINGIZE(VERSION_MINOR) \
|
||||||
|
"." STRINGIZE(VERSION_PATCH) \
|
||||||
|
"." STRINGIZE(VERSION_BUILDNO)
|
||||||
|
#else
|
||||||
|
#define VER_FILE_DESCRIPTION_STR "OpenXR Loader - " VERSION_BUILD_DESCRIPTION
|
||||||
|
#define VER_FILE_VERSION_STR STRINGIZE(VERSION_MAJOR) \
|
||||||
|
"." STRINGIZE(VERSION_MINOR) \
|
||||||
|
"." STRINGIZE(VERSION_PATCH) \
|
||||||
|
"." STRINGIZE(VERSION_BUILDNO) \
|
||||||
|
"." VERSION_BUILD_DESCRIPTION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION VER_FILE_VERSION
|
||||||
|
PRODUCTVERSION VER_FILE_VERSION
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS VS_FF_DEBUG
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FILEOS 0x00000L
|
||||||
|
FILETYPE VFT_DLL
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "04090000"
|
||||||
|
BEGIN
|
||||||
|
VALUE "FileDescription", VER_FILE_DESCRIPTION_STR
|
||||||
|
VALUE "FileVersion", VER_FILE_VERSION_STR
|
||||||
|
VALUE "LegalCopyright", "Copyright (C) 2015-2017"
|
||||||
|
VALUE "ProductName", "OpenXR Loader"
|
||||||
|
VALUE "ProductVersion", VER_FILE_VERSION_STR
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 0000
|
||||||
|
END
|
||||||
|
END
|
||||||
650
extern/openxr/src/loader/loader_core.cpp
vendored
Normal file
650
extern/openxr/src/loader/loader_core.cpp
vendored
Normal file
@@ -0,0 +1,650 @@
|
|||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef XR_OS_WINDOWS
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "api_layer_interface.hpp"
|
||||||
|
#include "exception_handling.hpp"
|
||||||
|
#include "hex_and_handles.h"
|
||||||
|
#include "loader_instance.hpp"
|
||||||
|
#include "loader_logger_recorders.hpp"
|
||||||
|
#include "loader_logger.hpp"
|
||||||
|
#include "loader_platform.hpp"
|
||||||
|
#include "runtime_interface.hpp"
|
||||||
|
#include "xr_generated_dispatch_table.h"
|
||||||
|
#include "xr_generated_loader.hpp"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Flag to cause the one time to init to only occur one time.
|
||||||
|
std::once_flag g_one_time_init_flag;
|
||||||
|
|
||||||
|
// Global lock to prevent reading JSON manifest files at the same time.
|
||||||
|
static std::mutex g_loader_json_mutex;
|
||||||
|
|
||||||
|
// Global lock to prevent simultaneous instance creation/destruction
|
||||||
|
static std::mutex g_loader_instance_mutex;
|
||||||
|
|
||||||
|
// Utility template function meant to validate if a fixed size string contains
|
||||||
|
// a null-terminator.
|
||||||
|
template <size_t max_length>
|
||||||
|
inline bool IsMissingNullTerminator(const char (&str)[max_length]) {
|
||||||
|
for (size_t index = 0; index < max_length; ++index) {
|
||||||
|
if (str[index] == '\0') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
// ---- Core 1.0 manual loader trampoline functions
|
||||||
|
|
||||||
|
LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateApiLayerProperties(uint32_t propertyCapacityInput,
|
||||||
|
uint32_t *propertyCountOutput,
|
||||||
|
XrApiLayerProperties *properties) XRLOADER_ABI_TRY {
|
||||||
|
LoaderLogger::LogVerboseMessage("xrEnumerateApiLayerProperties", "Entering loader trampoline");
|
||||||
|
|
||||||
|
// Make sure only one thread is attempting to read the JSON files at a time.
|
||||||
|
std::unique_lock<std::mutex> json_lock(g_loader_json_mutex);
|
||||||
|
|
||||||
|
XrResult result = ApiLayerInterface::GetApiLayerProperties("xrEnumerateApiLayerProperties", propertyCapacityInput,
|
||||||
|
propertyCountOutput, properties);
|
||||||
|
if (XR_SUCCESS != result) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrEnumerateApiLayerProperties", "Failed ApiLayerInterface::GetApiLayerProperties");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
xrEnumerateInstanceExtensionProperties(const char *layerName, uint32_t propertyCapacityInput, uint32_t *propertyCountOutput,
|
||||||
|
XrExtensionProperties *properties) XRLOADER_ABI_TRY {
|
||||||
|
bool just_layer_properties = false;
|
||||||
|
LoaderLogger::LogVerboseMessage("xrEnumerateInstanceExtensionProperties", "Entering loader trampoline");
|
||||||
|
|
||||||
|
if (nullptr != layerName && 0 != strlen(layerName)) {
|
||||||
|
// Application is only interested in layer's properties, not all of them.
|
||||||
|
just_layer_properties = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<XrExtensionProperties> extension_properties = {};
|
||||||
|
XrResult result;
|
||||||
|
|
||||||
|
{
|
||||||
|
// Make sure only one thread is attempting to read the JSON files at a time.
|
||||||
|
std::unique_lock<std::mutex> json_lock(g_loader_json_mutex);
|
||||||
|
|
||||||
|
// Get the layer extension properties
|
||||||
|
result = ApiLayerInterface::GetInstanceExtensionProperties("xrEnumerateInstanceExtensionProperties", layerName,
|
||||||
|
extension_properties);
|
||||||
|
if (XR_SUCCESS == result && !just_layer_properties) {
|
||||||
|
// If not specific to a layer, get the runtime extension properties
|
||||||
|
result = RuntimeInterface::LoadRuntime("xrEnumerateInstanceExtensionProperties");
|
||||||
|
if (XR_SUCCESS == result) {
|
||||||
|
RuntimeInterface::GetRuntime().GetInstanceExtensionProperties(extension_properties);
|
||||||
|
RuntimeInterface::UnloadRuntime("xrEnumerateInstanceExtensionProperties");
|
||||||
|
} else {
|
||||||
|
LoaderLogger::LogErrorMessage("xrEnumerateInstanceExtensionProperties",
|
||||||
|
"Failed to find default runtime with RuntimeInterface::LoadRuntime()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (XR_SUCCESS != result) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrEnumerateInstanceExtensionProperties", "Failed querying extension properties");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is not in reference to a specific layer, then add the loader-specific extension properties as well.
|
||||||
|
// These are extensions that the loader directly supports.
|
||||||
|
if (!just_layer_properties) {
|
||||||
|
auto loader_extension_props = LoaderInstance::LoaderSpecificExtensions();
|
||||||
|
for (XrExtensionProperties &loader_prop : loader_extension_props) {
|
||||||
|
bool found_prop = false;
|
||||||
|
for (XrExtensionProperties &existing_prop : extension_properties) {
|
||||||
|
if (0 == strcmp(existing_prop.extensionName, loader_prop.extensionName)) {
|
||||||
|
found_prop = true;
|
||||||
|
// Use the loader version if it is newer
|
||||||
|
if (existing_prop.extensionVersion < loader_prop.extensionVersion) {
|
||||||
|
existing_prop.extensionVersion = loader_prop.extensionVersion;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Only add extensions not supported by the loader
|
||||||
|
if (!found_prop) {
|
||||||
|
extension_properties.push_back(loader_prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto num_extension_properties = static_cast<uint32_t>(extension_properties.size());
|
||||||
|
if (propertyCapacityInput == 0) {
|
||||||
|
if (nullptr == propertyCountOutput) {
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
*propertyCountOutput = num_extension_properties;
|
||||||
|
} else if (nullptr != properties) {
|
||||||
|
if (propertyCapacityInput < num_extension_properties) {
|
||||||
|
*propertyCountOutput = num_extension_properties;
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrEnumerateInstanceExtensionProperties-propertyCountOutput-parameter",
|
||||||
|
"xrEnumerateInstanceExtensionProperties", "insufficient space in array");
|
||||||
|
return XR_ERROR_SIZE_INSUFFICIENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t num_to_copy = num_extension_properties;
|
||||||
|
// Determine how many extension properties we can copy over
|
||||||
|
if (propertyCapacityInput < num_to_copy) {
|
||||||
|
num_to_copy = propertyCapacityInput;
|
||||||
|
}
|
||||||
|
bool properties_valid = true;
|
||||||
|
for (uint32_t prop = 0; prop < propertyCapacityInput && prop < extension_properties.size(); ++prop) {
|
||||||
|
if (XR_TYPE_EXTENSION_PROPERTIES != properties[prop].type) {
|
||||||
|
properties_valid = false;
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-XrExtensionProperties-type-type",
|
||||||
|
"xrEnumerateInstanceExtensionProperties", "unknown type in properties");
|
||||||
|
}
|
||||||
|
if (nullptr != properties[prop].next) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-XrExtensionProperties-next-next",
|
||||||
|
"xrEnumerateInstanceExtensionProperties", "expected NULL");
|
||||||
|
properties_valid = false;
|
||||||
|
}
|
||||||
|
if (properties_valid) {
|
||||||
|
properties[prop] = extension_properties[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!properties_valid) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrEnumerateInstanceExtensionProperties-properties-parameter",
|
||||||
|
"xrEnumerateInstanceExtensionProperties", "invalid properties");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
if (nullptr != propertyCountOutput) {
|
||||||
|
*propertyCountOutput = num_to_copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LoaderLogger::LogVerboseMessage("xrEnumerateInstanceExtensionProperties", "Completed loader trampoline");
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateInstance(const XrInstanceCreateInfo *info,
|
||||||
|
XrInstance *instance) XRLOADER_ABI_TRY {
|
||||||
|
bool runtime_loaded = false;
|
||||||
|
|
||||||
|
LoaderLogger::LogVerboseMessage("xrCreateInstance", "Entering loader trampoline");
|
||||||
|
if (nullptr == info) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrCreateInstance-info-parameter", "xrCreateInstance", "must be non-NULL");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
// If application requested OpenXR API version is higher than the loader version, then we need to throw
|
||||||
|
// an error.
|
||||||
|
uint16_t app_major = XR_VERSION_MAJOR(info->applicationInfo.apiVersion); // NOLINT
|
||||||
|
uint16_t app_minor = XR_VERSION_MINOR(info->applicationInfo.apiVersion); // NOLINT
|
||||||
|
uint16_t loader_major = XR_VERSION_MAJOR(XR_CURRENT_API_VERSION); // NOLINT
|
||||||
|
uint16_t loader_minor = XR_VERSION_MINOR(XR_CURRENT_API_VERSION); // NOLINT
|
||||||
|
if (app_major > loader_major || (app_major == loader_major && app_minor > loader_minor)) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "xrCreateInstance called with invalid API version " << app_major << "." << app_minor
|
||||||
|
<< ". Max supported version is " << loader_major << "." << loader_minor;
|
||||||
|
LoaderLogger::LogErrorMessage("xrCreateInstance", oss.str());
|
||||||
|
return XR_ERROR_API_VERSION_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullptr == instance) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrCreateInstance-instance-parameter", "xrCreateInstance", "must be non-NULL");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<ApiLayerInterface>> api_layer_interfaces;
|
||||||
|
|
||||||
|
// Make sure only one thread is attempting to read the JSON files and use the instance.
|
||||||
|
XrResult result;
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> json_lock(g_loader_json_mutex);
|
||||||
|
// Load the available runtime
|
||||||
|
result = RuntimeInterface::LoadRuntime("xrCreateInstance");
|
||||||
|
if (XR_SUCCESS != result) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrCreateInstance", "Failed loading runtime information");
|
||||||
|
} else {
|
||||||
|
runtime_loaded = true;
|
||||||
|
// Load the appropriate layers
|
||||||
|
result = ApiLayerInterface::LoadApiLayers("xrCreateInstance", info->enabledApiLayerCount, info->enabledApiLayerNames,
|
||||||
|
api_layer_interfaces);
|
||||||
|
if (XR_SUCCESS != result) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrCreateInstance", "Failed loading layer information");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (XR_FAILED(result)) {
|
||||||
|
if (runtime_loaded) {
|
||||||
|
RuntimeInterface::UnloadRuntime("xrCreateInstance");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_lock<std::mutex> instance_lock(g_loader_instance_mutex);
|
||||||
|
|
||||||
|
// Create the loader instance (only send down first runtime interface)
|
||||||
|
XrInstance created_instance = XR_NULL_HANDLE;
|
||||||
|
result = LoaderInstance::CreateInstance(std::move(api_layer_interfaces), info, &created_instance);
|
||||||
|
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
*instance = created_instance;
|
||||||
|
|
||||||
|
LoaderInstance *loader_instance = g_instance_map.Get(created_instance);
|
||||||
|
|
||||||
|
// Create a debug utils messenger if the create structure is in the "next" chain
|
||||||
|
const auto *next_header = reinterpret_cast<const XrBaseInStructure *>(info->next);
|
||||||
|
const XrDebugUtilsMessengerCreateInfoEXT *dbg_utils_create_info = nullptr;
|
||||||
|
while (next_header != nullptr) {
|
||||||
|
if (next_header->type == XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
|
||||||
|
LoaderLogger::LogInfoMessage("xrCreateInstance", "Found XrDebugUtilsMessengerCreateInfoEXT in \'next\' chain.");
|
||||||
|
dbg_utils_create_info = reinterpret_cast<const XrDebugUtilsMessengerCreateInfoEXT *>(next_header);
|
||||||
|
XrDebugUtilsMessengerEXT messenger;
|
||||||
|
result = xrCreateDebugUtilsMessengerEXT(*instance, dbg_utils_create_info, &messenger);
|
||||||
|
if (XR_SUCCESS != result) {
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
loader_instance->SetDefaultDebugUtilsMessenger(messenger);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
next_header = reinterpret_cast<const XrBaseInStructure *>(next_header->next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LoaderLogger::LogVerboseMessage("xrCreateInstance", "Completed loader trampoline");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroyInstance(XrInstance instance) XRLOADER_ABI_TRY {
|
||||||
|
LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Entering loader trampoline");
|
||||||
|
// Runtimes may detect XR_NULL_HANDLE provided as a required handle parameter and return XR_ERROR_HANDLE_INVALID. - 2.9
|
||||||
|
if (XR_NULL_HANDLE == instance) {
|
||||||
|
return XR_ERROR_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoaderInstance *const loader_instance = g_instance_map.Get(instance);
|
||||||
|
if (loader_instance == nullptr) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrDestroyInstance-instance-parameter", "xrDestroyInstance",
|
||||||
|
"invalid instance");
|
||||||
|
return XR_ERROR_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
|
||||||
|
|
||||||
|
// If we allocated a default debug utils messenger, free it
|
||||||
|
XrDebugUtilsMessengerEXT messenger = loader_instance->DefaultDebugUtilsMessenger();
|
||||||
|
if (messenger != XR_NULL_HANDLE) {
|
||||||
|
xrDestroyDebugUtilsMessengerEXT(messenger);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now destroy the instance
|
||||||
|
if (XR_SUCCESS != dispatch_table->DestroyInstance(instance)) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrDestroyInstance", "Unknown error occurred calling down chain");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup any map entries that may still be using this instance
|
||||||
|
LoaderCleanUpMapsForInstance(loader_instance);
|
||||||
|
|
||||||
|
// Lock the instance create/destroy mutex
|
||||||
|
std::unique_lock<std::mutex> loader_instance_lock(g_loader_instance_mutex);
|
||||||
|
delete loader_instance;
|
||||||
|
LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Completed loader trampoline");
|
||||||
|
|
||||||
|
// Finally, unload the runtime if necessary
|
||||||
|
RuntimeInterface::UnloadRuntime("xrDestroyInstance");
|
||||||
|
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
// ---- Core 1.0 manual loader terminator functions
|
||||||
|
|
||||||
|
// Validate that the applicationInfo structure in the XrInstanceCreateInfo is valid.
|
||||||
|
static XrResult ValidateApplicationInfo(LoaderInstance *loader_instance, const XrApplicationInfo &info) {
|
||||||
|
if (IsMissingNullTerminator<XR_MAX_APPLICATION_NAME_SIZE>(info.applicationName)) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-XrApplicationInfo-applicationName-parameter", "xrCreateInstance",
|
||||||
|
"application name missing NULL terminator.");
|
||||||
|
return XR_ERROR_NAME_INVALID;
|
||||||
|
}
|
||||||
|
if (IsMissingNullTerminator<XR_MAX_ENGINE_NAME_SIZE>(info.engineName)) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-XrApplicationInfo-engineName-parameter", "xrCreateInstance",
|
||||||
|
"engine name missing NULL terminator.");
|
||||||
|
return XR_ERROR_NAME_INVALID;
|
||||||
|
}
|
||||||
|
if (strlen(info.applicationName) == 0) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrCreateInstance",
|
||||||
|
"VUID-XrApplicationInfo-engineName-parameter: application name can not be empty.");
|
||||||
|
return XR_ERROR_NAME_INVALID;
|
||||||
|
}
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate that the XrInstanceCreateInfo is valid
|
||||||
|
static XrResult ValidateInstanceCreateInfo(LoaderInstance *loader_instance, const XrInstanceCreateInfo *info) {
|
||||||
|
// Should have a valid 'type'
|
||||||
|
if (XR_TYPE_INSTANCE_CREATE_INFO != info->type) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-type-type", "xrCreateInstance",
|
||||||
|
"expected XR_TYPE_INSTANCE_CREATE_INFO.");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
// Flags must be 0
|
||||||
|
if (0 != info->createFlags) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-createFlags-zerobitmask", "xrCreateInstance",
|
||||||
|
"flags must be 0.");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
// ApplicationInfo struct must be valid
|
||||||
|
XrResult result = ValidateApplicationInfo(loader_instance, info->applicationInfo);
|
||||||
|
if (XR_SUCCESS != result) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-applicationInfo-parameter", "xrCreateInstance",
|
||||||
|
"info->applicationInfo is not valid.");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// VUID-XrInstanceCreateInfo-enabledApiLayerNames-parameter already tested in LoadApiLayers()
|
||||||
|
if ((info->enabledExtensionCount != 0u) && nullptr == info->enabledExtensionNames) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-enabledExtensionNames-parameter", "xrCreateInstance",
|
||||||
|
"enabledExtensionCount is non-0 but array is NULL");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateInstance(const XrInstanceCreateInfo *info, XrInstance *instance) XRLOADER_ABI_TRY {
|
||||||
|
LoaderLogger::LogVerboseMessage("xrCreateInstance", "Entering loader terminator");
|
||||||
|
LoaderInstance *loader_instance = reinterpret_cast<LoaderInstance *>(*instance);
|
||||||
|
XrResult result = ValidateInstanceCreateInfo(loader_instance, info);
|
||||||
|
if (XR_SUCCESS != result) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrCreateInstance-info-parameter", "xrCreateInstance",
|
||||||
|
"something wrong with XrInstanceCreateInfo contents");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = RuntimeInterface::GetRuntime().CreateInstance(info, instance);
|
||||||
|
loader_instance->SetRuntimeInstance(*instance);
|
||||||
|
LoaderLogger::LogVerboseMessage("xrCreateInstance", "Completed loader terminator");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateApiLayerInstance(const XrInstanceCreateInfo *info,
|
||||||
|
const struct XrApiLayerCreateInfo * /*apiLayerInfo*/,
|
||||||
|
XrInstance *instance) {
|
||||||
|
return LoaderXrTermCreateInstance(info, instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyInstance(XrInstance instance) XRLOADER_ABI_TRY {
|
||||||
|
XrResult result;
|
||||||
|
LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Entering loader terminator");
|
||||||
|
result = RuntimeInterface::GetRuntime().DestroyInstance(instance);
|
||||||
|
LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Completed loader terminator");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
// ---- Extension manual loader trampoline functions
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrCreateDebugUtilsMessengerEXT(XrInstance instance,
|
||||||
|
const XrDebugUtilsMessengerCreateInfoEXT *createInfo,
|
||||||
|
XrDebugUtilsMessengerEXT *messenger) XRLOADER_ABI_TRY {
|
||||||
|
LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Entering loader trampoline");
|
||||||
|
|
||||||
|
LoaderInstance *loader_instance = g_instance_map.Get(instance);
|
||||||
|
if (loader_instance == nullptr) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrCreateDebugUtilsMessengerEXT-instance-parameter",
|
||||||
|
"xrCreateDebugUtilsMessengerEXT", "invalid instance");
|
||||||
|
return XR_ERROR_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!loader_instance->ExtensionIsEnabled(XR_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
|
||||||
|
std::string error_str = "The ";
|
||||||
|
error_str += XR_EXT_DEBUG_UTILS_EXTENSION_NAME;
|
||||||
|
error_str += " extension has not been enabled prior to calling xrCreateDebugUtilsMessengerEXT";
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrCreateDebugUtilsMessengerEXT-extension-notenabled",
|
||||||
|
"xrCreateDebugUtilsMessengerEXT", error_str);
|
||||||
|
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
|
||||||
|
XrResult result = XR_SUCCESS;
|
||||||
|
result = dispatch_table->CreateDebugUtilsMessengerEXT(instance, createInfo, messenger);
|
||||||
|
if (XR_SUCCESS == result && nullptr != messenger) {
|
||||||
|
result = g_debugutilsmessengerext_map.Insert(*messenger, *loader_instance);
|
||||||
|
if (XR_FAILED(result)) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrCreateDebugUtilsMessengerEXT",
|
||||||
|
"Failed inserting new messenger into map: may be null or not unique");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Completed loader trampoline");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_BAD_ALLOC_OOM XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
xrDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT messenger) XRLOADER_ABI_TRY {
|
||||||
|
// TODO: get instance from messenger in loader
|
||||||
|
// Also, is the loader really doing all this every call?
|
||||||
|
LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Entering loader trampoline");
|
||||||
|
|
||||||
|
if (XR_NULL_HANDLE == messenger) {
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoaderInstance *loader_instance = g_debugutilsmessengerext_map.Get(messenger);
|
||||||
|
if (loader_instance == nullptr) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrDestroyDebugUtilsMessengerEXT-messenger-parameter",
|
||||||
|
"xrDestroyDebugUtilsMessengerEXT", "invalid messenger");
|
||||||
|
|
||||||
|
return XR_ERROR_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!loader_instance->ExtensionIsEnabled(XR_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
|
||||||
|
std::string error_str = "The ";
|
||||||
|
error_str += XR_EXT_DEBUG_UTILS_EXTENSION_NAME;
|
||||||
|
error_str += " extension has not been enabled prior to calling xrDestroyDebugUtilsMessengerEXT";
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrDestroyDebugUtilsMessengerEXT-extension-notenabled",
|
||||||
|
"xrDestroyDebugUtilsMessengerEXT", error_str);
|
||||||
|
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
|
||||||
|
XrResult result = dispatch_table->DestroyDebugUtilsMessengerEXT(messenger);
|
||||||
|
LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Completed loader trampoline");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
// ---- Extension manual loader terminator functions
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateDebugUtilsMessengerEXT(XrInstance instance,
|
||||||
|
const XrDebugUtilsMessengerCreateInfoEXT *createInfo,
|
||||||
|
XrDebugUtilsMessengerEXT *messenger) XRLOADER_ABI_TRY {
|
||||||
|
LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Entering loader terminator");
|
||||||
|
if (nullptr == messenger) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrCreateDebugUtilsMessengerEXT-messenger-parameter",
|
||||||
|
"xrCreateDebugUtilsMessengerEXT", "invalid messenger pointer");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance);
|
||||||
|
XrResult result = XR_SUCCESS;
|
||||||
|
// This extension is supported entirely by the loader which means the runtime may or may not support it.
|
||||||
|
if (nullptr != dispatch_table->CreateDebugUtilsMessengerEXT) {
|
||||||
|
result = dispatch_table->CreateDebugUtilsMessengerEXT(instance, createInfo, messenger);
|
||||||
|
} else {
|
||||||
|
// Just allocate a character so we have a unique value
|
||||||
|
char *temp_mess_ptr = new char;
|
||||||
|
*messenger = reinterpret_cast<XrDebugUtilsMessengerEXT>(temp_mess_ptr);
|
||||||
|
}
|
||||||
|
if (XR_SUCCESS == result) {
|
||||||
|
LoaderLogger::GetInstance().AddLogRecorder(MakeDebugUtilsLoaderLogRecorder(createInfo, *messenger));
|
||||||
|
RuntimeInterface::GetRuntime().TrackDebugMessenger(instance, *messenger);
|
||||||
|
}
|
||||||
|
LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Completed loader terminator");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT messenger) XRLOADER_ABI_TRY {
|
||||||
|
LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Entering loader terminator");
|
||||||
|
const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDebugUtilsMessengerDispatchTable(messenger);
|
||||||
|
XrResult result = XR_SUCCESS;
|
||||||
|
LoaderLogger::GetInstance().RemoveLogRecorder(MakeHandleGeneric(messenger));
|
||||||
|
RuntimeInterface::GetRuntime().ForgetDebugMessenger(messenger);
|
||||||
|
// This extension is supported entirely by the loader which means the runtime may or may not support it.
|
||||||
|
if (nullptr != dispatch_table->DestroyDebugUtilsMessengerEXT) {
|
||||||
|
result = dispatch_table->DestroyDebugUtilsMessengerEXT(messenger);
|
||||||
|
} else {
|
||||||
|
// Delete the character we would've created
|
||||||
|
delete (reinterpret_cast<char *>(MakeHandleGeneric(messenger)));
|
||||||
|
}
|
||||||
|
LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Completed loader terminator");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermSubmitDebugUtilsMessageEXT(
|
||||||
|
XrInstance instance, XrDebugUtilsMessageSeverityFlagsEXT messageSeverity, XrDebugUtilsMessageTypeFlagsEXT messageTypes,
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT *callbackData) XRLOADER_ABI_TRY {
|
||||||
|
LoaderLogger::LogVerboseMessage("xrSubmitDebugUtilsMessageEXT", "Entering loader terminator");
|
||||||
|
const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance);
|
||||||
|
XrResult result = XR_SUCCESS;
|
||||||
|
if (nullptr != dispatch_table->SubmitDebugUtilsMessageEXT) {
|
||||||
|
result = dispatch_table->SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, callbackData);
|
||||||
|
} else {
|
||||||
|
// Only log the message from the loader if the runtime doesn't support this extension. If we did,
|
||||||
|
// then the user would receive multiple instances of the same message.
|
||||||
|
LoaderLogger::GetInstance().LogDebugUtilsMessage(messageSeverity, messageTypes, callbackData);
|
||||||
|
}
|
||||||
|
LoaderLogger::LogVerboseMessage("xrSubmitDebugUtilsMessageEXT", "Completed loader terminator");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
LoaderXrTermSetDebugUtilsObjectNameEXT(XrInstance instance, const XrDebugUtilsObjectNameInfoEXT *nameInfo) XRLOADER_ABI_TRY {
|
||||||
|
LoaderLogger::LogVerboseMessage("xrSetDebugUtilsObjectNameEXT", "Entering loader terminator");
|
||||||
|
const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance);
|
||||||
|
XrResult result = XR_SUCCESS;
|
||||||
|
if (nullptr != dispatch_table->SetDebugUtilsObjectNameEXT) {
|
||||||
|
result = dispatch_table->SetDebugUtilsObjectNameEXT(instance, nameInfo);
|
||||||
|
}
|
||||||
|
LoaderLogger::GetInstance().AddObjectName(nameInfo->objectHandle, nameInfo->objectType, nameInfo->objectName);
|
||||||
|
LoaderLogger::LogVerboseMessage("xrSetDebugUtilsObjectNameEXT", "Completed loader terminator");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrSessionBeginDebugUtilsLabelRegionEXT(XrSession session,
|
||||||
|
const XrDebugUtilsLabelEXT *labelInfo) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance *loader_instance = g_session_map.Get(session);
|
||||||
|
if (nullptr == loader_instance) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrSessionBeginDebugUtilsLabelRegionEXT-session-parameter",
|
||||||
|
"xrSessionBeginDebugUtilsLabelRegionEXT", "session is not a valid XrSession",
|
||||||
|
{XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
|
||||||
|
return XR_ERROR_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
if (!loader_instance->ExtensionIsEnabled(XR_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("TBD", "xrSessionBeginDebugUtilsLabelRegionEXT",
|
||||||
|
"Extension entrypoint called without enabling appropriate extension",
|
||||||
|
{XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
|
||||||
|
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
if (nullptr == labelInfo) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrSessionBeginDebugUtilsLabelRegionEXT-labelInfo-parameter",
|
||||||
|
"xrSessionBeginDebugUtilsLabelRegionEXT", "labelInfo must be non-NULL",
|
||||||
|
{XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoaderLogger::GetInstance().BeginLabelRegion(session, labelInfo);
|
||||||
|
const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
|
||||||
|
if (nullptr != dispatch_table->SessionBeginDebugUtilsLabelRegionEXT) {
|
||||||
|
return dispatch_table->SessionBeginDebugUtilsLabelRegionEXT(session, labelInfo);
|
||||||
|
}
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrSessionEndDebugUtilsLabelRegionEXT(XrSession session) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance *loader_instance = g_session_map.Get(session);
|
||||||
|
if (nullptr == loader_instance) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrSessionEndDebugUtilsLabelRegionEXT-session-parameter",
|
||||||
|
"xrSessionEndDebugUtilsLabelRegionEXT", "session is not a valid XrSession",
|
||||||
|
{XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
|
||||||
|
return XR_ERROR_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
if (!loader_instance->ExtensionIsEnabled(XR_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
|
||||||
|
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
LoaderLogger::GetInstance().EndLabelRegion(session);
|
||||||
|
const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
|
||||||
|
if (nullptr != dispatch_table->SessionBeginDebugUtilsLabelRegionEXT) {
|
||||||
|
return dispatch_table->SessionEndDebugUtilsLabelRegionEXT(session);
|
||||||
|
}
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrSessionInsertDebugUtilsLabelEXT(XrSession session,
|
||||||
|
const XrDebugUtilsLabelEXT *labelInfo) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance *loader_instance = g_session_map.Get(session);
|
||||||
|
if (nullptr == loader_instance) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrSessionInsertDebugUtilsLabelEXT-session-parameter",
|
||||||
|
"xrSessionInsertDebugUtilsLabelEXT", "session is not a valid XrSession",
|
||||||
|
{XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
|
||||||
|
return XR_ERROR_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
if (!loader_instance->ExtensionIsEnabled(XR_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("TBD", "xrSessionInsertDebugUtilsLabelEXT",
|
||||||
|
"Extension entrypoint called without enabling appropriate extension",
|
||||||
|
{XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
|
||||||
|
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
if (nullptr == labelInfo) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrSessionInsertDebugUtilsLabelEXT-labelInfo-parameter",
|
||||||
|
"xrSessionInsertDebugUtilsLabelEXT", "labelInfo must be non-NULL",
|
||||||
|
{XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoaderLogger::GetInstance().InsertLabel(session, labelInfo);
|
||||||
|
const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
|
||||||
|
if (nullptr != dispatch_table->SessionInsertDebugUtilsLabelEXT) {
|
||||||
|
return dispatch_table->SessionInsertDebugUtilsLabelEXT(session, labelInfo);
|
||||||
|
}
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
} // extern "C"
|
||||||
235
extern/openxr/src/loader/loader_instance.cpp
vendored
Normal file
235
extern/openxr/src/loader/loader_instance.cpp
vendored
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef XR_OS_WINDOWS
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "loader_instance.hpp"
|
||||||
|
|
||||||
|
#include "api_layer_interface.hpp"
|
||||||
|
#include "hex_and_handles.h"
|
||||||
|
#include "loader_interfaces.h"
|
||||||
|
#include "loader_logger.hpp"
|
||||||
|
#include "runtime_interface.hpp"
|
||||||
|
#include "xr_generated_dispatch_table.h"
|
||||||
|
#include "xr_generated_loader.hpp"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Extensions that are supported by the loader, but may not be supported
|
||||||
|
// the the runtime.
|
||||||
|
static const XrExtensionProperties g_debug_utils_props = {XR_TYPE_EXTENSION_PROPERTIES, nullptr, XR_EXT_DEBUG_UTILS_EXTENSION_NAME,
|
||||||
|
XR_EXT_debug_utils_SPEC_VERSION};
|
||||||
|
const std::vector<XrExtensionProperties> LoaderInstance::_loader_supported_extensions = {g_debug_utils_props};
|
||||||
|
|
||||||
|
// Factory method
|
||||||
|
XrResult LoaderInstance::CreateInstance(std::vector<std::unique_ptr<ApiLayerInterface>>&& api_layer_interfaces,
|
||||||
|
const XrInstanceCreateInfo* info, XrInstance* instance) {
|
||||||
|
XrResult last_error = XR_SUCCESS;
|
||||||
|
LoaderLogger::LogVerboseMessage("xrCreateInstance", "Entering LoaderInstance::CreateInstance");
|
||||||
|
|
||||||
|
// Topmost means "closest to the application"
|
||||||
|
PFN_xrCreateInstance topmost_ci_fp = LoaderXrTermCreateInstance;
|
||||||
|
PFN_xrCreateApiLayerInstance topmost_cali_fp = LoaderXrTermCreateApiLayerInstance;
|
||||||
|
|
||||||
|
// Create the loader instance
|
||||||
|
std::unique_ptr<LoaderInstance> loader_instance(new LoaderInstance(std::move(api_layer_interfaces)));
|
||||||
|
*instance = reinterpret_cast<XrInstance>(loader_instance.get());
|
||||||
|
|
||||||
|
// Only start the xrCreateApiLayerInstance stack if we have layers.
|
||||||
|
std::vector<std::unique_ptr<ApiLayerInterface>>& layer_interfaces = loader_instance->LayerInterfaces();
|
||||||
|
if (!layer_interfaces.empty()) {
|
||||||
|
// Initialize an array of ApiLayerNextInfo structs
|
||||||
|
auto* next_info_list = new XrApiLayerNextInfo[layer_interfaces.size()];
|
||||||
|
auto ni_index = static_cast<uint32_t>(layer_interfaces.size() - 1);
|
||||||
|
for (uint32_t i = 0; i <= ni_index; i++) {
|
||||||
|
next_info_list[i].structType = XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO;
|
||||||
|
next_info_list[i].structVersion = XR_API_LAYER_NEXT_INFO_STRUCT_VERSION;
|
||||||
|
next_info_list[i].structSize = sizeof(XrApiLayerNextInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go through all layers, and override the instance pointers with the layer version. However,
|
||||||
|
// go backwards through the layer list so we replace in reverse order so the layers can call their next function
|
||||||
|
// appropriately.
|
||||||
|
XrApiLayerNextInfo* prev_nextinfo = nullptr;
|
||||||
|
PFN_xrGetInstanceProcAddr prev_gipa_fp = LoaderXrTermGetInstanceProcAddr;
|
||||||
|
PFN_xrCreateApiLayerInstance prev_cali_fp = LoaderXrTermCreateApiLayerInstance;
|
||||||
|
for (auto layer_interface = layer_interfaces.rbegin(); layer_interface != layer_interfaces.rend(); ++layer_interface) {
|
||||||
|
// Collect current layer's function pointers
|
||||||
|
PFN_xrGetInstanceProcAddr cur_gipa_fp = (*layer_interface)->GetInstanceProcAddrFuncPointer();
|
||||||
|
PFN_xrCreateApiLayerInstance cur_cali_fp = (*layer_interface)->GetCreateApiLayerInstanceFuncPointer();
|
||||||
|
// Update topmosts
|
||||||
|
cur_gipa_fp(XR_NULL_HANDLE, "xrCreateInstance", reinterpret_cast<PFN_xrVoidFunction*>(&topmost_ci_fp));
|
||||||
|
topmost_cali_fp = cur_cali_fp;
|
||||||
|
|
||||||
|
// Fill in layer info and link previous (lower) layer fxn pointers
|
||||||
|
strncpy(next_info_list[ni_index].layerName, (*layer_interface)->LayerName().c_str(), XR_MAX_API_LAYER_NAME_SIZE - 1);
|
||||||
|
next_info_list[ni_index].layerName[XR_MAX_API_LAYER_NAME_SIZE - 1] = '\0';
|
||||||
|
next_info_list[ni_index].next = prev_nextinfo;
|
||||||
|
next_info_list[ni_index].nextGetInstanceProcAddr = prev_gipa_fp;
|
||||||
|
next_info_list[ni_index].nextCreateApiLayerInstance = prev_cali_fp;
|
||||||
|
|
||||||
|
// Update saved pointers for next iteration
|
||||||
|
prev_nextinfo = &next_info_list[ni_index];
|
||||||
|
prev_gipa_fp = cur_gipa_fp;
|
||||||
|
prev_cali_fp = cur_cali_fp;
|
||||||
|
ni_index--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate the ApiLayerCreateInfo struct and pass to topmost CreateApiLayerInstance()
|
||||||
|
XrApiLayerCreateInfo api_layer_ci = {};
|
||||||
|
api_layer_ci.structType = XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO;
|
||||||
|
api_layer_ci.structVersion = XR_API_LAYER_CREATE_INFO_STRUCT_VERSION;
|
||||||
|
api_layer_ci.structSize = sizeof(XrApiLayerCreateInfo);
|
||||||
|
api_layer_ci.loaderInstance = reinterpret_cast<void*>(loader_instance.get());
|
||||||
|
api_layer_ci.settings_file_location[0] = '\0';
|
||||||
|
api_layer_ci.nextInfo = next_info_list;
|
||||||
|
last_error = topmost_cali_fp(info, &api_layer_ci, instance);
|
||||||
|
|
||||||
|
delete[] next_info_list;
|
||||||
|
} else {
|
||||||
|
last_error = topmost_ci_fp(info, instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (XR_SUCCEEDED(last_error)) {
|
||||||
|
// Check the list of enabled extensions to make sure something supports them, and, if we do,
|
||||||
|
// add it to the list of enabled extensions
|
||||||
|
for (uint32_t ext = 0; ext < info->enabledExtensionCount; ++ext) {
|
||||||
|
bool found = false;
|
||||||
|
// First check the runtime
|
||||||
|
if (RuntimeInterface::GetRuntime().SupportsExtension(info->enabledExtensionNames[ext])) {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
// Next check the loader
|
||||||
|
if (!found) {
|
||||||
|
for (auto loader_extension : LoaderInstance::_loader_supported_extensions) {
|
||||||
|
if (strcmp(loader_extension.extensionName, info->enabledExtensionNames[ext]) == 0) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Finally, check the enabled layers
|
||||||
|
if (!found) {
|
||||||
|
for (auto& layer_interface : layer_interfaces) {
|
||||||
|
if (layer_interface->SupportsExtension(info->enabledExtensionNames[ext])) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
std::string msg = "LoaderInstance::CreateInstance, no support found for requested extension: ";
|
||||||
|
msg += info->enabledExtensionNames[ext];
|
||||||
|
LoaderLogger::LogErrorMessage("xrCreateInstance", msg);
|
||||||
|
last_error = XR_ERROR_EXTENSION_NOT_PRESENT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
loader_instance->AddEnabledExtension(info->enabledExtensionNames[ext]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LoaderLogger::LogErrorMessage("xrCreateInstance", "LoaderInstance::CreateInstance chained CreateInstance call failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (XR_SUCCEEDED(last_error)) {
|
||||||
|
// Create the top-level dispatch table for the instance. This will contain the function pointers to the
|
||||||
|
// first instantiation of every command, whether that is in a layer, or a runtime.
|
||||||
|
last_error = loader_instance->CreateDispatchTable(*instance);
|
||||||
|
if (XR_FAILED(last_error)) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrCreateInstance",
|
||||||
|
"LoaderInstance::CreateInstance failed creating top-level dispatch table");
|
||||||
|
} else {
|
||||||
|
last_error = g_instance_map.Insert(*instance, *loader_instance);
|
||||||
|
if (XR_FAILED(last_error)) {
|
||||||
|
LoaderLogger::LogErrorMessage(
|
||||||
|
"xrCreateInstance",
|
||||||
|
"LoaderInstance::CreateInstance failed inserting new instance into map: may be null or not unique");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (XR_SUCCEEDED(last_error)) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "LoaderInstance::CreateInstance succeeded with ";
|
||||||
|
oss << loader_instance->LayerInterfaces().size();
|
||||||
|
oss << " layers enabled and runtime interface - created instance = ";
|
||||||
|
oss << HandleToHexString(*instance);
|
||||||
|
LoaderLogger::LogInfoMessage("xrCreateInstance", oss.str());
|
||||||
|
// Make the unique_ptr no longer delete this.
|
||||||
|
// Don't need to save the return value because we already set *instance
|
||||||
|
(void)loader_instance.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always clear the input lists. Either we use them or we don't.
|
||||||
|
api_layer_interfaces.clear();
|
||||||
|
|
||||||
|
return last_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoaderInstance::LoaderInstance(std::vector<std::unique_ptr<ApiLayerInterface>>&& api_layer_interfaces)
|
||||||
|
: _unique_id(0xDECAFBAD),
|
||||||
|
_api_version(XR_CURRENT_API_VERSION),
|
||||||
|
_api_layer_interfaces(std::move(api_layer_interfaces)),
|
||||||
|
_dispatch_valid(false),
|
||||||
|
_messenger(XR_NULL_HANDLE) {}
|
||||||
|
|
||||||
|
LoaderInstance::~LoaderInstance() {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Destroying LoaderInstance = ";
|
||||||
|
oss << PointerToHexString(this);
|
||||||
|
LoaderLogger::LogInfoMessage("xrDestroyInstance", oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult LoaderInstance::CreateDispatchTable(XrInstance instance) {
|
||||||
|
XrResult res = XR_SUCCESS;
|
||||||
|
// Create the top-level dispatch table. First, we want to start with a dispatch table generated
|
||||||
|
// using the commands from the runtime, with the exception of commands that we need a terminator
|
||||||
|
// for. The loaderGenInitInstanceDispatchTable utility function handles that automatically for us.
|
||||||
|
std::unique_ptr<XrGeneratedDispatchTable> new_instance_dispatch_table(new XrGeneratedDispatchTable());
|
||||||
|
LoaderGenInitInstanceDispatchTable(_runtime_instance, new_instance_dispatch_table);
|
||||||
|
|
||||||
|
// Go through all layers, and override the instance pointers with the layer version. However,
|
||||||
|
// go backwards through the layer list so we replace in reverse order so the layers can call their next function
|
||||||
|
// appropriately.
|
||||||
|
if (!_api_layer_interfaces.empty()) {
|
||||||
|
(*_api_layer_interfaces.begin())->GenUpdateInstanceDispatchTable(instance, new_instance_dispatch_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the top-level instance dispatch table to the top-most commands now that we've figured them out.
|
||||||
|
_dispatch_table = std::move(new_instance_dispatch_table);
|
||||||
|
_dispatch_valid = true;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoaderInstance::ExtensionIsEnabled(const std::string& extension) {
|
||||||
|
for (std::string& cur_enabled : _enabled_extensions) {
|
||||||
|
if (cur_enabled == extension) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
155
extern/openxr/src/loader/loader_instance.hpp
vendored
Normal file
155
extern/openxr/src/loader/loader_instance.hpp
vendored
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "extra_algorithms.h"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class LoaderInstance;
|
||||||
|
class ApiLayerInterface;
|
||||||
|
struct XrGeneratedDispatchTable;
|
||||||
|
|
||||||
|
typedef std::unique_lock<std::mutex> UniqueLock;
|
||||||
|
template <typename HandleType>
|
||||||
|
class HandleLoaderMap {
|
||||||
|
public:
|
||||||
|
using handle_t = HandleType;
|
||||||
|
using map_t = std::unordered_map<HandleType, LoaderInstance*>;
|
||||||
|
using value_t = typename map_t::value_type;
|
||||||
|
|
||||||
|
/// Lookup a handle.
|
||||||
|
/// Returns nullptr if not found.
|
||||||
|
LoaderInstance* Get(HandleType handle);
|
||||||
|
|
||||||
|
/// Insert an info for the supplied handle.
|
||||||
|
/// Returns XR_ERROR_RUNTIME_FAILURE if it's null.
|
||||||
|
/// Does not error if already there, because the loader is not currently very good at cleaning up handles.
|
||||||
|
XrResult Insert(HandleType handle, LoaderInstance& loader);
|
||||||
|
|
||||||
|
/// Remove the info associated with the supplied handle.
|
||||||
|
/// Returns XR_ERROR_RUNTIME_FAILURE if it's null or not there.
|
||||||
|
XrResult Erase(HandleType handle);
|
||||||
|
|
||||||
|
/// Removes handles associated with a loader instance.
|
||||||
|
void RemoveHandlesForLoader(LoaderInstance& loader);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
map_t instance_map_;
|
||||||
|
std::mutex mutex_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LoaderInstance {
|
||||||
|
public:
|
||||||
|
// Factory method
|
||||||
|
static XrResult CreateInstance(std::vector<std::unique_ptr<ApiLayerInterface>>&& layer_interfaces,
|
||||||
|
const XrInstanceCreateInfo* info, XrInstance* instance);
|
||||||
|
|
||||||
|
LoaderInstance(std::vector<std::unique_ptr<ApiLayerInterface>>&& api_layer_interfaces);
|
||||||
|
virtual ~LoaderInstance();
|
||||||
|
|
||||||
|
bool IsValid() { return _unique_id == 0xDECAFBAD; }
|
||||||
|
XrVersion ApiVersion() { return _api_version; }
|
||||||
|
XrResult CreateDispatchTable(XrInstance instance);
|
||||||
|
void SetRuntimeInstance(XrInstance instance) { _runtime_instance = instance; }
|
||||||
|
const std::unique_ptr<XrGeneratedDispatchTable>& DispatchTable() { return _dispatch_table; }
|
||||||
|
std::vector<std::unique_ptr<ApiLayerInterface>>& LayerInterfaces() { return _api_layer_interfaces; }
|
||||||
|
void AddEnabledExtension(const std::string& extension) { return _enabled_extensions.push_back(extension); }
|
||||||
|
bool ExtensionIsEnabled(const std::string& extension);
|
||||||
|
static const std::vector<XrExtensionProperties>& LoaderSpecificExtensions() { return _loader_supported_extensions; }
|
||||||
|
XrDebugUtilsMessengerEXT DefaultDebugUtilsMessenger() { return _messenger; }
|
||||||
|
void SetDefaultDebugUtilsMessenger(XrDebugUtilsMessengerEXT messenger) { _messenger = messenger; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t _unique_id; // 0xDECAFBAD - for debugging
|
||||||
|
XrVersion _api_version;
|
||||||
|
std::vector<std::unique_ptr<ApiLayerInterface>> _api_layer_interfaces;
|
||||||
|
XrInstance _runtime_instance;
|
||||||
|
bool _dispatch_valid;
|
||||||
|
std::unique_ptr<XrGeneratedDispatchTable> _dispatch_table;
|
||||||
|
static const std::vector<XrExtensionProperties> _loader_supported_extensions;
|
||||||
|
std::vector<std::string> _enabled_extensions;
|
||||||
|
// Internal debug messenger created during xrCreateInstance
|
||||||
|
XrDebugUtilsMessengerEXT _messenger;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename HandleType>
|
||||||
|
inline LoaderInstance* HandleLoaderMap<HandleType>::Get(HandleType handle) {
|
||||||
|
if (handle == XR_NULL_HANDLE) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
// Try to find the handle in the appropriate map
|
||||||
|
UniqueLock lock(mutex_);
|
||||||
|
auto entry_returned = instance_map_.find(handle);
|
||||||
|
if (entry_returned == instance_map_.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return entry_returned->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename HandleType>
|
||||||
|
inline XrResult HandleLoaderMap<HandleType>::Insert(HandleType handle, LoaderInstance& loader) {
|
||||||
|
if (handle == XR_NULL_HANDLE) {
|
||||||
|
// Internal error in loader or runtime.
|
||||||
|
return XR_ERROR_RUNTIME_FAILURE;
|
||||||
|
}
|
||||||
|
UniqueLock lock(mutex_);
|
||||||
|
//! @todo This check is currently disabled, because the loader is not good at cleaning up handles when their parent handles are
|
||||||
|
//! destroyed.
|
||||||
|
#if 0
|
||||||
|
auto entry_returned = instance_map_.find(handle);
|
||||||
|
if (entry_returned != instance_map_.end()) {
|
||||||
|
// Internal error in loader or runtime.
|
||||||
|
return XR_ERROR_RUNTIME_FAILURE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
instance_map_[handle] = &loader;
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename HandleType>
|
||||||
|
inline XrResult HandleLoaderMap<HandleType>::Erase(HandleType handle) {
|
||||||
|
if (handle == XR_NULL_HANDLE) {
|
||||||
|
// Internal error in loader or runtime.
|
||||||
|
return XR_ERROR_RUNTIME_FAILURE;
|
||||||
|
}
|
||||||
|
UniqueLock lock(mutex_);
|
||||||
|
auto entry_returned = instance_map_.find(handle);
|
||||||
|
if (entry_returned == instance_map_.end()) {
|
||||||
|
// Internal error in loader or runtime.
|
||||||
|
return XR_ERROR_RUNTIME_FAILURE;
|
||||||
|
}
|
||||||
|
instance_map_.erase(handle);
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename HandleType>
|
||||||
|
inline void HandleLoaderMap<HandleType>::RemoveHandlesForLoader(LoaderInstance& loader) {
|
||||||
|
UniqueLock lock(mutex_);
|
||||||
|
auto search_value = &loader;
|
||||||
|
map_erase_if(instance_map_, [=](value_t const& data) { return data.second && data.second == search_value; });
|
||||||
|
}
|
||||||
405
extern/openxr/src/loader/loader_logger.cpp
vendored
Normal file
405
extern/openxr/src/loader/loader_logger.cpp
vendored
Normal file
@@ -0,0 +1,405 @@
|
|||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "loader_logger.hpp"
|
||||||
|
|
||||||
|
#include "extra_algorithms.h"
|
||||||
|
#include "hex_and_handles.h"
|
||||||
|
#include "loader_logger_recorders.hpp"
|
||||||
|
#include "platform_utils.hpp"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
std::unique_ptr<LoaderLogger> LoaderLogger::_instance;
|
||||||
|
std::once_flag LoaderLogger::_once_flag;
|
||||||
|
|
||||||
|
std::string XrLoaderLogObjectInfo::ToString() const {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << Uint64ToHexString(handle);
|
||||||
|
if (!name.empty()) {
|
||||||
|
oss << " (" << name << ")";
|
||||||
|
}
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoaderLogRecorder::LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT /*message_severity*/,
|
||||||
|
XrDebugUtilsMessageTypeFlagsEXT /*message_type*/,
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT* /*callback_data*/) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectInfoCollection::AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name) {
|
||||||
|
// If name is empty, we should erase it
|
||||||
|
if (object_name.empty()) {
|
||||||
|
vector_remove_if_and_erase(_object_info, [=](XrLoaderLogObjectInfo const& info) { return info.handle == object_handle; });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Otherwise, add it or update the name
|
||||||
|
|
||||||
|
XrLoaderLogObjectInfo new_obj = {object_handle, object_type};
|
||||||
|
|
||||||
|
// If it already exists, update the name
|
||||||
|
auto lookup_info = LookUpStoredObjectInfo(new_obj);
|
||||||
|
if (lookup_info != nullptr) {
|
||||||
|
lookup_info->name = object_name;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It doesn't exist, so add a new info block
|
||||||
|
new_obj.name = object_name;
|
||||||
|
_object_info.push_back(new_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
XrLoaderLogObjectInfo const* ObjectInfoCollection::LookUpStoredObjectInfo(XrLoaderLogObjectInfo const& info) const {
|
||||||
|
auto e = _object_info.end();
|
||||||
|
auto it = std::find_if(_object_info.begin(), e, [&](XrLoaderLogObjectInfo const& stored) { return Equivalent(stored, info); });
|
||||||
|
if (it != e) {
|
||||||
|
return &(*it);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrLoaderLogObjectInfo* ObjectInfoCollection::LookUpStoredObjectInfo(XrLoaderLogObjectInfo const& info) {
|
||||||
|
auto e = _object_info.end();
|
||||||
|
auto it = std::find_if(_object_info.begin(), e, [&](XrLoaderLogObjectInfo const& stored) { return Equivalent(stored, info); });
|
||||||
|
if (it != e) {
|
||||||
|
return &(*it);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectInfoCollection::LookUpObjectName(XrDebugUtilsObjectNameInfoEXT& info) const {
|
||||||
|
auto info_lookup = LookUpStoredObjectInfo(info.objectHandle, info.objectType);
|
||||||
|
if (info_lookup != nullptr) {
|
||||||
|
info.objectName = info_lookup->name.c_str();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectInfoCollection::LookUpObjectName(XrLoaderLogObjectInfo& info) const {
|
||||||
|
auto info_lookup = LookUpStoredObjectInfo(info);
|
||||||
|
if (info_lookup != nullptr) {
|
||||||
|
info.name = info_lookup->name;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility functions for converting to/from XR_EXT_debug_utils values
|
||||||
|
|
||||||
|
XrLoaderLogMessageSeverityFlags DebugUtilsSeveritiesToLoaderLogMessageSeverities(
|
||||||
|
XrDebugUtilsMessageSeverityFlagsEXT utils_severities) {
|
||||||
|
XrLoaderLogMessageSeverityFlags log_severities = 0UL;
|
||||||
|
if ((utils_severities & XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) != 0u) {
|
||||||
|
log_severities |= XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT;
|
||||||
|
}
|
||||||
|
if ((utils_severities & XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0u) {
|
||||||
|
log_severities |= XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT;
|
||||||
|
}
|
||||||
|
if ((utils_severities & XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0u) {
|
||||||
|
log_severities |= XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT;
|
||||||
|
}
|
||||||
|
if ((utils_severities & XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0u) {
|
||||||
|
log_severities |= XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT;
|
||||||
|
}
|
||||||
|
return log_severities;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrDebugUtilsMessageSeverityFlagsEXT LoaderLogMessageSeveritiesToDebugUtilsMessageSeverities(
|
||||||
|
XrLoaderLogMessageSeverityFlags log_severities) {
|
||||||
|
XrDebugUtilsMessageSeverityFlagsEXT utils_severities = 0UL;
|
||||||
|
if ((log_severities & XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT) != 0u) {
|
||||||
|
utils_severities |= XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
|
||||||
|
}
|
||||||
|
if ((log_severities & XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT) != 0u) {
|
||||||
|
utils_severities |= XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
|
||||||
|
}
|
||||||
|
if ((log_severities & XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT) != 0u) {
|
||||||
|
utils_severities |= XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
|
||||||
|
}
|
||||||
|
if ((log_severities & XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT) != 0u) {
|
||||||
|
utils_severities |= XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
||||||
|
}
|
||||||
|
return utils_severities;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrLoaderLogMessageTypeFlagBits DebugUtilsMessageTypesToLoaderLogMessageTypes(XrDebugUtilsMessageTypeFlagsEXT utils_types) {
|
||||||
|
XrLoaderLogMessageTypeFlagBits log_types = 0UL;
|
||||||
|
if ((utils_types & XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) != 0u) {
|
||||||
|
log_types |= XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT;
|
||||||
|
}
|
||||||
|
if ((utils_types & XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) != 0u) {
|
||||||
|
log_types |= XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT;
|
||||||
|
}
|
||||||
|
if ((utils_types & XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) != 0u) {
|
||||||
|
log_types |= XR_LOADER_LOG_MESSAGE_TYPE_PERFORMANCE_BIT;
|
||||||
|
}
|
||||||
|
return log_types;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrDebugUtilsMessageTypeFlagsEXT LoaderLogMessageTypesToDebugUtilsMessageTypes(XrLoaderLogMessageTypeFlagBits log_types) {
|
||||||
|
XrDebugUtilsMessageTypeFlagsEXT utils_types = 0UL;
|
||||||
|
if ((log_types & XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT) != 0u) {
|
||||||
|
utils_types |= XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
|
||||||
|
}
|
||||||
|
if ((log_types & XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT) != 0u) {
|
||||||
|
utils_types |= XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
|
||||||
|
}
|
||||||
|
if ((log_types & XR_LOADER_LOG_MESSAGE_TYPE_PERFORMANCE_BIT) != 0u) {
|
||||||
|
utils_types |= XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
||||||
|
}
|
||||||
|
return utils_types;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoaderLogger::LoaderLogger() {
|
||||||
|
// Add an error logger by default so that we at least get errors out to std::cerr.
|
||||||
|
AddLogRecorder(MakeStdErrLoaderLogRecorder(nullptr));
|
||||||
|
|
||||||
|
// If the environment variable to enable loader debugging is set, then enable the
|
||||||
|
// appropriate logging out to std::cout.
|
||||||
|
char* loader_debug = PlatformUtilsGetSecureEnv("XR_LOADER_DEBUG");
|
||||||
|
if (nullptr != loader_debug) {
|
||||||
|
std::string debug_string = loader_debug;
|
||||||
|
PlatformUtilsFreeEnv(loader_debug);
|
||||||
|
XrLoaderLogMessageSeverityFlags debug_flags = {};
|
||||||
|
if (debug_string == "error") {
|
||||||
|
debug_flags = XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT;
|
||||||
|
} else if (debug_string == "warn") {
|
||||||
|
debug_flags = XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT | XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT;
|
||||||
|
} else if (debug_string == "info") {
|
||||||
|
debug_flags = XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT | XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT |
|
||||||
|
XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT;
|
||||||
|
} else if (debug_string == "all" || debug_string == "verbose") {
|
||||||
|
debug_flags = XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT | XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT |
|
||||||
|
XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT | XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT;
|
||||||
|
}
|
||||||
|
AddLogRecorder(MakeStdOutLoaderLogRecorder(nullptr, debug_flags));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoaderLogger::AddLogRecorder(std::unique_ptr<LoaderLogRecorder>&& recorder) { _recorders.push_back(std::move(recorder)); }
|
||||||
|
|
||||||
|
void LoaderLogger::RemoveLogRecorder(uint64_t unique_id) {
|
||||||
|
vector_remove_if_and_erase(
|
||||||
|
_recorders, [=](std::unique_ptr<LoaderLogRecorder> const& recorder) { return recorder->UniqueId() == unique_id; });
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoaderLogger::LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
|
||||||
|
const std::string& message_id, const std::string& command_name, const std::string& message,
|
||||||
|
const std::vector<XrLoaderLogObjectInfo>& objects) {
|
||||||
|
XrLoaderLogMessengerCallbackData callback_data = {};
|
||||||
|
callback_data.message_id = message_id.c_str();
|
||||||
|
callback_data.command_name = command_name.c_str();
|
||||||
|
callback_data.message = message.c_str();
|
||||||
|
|
||||||
|
std::vector<XrDebugUtilsLabelEXT> labels;
|
||||||
|
|
||||||
|
// Copy objects into a vector we can modify and will keep around past the callback.
|
||||||
|
std::vector<XrLoaderLogObjectInfo> object_vector = objects;
|
||||||
|
for (auto& obj : object_vector) {
|
||||||
|
// Check for any names that have been associated with the objects and set them up here
|
||||||
|
_object_names.LookUpObjectName(obj);
|
||||||
|
// If this is a session, see if there are any labels associated with it for us to add
|
||||||
|
// to the callback content.
|
||||||
|
if (XR_OBJECT_TYPE_SESSION == obj.type) {
|
||||||
|
LookUpSessionLabels(obj.GetTypedHandle<XrSession>(), labels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback_data.objects = object_vector.empty() ? nullptr : object_vector.data();
|
||||||
|
callback_data.object_count = static_cast<uint8_t>(object_vector.size());
|
||||||
|
|
||||||
|
callback_data.session_labels = labels.empty() ? nullptr : labels.data();
|
||||||
|
callback_data.session_labels_count = static_cast<uint8_t>(labels.size());
|
||||||
|
|
||||||
|
bool exit_app = false;
|
||||||
|
for (std::unique_ptr<LoaderLogRecorder>& recorder : _recorders) {
|
||||||
|
if ((recorder->MessageSeverities() & message_severity) == message_severity &&
|
||||||
|
(recorder->MessageTypes() & message_type) == message_type) {
|
||||||
|
exit_app |= recorder->LogMessage(message_severity, message_type, &callback_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return exit_app;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoaderLogger::LookUpSessionLabels(XrSession session, std::vector<XrDebugUtilsLabelEXT>& labels) const {
|
||||||
|
auto session_label_iterator = _session_labels.find(session);
|
||||||
|
if (session_label_iterator != _session_labels.end()) {
|
||||||
|
auto& internalSessionLabels = *session_label_iterator->second;
|
||||||
|
// Copy the debug utils labels in reverse order in the the labels vector.
|
||||||
|
std::transform(internalSessionLabels.rbegin(), internalSessionLabels.rend(), std::back_inserter(labels),
|
||||||
|
[](InternalSessionLabelPtr const& label) { return label->debug_utils_label; });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extension-specific logging functions
|
||||||
|
bool LoaderLogger::LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT message_severity,
|
||||||
|
XrDebugUtilsMessageTypeFlagsEXT message_type,
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT* callback_data) {
|
||||||
|
bool exit_app = false;
|
||||||
|
XrLoaderLogMessageSeverityFlags log_message_severity = DebugUtilsSeveritiesToLoaderLogMessageSeverities(message_severity);
|
||||||
|
XrLoaderLogMessageTypeFlags log_message_type = DebugUtilsMessageTypesToLoaderLogMessageTypes(message_type);
|
||||||
|
|
||||||
|
bool obj_name_found = false;
|
||||||
|
std::vector<XrDebugUtilsLabelEXT> labels;
|
||||||
|
if (!_object_names.Empty() && callback_data->objectCount > 0) {
|
||||||
|
for (uint32_t obj = 0; obj < callback_data->objectCount; ++obj) {
|
||||||
|
auto& current_obj = callback_data->objects[obj];
|
||||||
|
auto stored_info = _object_names.LookUpStoredObjectInfo(current_obj.objectHandle, current_obj.objectType);
|
||||||
|
if (stored_info != nullptr) {
|
||||||
|
obj_name_found = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is a session, see if there are any labels associated with it for us to add
|
||||||
|
// to the callback content.
|
||||||
|
if (XR_OBJECT_TYPE_SESSION == current_obj.objectType) {
|
||||||
|
XrSession session = TreatIntegerAsHandle<XrSession>(current_obj.objectHandle);
|
||||||
|
LookUpSessionLabels(session, labels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Use unmodified ones by default.
|
||||||
|
XrDebugUtilsMessengerCallbackDataEXT const* callback_data_to_use = callback_data;
|
||||||
|
|
||||||
|
XrDebugUtilsMessengerCallbackDataEXT new_callback_data = *callback_data;
|
||||||
|
std::vector<XrDebugUtilsObjectNameInfoEXT> new_objects;
|
||||||
|
|
||||||
|
// If a name or a label has been found, we should update it in a new version of the callback
|
||||||
|
if (obj_name_found || !labels.empty()) {
|
||||||
|
// Copy objects
|
||||||
|
new_objects =
|
||||||
|
std::vector<XrDebugUtilsObjectNameInfoEXT>(callback_data->objects, callback_data->objects + callback_data->objectCount);
|
||||||
|
for (auto& obj : new_objects) {
|
||||||
|
// Check for any names that have been associated with the objects and set them up here
|
||||||
|
_object_names.LookUpObjectName(obj);
|
||||||
|
}
|
||||||
|
new_callback_data.objects = new_objects.data();
|
||||||
|
new_callback_data.sessionLabelCount = static_cast<uint32_t>(labels.size());
|
||||||
|
new_callback_data.sessionLabels = labels.empty() ? nullptr : labels.data();
|
||||||
|
callback_data_to_use = &new_callback_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through the recorders
|
||||||
|
for (std::unique_ptr<LoaderLogRecorder>& recorder : _recorders) {
|
||||||
|
// Only send the message if it's a debug utils recorder and of the type the recorder cares about.
|
||||||
|
if (recorder->Type() != XR_LOADER_LOG_DEBUG_UTILS ||
|
||||||
|
(recorder->MessageSeverities() & log_message_severity) != log_message_severity ||
|
||||||
|
(recorder->MessageTypes() & log_message_type) != log_message_type) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_app |= recorder->LogDebugUtilsMessage(message_severity, message_type, callback_data_to_use);
|
||||||
|
}
|
||||||
|
return exit_app;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoaderLogger::AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name) {
|
||||||
|
_object_names.AddObjectName(object_handle, object_type, object_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We always want to remove the old individual label before we do anything else.
|
||||||
|
// So, do that in it's own method
|
||||||
|
void LoaderLogger::RemoveIndividualLabel(InternalSessionLabelList& label_vec) {
|
||||||
|
if (!label_vec.empty() && label_vec.back()->is_individual_label) {
|
||||||
|
label_vec.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InternalSessionLabelList* LoaderLogger::GetSessionLabelList(XrSession session) {
|
||||||
|
auto session_label_iterator = _session_labels.find(session);
|
||||||
|
if (session_label_iterator == _session_labels.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return session_label_iterator->second.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
InternalSessionLabelList& LoaderLogger::GetOrCreateSessionLabelList(XrSession session) {
|
||||||
|
InternalSessionLabelList* vec_ptr = GetSessionLabelList(session);
|
||||||
|
if (vec_ptr == nullptr) {
|
||||||
|
std::unique_ptr<InternalSessionLabelList> vec(new InternalSessionLabelList);
|
||||||
|
vec_ptr = vec.get();
|
||||||
|
_session_labels[session] = std::move(vec);
|
||||||
|
}
|
||||||
|
return *vec_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoaderLogger::BeginLabelRegion(XrSession session, const XrDebugUtilsLabelEXT* label_info) {
|
||||||
|
auto& vec = GetOrCreateSessionLabelList(session);
|
||||||
|
|
||||||
|
// Individual labels do not stay around in the transition into a new label region
|
||||||
|
RemoveIndividualLabel(vec);
|
||||||
|
|
||||||
|
// Start the new label region
|
||||||
|
InternalSessionLabelPtr new_session_label(new InternalSessionLabel);
|
||||||
|
new_session_label->label_name = label_info->labelName;
|
||||||
|
new_session_label->debug_utils_label = *label_info;
|
||||||
|
new_session_label->debug_utils_label.labelName = new_session_label->label_name.c_str();
|
||||||
|
new_session_label->is_individual_label = false;
|
||||||
|
vec.emplace_back(std::move(new_session_label));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoaderLogger::EndLabelRegion(XrSession session) {
|
||||||
|
InternalSessionLabelList* vec_ptr = GetSessionLabelList(session);
|
||||||
|
if (vec_ptr == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Individual labels do not stay around in the transition out of label region
|
||||||
|
RemoveIndividualLabel(*vec_ptr);
|
||||||
|
|
||||||
|
// Remove the last label region
|
||||||
|
if (!vec_ptr->empty()) {
|
||||||
|
vec_ptr->pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoaderLogger::InsertLabel(XrSession session, const XrDebugUtilsLabelEXT* label_info) {
|
||||||
|
//! @todo only difference from BeginLabelRegion is value of is_individual_label
|
||||||
|
auto& vec = GetOrCreateSessionLabelList(session);
|
||||||
|
|
||||||
|
// Remove any individual layer that might already be there
|
||||||
|
RemoveIndividualLabel(vec);
|
||||||
|
|
||||||
|
// Insert a new individual label
|
||||||
|
InternalSessionLabelPtr new_session_label(new InternalSessionLabel);
|
||||||
|
new_session_label->label_name = label_info->labelName;
|
||||||
|
new_session_label->debug_utils_label = *label_info;
|
||||||
|
new_session_label->debug_utils_label.labelName = new_session_label->label_name.c_str();
|
||||||
|
new_session_label->is_individual_label = true;
|
||||||
|
vec.emplace_back(std::move(new_session_label));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called during xrDestroySession. We need to delete all session related labels.
|
||||||
|
void LoaderLogger::DeleteSessionLabels(XrSession session) {
|
||||||
|
InternalSessionLabelList* vec_ptr = GetSessionLabelList(session);
|
||||||
|
if (vec_ptr == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_session_labels.erase(session);
|
||||||
|
}
|
||||||
289
extern/openxr/src/loader/loader_logger.hpp
vendored
Normal file
289
extern/openxr/src/loader/loader_logger.hpp
vendored
Normal file
@@ -0,0 +1,289 @@
|
|||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include "hex_and_handles.h"
|
||||||
|
|
||||||
|
// Use internal versions of flags similar to XR_EXT_debug_utils so that
|
||||||
|
// we're not tightly coupled to that extension. This way, if the extension
|
||||||
|
// changes or gets replaced, we can be flexible in the loader.
|
||||||
|
#define XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT 0x00000001
|
||||||
|
#define XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT 0x00000010
|
||||||
|
#define XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT 0x00000100
|
||||||
|
#define XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT 0x00001000
|
||||||
|
#define XR_LOADER_LOG_MESSAGE_SEVERITY_DEFAULT_BITS 0x00000000
|
||||||
|
typedef XrFlags64 XrLoaderLogMessageSeverityFlagBits;
|
||||||
|
typedef XrFlags64 XrLoaderLogMessageSeverityFlags;
|
||||||
|
|
||||||
|
#define XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT 0x00000001
|
||||||
|
#define XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT 0x00000002
|
||||||
|
#define XR_LOADER_LOG_MESSAGE_TYPE_PERFORMANCE_BIT 0x00000004
|
||||||
|
#define XR_LOADER_LOG_MESSAGE_TYPE_DEFAULT_BITS 0xffffffff
|
||||||
|
typedef XrFlags64 XrLoaderLogMessageTypeFlagBits;
|
||||||
|
typedef XrFlags64 XrLoaderLogMessageTypeFlags;
|
||||||
|
|
||||||
|
struct XrLoaderLogObjectInfo {
|
||||||
|
//! Type-erased handle value
|
||||||
|
uint64_t handle;
|
||||||
|
|
||||||
|
//! Kind of object this handle refers to
|
||||||
|
XrObjectType type;
|
||||||
|
|
||||||
|
//! To be assigned by the application - not part of this object's identity
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
/// Un-erase the type of the handle and get it properly typed again.
|
||||||
|
///
|
||||||
|
/// Note: Does not check the type before doing it!
|
||||||
|
template <typename HandleType>
|
||||||
|
HandleType& GetTypedHandle() {
|
||||||
|
return TreatIntegerAsHandle<HandleType&>(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @overload
|
||||||
|
template <typename HandleType>
|
||||||
|
HandleType const& GetTypedHandle() const {
|
||||||
|
return TreatIntegerAsHandle<HandleType&>(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
XrLoaderLogObjectInfo() = default;
|
||||||
|
|
||||||
|
//! Create from a typed handle and object type
|
||||||
|
template <typename T>
|
||||||
|
XrLoaderLogObjectInfo(T h, XrObjectType t) : handle(MakeHandleGeneric(h)), type(t) {}
|
||||||
|
|
||||||
|
//! Create from an untyped handle value (integer) and object type
|
||||||
|
XrLoaderLogObjectInfo(uint64_t h, XrObjectType t) : handle(h), type(t) {}
|
||||||
|
|
||||||
|
std::string ToString() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
//! True if the two object infos have the same handle value and handle type
|
||||||
|
static inline bool Equivalent(XrLoaderLogObjectInfo const& a, XrLoaderLogObjectInfo const& b) {
|
||||||
|
return a.handle == b.handle && a.type == b.type;
|
||||||
|
}
|
||||||
|
//! @overload
|
||||||
|
static inline bool Equivalent(XrDebugUtilsObjectNameInfoEXT const& a, XrLoaderLogObjectInfo const& b) {
|
||||||
|
return a.objectHandle == b.handle && a.objectType == b.type;
|
||||||
|
}
|
||||||
|
//! @overload
|
||||||
|
static inline bool Equivalent(XrLoaderLogObjectInfo const& a, XrDebugUtilsObjectNameInfoEXT const& b) { return Equivalent(b, a); }
|
||||||
|
|
||||||
|
struct XrLoaderLogMessengerCallbackData {
|
||||||
|
const char* message_id;
|
||||||
|
const char* command_name;
|
||||||
|
const char* message;
|
||||||
|
uint8_t object_count;
|
||||||
|
XrLoaderLogObjectInfo* objects;
|
||||||
|
uint8_t session_labels_count;
|
||||||
|
XrDebugUtilsLabelEXT* session_labels;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum XrLoaderLogType {
|
||||||
|
XR_LOADER_LOG_UNKNOWN = 0,
|
||||||
|
XR_LOADER_LOG_STDERR,
|
||||||
|
XR_LOADER_LOG_STDOUT,
|
||||||
|
XR_LOADER_LOG_DEBUG_UTILS,
|
||||||
|
};
|
||||||
|
|
||||||
|
class LoaderLogRecorder {
|
||||||
|
public:
|
||||||
|
LoaderLogRecorder(XrLoaderLogType type, void* user_data, XrLoaderLogMessageSeverityFlags message_severities,
|
||||||
|
XrLoaderLogMessageTypeFlags message_types) {
|
||||||
|
_active = false;
|
||||||
|
_user_data = user_data;
|
||||||
|
_type = type;
|
||||||
|
_unique_id = 0;
|
||||||
|
_message_severities = message_severities;
|
||||||
|
_message_types = message_types;
|
||||||
|
}
|
||||||
|
virtual ~LoaderLogRecorder() = default;
|
||||||
|
|
||||||
|
XrLoaderLogType Type() { return _type; }
|
||||||
|
|
||||||
|
uint64_t UniqueId() { return _unique_id; }
|
||||||
|
|
||||||
|
XrLoaderLogMessageSeverityFlags MessageSeverities() { return _message_severities; }
|
||||||
|
|
||||||
|
XrLoaderLogMessageTypeFlags MessageTypes() { return _message_types; }
|
||||||
|
|
||||||
|
virtual void Start() { _active = true; }
|
||||||
|
|
||||||
|
bool IsPaused() { return _active; }
|
||||||
|
|
||||||
|
virtual void Pause() { _active = false; }
|
||||||
|
|
||||||
|
virtual void Resume() { _active = true; }
|
||||||
|
|
||||||
|
virtual void Stop() { _active = false; }
|
||||||
|
|
||||||
|
virtual bool LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
|
||||||
|
const XrLoaderLogMessengerCallbackData* callback_data) = 0;
|
||||||
|
|
||||||
|
// Extension-specific logging functions - defaults to do nothing.
|
||||||
|
virtual bool LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT message_severity,
|
||||||
|
XrDebugUtilsMessageTypeFlagsEXT message_type,
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT* callback_data);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool _active;
|
||||||
|
XrLoaderLogType _type;
|
||||||
|
uint64_t _unique_id;
|
||||||
|
void* _user_data;
|
||||||
|
XrLoaderLogMessageSeverityFlags _message_severities;
|
||||||
|
XrLoaderLogMessageTypeFlags _message_types;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ObjectInfoCollection {
|
||||||
|
public:
|
||||||
|
//! Called from LoaderXrTermSetDebugUtilsObjectNameEXT - an empty name means remove
|
||||||
|
void AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name);
|
||||||
|
|
||||||
|
//! Find the stored object info, if any, matching handle and type.
|
||||||
|
//! Return nullptr if not found.
|
||||||
|
XrLoaderLogObjectInfo const* LookUpStoredObjectInfo(XrLoaderLogObjectInfo const& info) const;
|
||||||
|
//! Find the stored object info, if any, matching handle and type.
|
||||||
|
//! Return nullptr if not found.
|
||||||
|
XrLoaderLogObjectInfo* LookUpStoredObjectInfo(XrLoaderLogObjectInfo const& info);
|
||||||
|
|
||||||
|
//! Find the stored object info, if any.
|
||||||
|
//! Return nullptr if not found.
|
||||||
|
XrLoaderLogObjectInfo const* LookUpStoredObjectInfo(uint64_t handle, XrObjectType type) const {
|
||||||
|
return LookUpStoredObjectInfo({handle, type});
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Find the object name, if any, and update debug utils info accordingly.
|
||||||
|
//! Return true if found and updated.
|
||||||
|
bool LookUpObjectName(XrDebugUtilsObjectNameInfoEXT& info) const;
|
||||||
|
|
||||||
|
//! Find the object name, if any, and update logging info accordingly.
|
||||||
|
//! Return true if found and updated.
|
||||||
|
bool LookUpObjectName(XrLoaderLogObjectInfo& info) const;
|
||||||
|
|
||||||
|
//! Is the collection empty?
|
||||||
|
bool Empty() const { return _object_info.empty(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Object names that have been set for given objects
|
||||||
|
std::vector<XrLoaderLogObjectInfo> _object_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct InternalSessionLabel {
|
||||||
|
XrDebugUtilsLabelEXT debug_utils_label;
|
||||||
|
std::string label_name;
|
||||||
|
bool is_individual_label;
|
||||||
|
};
|
||||||
|
|
||||||
|
using InternalSessionLabelPtr = std::unique_ptr<InternalSessionLabel>;
|
||||||
|
using InternalSessionLabelList = std::vector<InternalSessionLabelPtr>;
|
||||||
|
|
||||||
|
class LoaderLogger {
|
||||||
|
public:
|
||||||
|
static LoaderLogger& GetInstance() {
|
||||||
|
std::call_once(LoaderLogger::_once_flag, []() { _instance.reset(new LoaderLogger); });
|
||||||
|
return *(_instance.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddLogRecorder(std::unique_ptr<LoaderLogRecorder>&& recorder);
|
||||||
|
void RemoveLogRecorder(uint64_t unique_id);
|
||||||
|
|
||||||
|
//! Called from LoaderXrTermSetDebugUtilsObjectNameEXT - an empty name means remove
|
||||||
|
void AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name);
|
||||||
|
void BeginLabelRegion(XrSession session, const XrDebugUtilsLabelEXT* label_info);
|
||||||
|
void EndLabelRegion(XrSession session);
|
||||||
|
void InsertLabel(XrSession session, const XrDebugUtilsLabelEXT* label_info);
|
||||||
|
void DeleteSessionLabels(XrSession session);
|
||||||
|
|
||||||
|
bool LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
|
||||||
|
const std::string& message_id, const std::string& command_name, const std::string& message,
|
||||||
|
const std::vector<XrLoaderLogObjectInfo>& objects = {});
|
||||||
|
static bool LogErrorMessage(const std::string& command_name, const std::string& message,
|
||||||
|
const std::vector<XrLoaderLogObjectInfo>& objects = {}) {
|
||||||
|
return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT, XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT,
|
||||||
|
"OpenXR-Loader", command_name, message, objects);
|
||||||
|
}
|
||||||
|
static bool LogWarningMessage(const std::string& command_name, const std::string& message,
|
||||||
|
const std::vector<XrLoaderLogObjectInfo>& objects = {}) {
|
||||||
|
return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT, XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT,
|
||||||
|
"OpenXR-Loader", command_name, message, objects);
|
||||||
|
}
|
||||||
|
static bool LogInfoMessage(const std::string& command_name, const std::string& message,
|
||||||
|
const std::vector<XrLoaderLogObjectInfo>& objects = {}) {
|
||||||
|
return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT, XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT,
|
||||||
|
"OpenXR-Loader", command_name, message, objects);
|
||||||
|
}
|
||||||
|
static bool LogVerboseMessage(const std::string& command_name, const std::string& message,
|
||||||
|
const std::vector<XrLoaderLogObjectInfo>& objects = {}) {
|
||||||
|
return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT, XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT,
|
||||||
|
"OpenXR-Loader", command_name, message, objects);
|
||||||
|
}
|
||||||
|
static bool LogValidationErrorMessage(const std::string& vuid, const std::string& command_name, const std::string& message,
|
||||||
|
const std::vector<XrLoaderLogObjectInfo>& objects = {}) {
|
||||||
|
return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT, XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT,
|
||||||
|
vuid, command_name, message, objects);
|
||||||
|
}
|
||||||
|
static bool LogValidationWarningMessage(const std::string& vuid, const std::string& command_name, const std::string& message,
|
||||||
|
const std::vector<XrLoaderLogObjectInfo>& objects = {}) {
|
||||||
|
return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT, XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT,
|
||||||
|
vuid, command_name, message, objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extension-specific logging functions
|
||||||
|
bool LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT message_severity, XrDebugUtilsMessageTypeFlagsEXT message_type,
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT* callback_data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
LoaderLogger();
|
||||||
|
LoaderLogger(const LoaderLogger&) = delete;
|
||||||
|
LoaderLogger& operator=(const LoaderLogger&) = delete;
|
||||||
|
|
||||||
|
/// Retrieve labels for the given session, if any, and push them in reverse order on the vector.
|
||||||
|
void LookUpSessionLabels(XrSession session, std::vector<XrDebugUtilsLabelEXT>& labels) const;
|
||||||
|
|
||||||
|
void RemoveIndividualLabel(InternalSessionLabelList& label_vec);
|
||||||
|
InternalSessionLabelList* GetSessionLabelList(XrSession session);
|
||||||
|
InternalSessionLabelList& GetOrCreateSessionLabelList(XrSession session);
|
||||||
|
|
||||||
|
static std::unique_ptr<LoaderLogger> _instance;
|
||||||
|
static std::once_flag _once_flag;
|
||||||
|
|
||||||
|
// List of available recorder objects
|
||||||
|
std::vector<std::unique_ptr<LoaderLogRecorder>> _recorders;
|
||||||
|
|
||||||
|
ObjectInfoCollection _object_names;
|
||||||
|
// Session labels
|
||||||
|
std::unordered_map<XrSession, std::unique_ptr<InternalSessionLabelList>> _session_labels;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Utility functions for converting to/from XR_EXT_debug_utils values
|
||||||
|
XrLoaderLogMessageSeverityFlags DebugUtilsSeveritiesToLoaderLogMessageSeverities(
|
||||||
|
XrDebugUtilsMessageSeverityFlagsEXT utils_severities);
|
||||||
|
XrDebugUtilsMessageSeverityFlagsEXT LoaderLogMessageSeveritiesToDebugUtilsMessageSeverities(
|
||||||
|
XrLoaderLogMessageSeverityFlags log_severities);
|
||||||
|
XrLoaderLogMessageTypeFlagBits DebugUtilsMessageTypesToLoaderLogMessageTypes(XrDebugUtilsMessageTypeFlagsEXT utils_types);
|
||||||
|
XrDebugUtilsMessageTypeFlagsEXT LoaderLogMessageTypesToDebugUtilsMessageTypes(XrLoaderLogMessageTypeFlagBits log_types);
|
||||||
188
extern/openxr/src/loader/loader_logger_recorders.cpp
vendored
Normal file
188
extern/openxr/src/loader/loader_logger_recorders.cpp
vendored
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "loader_logger_recorders.hpp"
|
||||||
|
|
||||||
|
#include "hex_and_handles.h"
|
||||||
|
#include "loader_logger.hpp"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
// Anonymous namespace to keep these types private
|
||||||
|
namespace {
|
||||||
|
// With std::cerr: Standard Error logger, always on for now
|
||||||
|
// With std::cout: Standard Output logger used with XR_LOADER_DEBUG
|
||||||
|
class OstreamLoaderLogRecorder : public LoaderLogRecorder {
|
||||||
|
public:
|
||||||
|
OstreamLoaderLogRecorder(std::ostream& os, void* user_data, XrLoaderLogMessageSeverityFlags flags);
|
||||||
|
|
||||||
|
bool LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
|
||||||
|
const XrLoaderLogMessengerCallbackData* callback_data) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::ostream& os_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Debug Utils logger used with XR_EXT_debug_utils
|
||||||
|
class DebugUtilsLogRecorder : public LoaderLogRecorder {
|
||||||
|
public:
|
||||||
|
DebugUtilsLogRecorder(const XrDebugUtilsMessengerCreateInfoEXT* create_info, XrDebugUtilsMessengerEXT debug_messenger);
|
||||||
|
|
||||||
|
bool LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
|
||||||
|
const XrLoaderLogMessengerCallbackData* callback_data) override;
|
||||||
|
|
||||||
|
// Extension-specific logging functions
|
||||||
|
bool LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT message_severity, XrDebugUtilsMessageTypeFlagsEXT message_type,
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT* callback_data) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PFN_xrDebugUtilsMessengerCallbackEXT _user_callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Unified stdout/stderr logger
|
||||||
|
OstreamLoaderLogRecorder::OstreamLoaderLogRecorder(std::ostream& os, void* user_data, XrLoaderLogMessageSeverityFlags flags)
|
||||||
|
: LoaderLogRecorder(XR_LOADER_LOG_STDOUT, user_data, flags, 0xFFFFFFFFUL), os_(os) {
|
||||||
|
// Automatically start
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OstreamLoaderLogRecorder::LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity,
|
||||||
|
XrLoaderLogMessageTypeFlags message_type,
|
||||||
|
const XrLoaderLogMessengerCallbackData* callback_data) {
|
||||||
|
if (_active && 0 != (_message_severities & message_severity) && 0 != (_message_types & message_type)) {
|
||||||
|
if (XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT > message_severity) {
|
||||||
|
os_ << "Verbose [";
|
||||||
|
} else if (XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT > message_severity) {
|
||||||
|
os_ << "Info [";
|
||||||
|
} else if (XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT > message_severity) {
|
||||||
|
os_ << "Warning [";
|
||||||
|
} else {
|
||||||
|
os_ << "Error [";
|
||||||
|
}
|
||||||
|
switch (message_type) {
|
||||||
|
case XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT:
|
||||||
|
os_ << "GENERAL";
|
||||||
|
break;
|
||||||
|
case XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT:
|
||||||
|
os_ << "SPEC";
|
||||||
|
break;
|
||||||
|
case XR_LOADER_LOG_MESSAGE_TYPE_PERFORMANCE_BIT:
|
||||||
|
os_ << "PERF";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
os_ << "UNKNOWN";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
os_ << " | " << callback_data->command_name << " | " << callback_data->message_id << "] : " << callback_data->message
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
for (uint32_t obj = 0; obj < callback_data->object_count; ++obj) {
|
||||||
|
os_ << " Object[" << obj << "] = " << callback_data->objects[obj].ToString();
|
||||||
|
os_ << std::endl;
|
||||||
|
}
|
||||||
|
for (uint32_t label = 0; label < callback_data->session_labels_count; ++label) {
|
||||||
|
os_ << " SessionLabel[" << std::to_string(label) << "] = " << callback_data->session_labels[label].labelName;
|
||||||
|
os_ << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return of "true" means that we should exit the application after the logged message. We
|
||||||
|
// don't want to do that for our internal logging. Only let a user return true.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A logger associated with the XR_EXT_debug_utils extension
|
||||||
|
|
||||||
|
DebugUtilsLogRecorder::DebugUtilsLogRecorder(const XrDebugUtilsMessengerCreateInfoEXT* create_info,
|
||||||
|
XrDebugUtilsMessengerEXT debug_messenger)
|
||||||
|
: LoaderLogRecorder(XR_LOADER_LOG_DEBUG_UTILS, static_cast<void*>(create_info->userData),
|
||||||
|
DebugUtilsSeveritiesToLoaderLogMessageSeverities(create_info->messageSeverities),
|
||||||
|
DebugUtilsMessageTypesToLoaderLogMessageTypes(create_info->messageTypes)),
|
||||||
|
_user_callback(create_info->userCallback) {
|
||||||
|
// Use the debug messenger value to uniquely identify this logger with that messenger
|
||||||
|
_unique_id = MakeHandleGeneric(debug_messenger);
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extension-specific logging functions
|
||||||
|
bool DebugUtilsLogRecorder::LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity,
|
||||||
|
XrLoaderLogMessageTypeFlags message_type,
|
||||||
|
const XrLoaderLogMessengerCallbackData* callback_data) {
|
||||||
|
bool should_exit = false;
|
||||||
|
if (_active && 0 != (_message_severities & message_severity) && 0 != (_message_types & message_type)) {
|
||||||
|
XrDebugUtilsMessageSeverityFlagsEXT utils_severity = DebugUtilsSeveritiesToLoaderLogMessageSeverities(message_severity);
|
||||||
|
XrDebugUtilsMessageTypeFlagsEXT utils_type = LoaderLogMessageTypesToDebugUtilsMessageTypes(message_type);
|
||||||
|
|
||||||
|
// Convert the loader log message into the debug utils log message information
|
||||||
|
XrDebugUtilsMessengerCallbackDataEXT utils_callback_data = {};
|
||||||
|
utils_callback_data.type = XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
|
||||||
|
utils_callback_data.messageId = callback_data->message_id;
|
||||||
|
utils_callback_data.functionName = callback_data->command_name;
|
||||||
|
utils_callback_data.message = callback_data->message;
|
||||||
|
std::vector<XrDebugUtilsObjectNameInfoEXT> utils_objects;
|
||||||
|
utils_objects.resize(callback_data->object_count);
|
||||||
|
for (uint8_t object = 0; object < callback_data->object_count; ++object) {
|
||||||
|
utils_objects[object].type = XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
|
||||||
|
utils_objects[object].next = nullptr;
|
||||||
|
utils_objects[object].objectHandle = callback_data->objects[object].handle;
|
||||||
|
utils_objects[object].objectType = callback_data->objects[object].type;
|
||||||
|
utils_objects[object].objectName = callback_data->objects[object].name.c_str();
|
||||||
|
}
|
||||||
|
utils_callback_data.objectCount = callback_data->object_count;
|
||||||
|
utils_callback_data.objects = utils_objects.data();
|
||||||
|
utils_callback_data.sessionLabelCount = callback_data->session_labels_count;
|
||||||
|
utils_callback_data.sessionLabels = callback_data->session_labels;
|
||||||
|
|
||||||
|
// Call the user callback with the appropriate info
|
||||||
|
// Return of "true" means that we should exit the application after the logged message.
|
||||||
|
should_exit = (_user_callback(utils_severity, utils_type, &utils_callback_data, _user_data) == XR_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return should_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DebugUtilsLogRecorder::LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT message_severity,
|
||||||
|
XrDebugUtilsMessageTypeFlagsEXT message_type,
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT* callback_data) {
|
||||||
|
// Call the user callback with the appropriate info
|
||||||
|
// Return of "true" means that we should exit the application after the logged message.
|
||||||
|
return (_user_callback(message_severity, message_type, callback_data, _user_data) == XR_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
std::unique_ptr<LoaderLogRecorder> MakeStdOutLoaderLogRecorder(void* user_data, XrLoaderLogMessageSeverityFlags flags) {
|
||||||
|
std::unique_ptr<LoaderLogRecorder> recorder(new OstreamLoaderLogRecorder(std::cout, user_data, flags));
|
||||||
|
return recorder;
|
||||||
|
}
|
||||||
|
std::unique_ptr<LoaderLogRecorder> MakeStdErrLoaderLogRecorder(void* user_data) {
|
||||||
|
std::unique_ptr<LoaderLogRecorder> recorder(
|
||||||
|
new OstreamLoaderLogRecorder(std::cerr, user_data, XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT));
|
||||||
|
return recorder;
|
||||||
|
}
|
||||||
|
std::unique_ptr<LoaderLogRecorder> MakeDebugUtilsLoaderLogRecorder(const XrDebugUtilsMessengerCreateInfoEXT* create_info,
|
||||||
|
XrDebugUtilsMessengerEXT debug_messenger) {
|
||||||
|
std::unique_ptr<LoaderLogRecorder> recorder(new DebugUtilsLogRecorder(create_info, debug_messenger));
|
||||||
|
return recorder;
|
||||||
|
}
|
||||||
40
extern/openxr/src/loader/loader_logger_recorders.hpp
vendored
Normal file
40
extern/openxr/src/loader/loader_logger_recorders.hpp
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "loader_logger.hpp"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
//! Standard Error logger, always on for now
|
||||||
|
std::unique_ptr<LoaderLogRecorder> MakeStdErrLoaderLogRecorder(void* user_data);
|
||||||
|
|
||||||
|
//! Standard Output logger used with XR_LOADER_DEBUG
|
||||||
|
std::unique_ptr<LoaderLogRecorder> MakeStdOutLoaderLogRecorder(void* user_data, XrLoaderLogMessageSeverityFlags flags);
|
||||||
|
|
||||||
|
// Debug Utils logger used with XR_EXT_debug_utils
|
||||||
|
std::unique_ptr<LoaderLogRecorder> MakeDebugUtilsLoaderLogRecorder(const XrDebugUtilsMessengerCreateInfoEXT* create_info,
|
||||||
|
XrDebugUtilsMessengerEXT debug_messenger);
|
||||||
|
|
||||||
|
// TODO: Add other Derived classes:
|
||||||
|
// - FileLoaderLogRecorder - During/after xrCreateInstance
|
||||||
|
// - PipeLoaderLogRecorder? - During/after xrCreateInstance
|
||||||
215
extern/openxr/src/loader/loader_platform.hpp
vendored
Normal file
215
extern/openxr/src/loader/loader_platform.hpp
vendored
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
// Author: Dave Houlton <daveh@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "xr_dependencies.h"
|
||||||
|
#include "platform_utils.hpp"
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && __GNUC__ >= 4
|
||||||
|
#define LOADER_EXPORT __attribute__((visibility("default")))
|
||||||
|
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
|
||||||
|
#define LOADER_EXPORT __attribute__((visibility("default")))
|
||||||
|
#else
|
||||||
|
#define LOADER_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Environment variables
|
||||||
|
#if defined(XR_OS_LINUX) || defined(XR_OS_APPLE)
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
#ifndef PATH_MAX
|
||||||
|
#define PATH_MAX 1024
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PATH_SEPARATOR ':'
|
||||||
|
#define DIRECTORY_SYMBOL '/'
|
||||||
|
|
||||||
|
// Dynamic Loading of libraries:
|
||||||
|
typedef void *LoaderPlatformLibraryHandle;
|
||||||
|
static inline LoaderPlatformLibraryHandle LoaderPlatformLibraryOpen(const std::string &path) {
|
||||||
|
// When loading the library, we use RTLD_LAZY so that not all symbols have to be
|
||||||
|
// resolved at this time (which improves performance). Note that if not all symbols
|
||||||
|
// can be resolved, this could cause crashes later.
|
||||||
|
// For experimenting/debugging: Define the LD_BIND_NOW environment variable to force all
|
||||||
|
// symbols to be resolved here.
|
||||||
|
return dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const char *LoaderPlatformLibraryOpenError(const std::string &path) {
|
||||||
|
(void)path;
|
||||||
|
return dlerror();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void LoaderPlatformLibraryClose(LoaderPlatformLibraryHandle library) { dlclose(library); }
|
||||||
|
|
||||||
|
static inline void *LoaderPlatformLibraryGetProcAddr(LoaderPlatformLibraryHandle library, const std::string &name) {
|
||||||
|
assert(library);
|
||||||
|
assert(!name.empty());
|
||||||
|
return dlsym(library, name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const char *LoaderPlatformLibraryGetProcAddrError(const std::string &name) {
|
||||||
|
(void)name;
|
||||||
|
return dlerror();
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(XR_OS_WINDOWS)
|
||||||
|
|
||||||
|
#define PATH_SEPARATOR ';'
|
||||||
|
#define DIRECTORY_SYMBOL '\\'
|
||||||
|
|
||||||
|
// Workaround for MS VS 2010/2013 missing snprintf and vsnprintf
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
static inline int32_t xr_vsnprintf(char *result_buffer, size_t buffer_size, const char *print_format, va_list varying_list) {
|
||||||
|
int32_t copy_count = -1;
|
||||||
|
if (buffer_size != 0) {
|
||||||
|
copy_count = _vsnprintf_s(result_buffer, buffer_size, _TRUNCATE, print_format, varying_list);
|
||||||
|
}
|
||||||
|
if (copy_count == -1) {
|
||||||
|
copy_count = _vscprintf(print_format, varying_list);
|
||||||
|
}
|
||||||
|
return copy_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int32_t xr_snprintf(char *result_buffer, size_t buffer_size, const char *print_format, ...) {
|
||||||
|
va_list varying_list;
|
||||||
|
va_start(varying_list, print_format);
|
||||||
|
int32_t copy_count = xr_vsnprintf(result_buffer, buffer_size, print_format, varying_list);
|
||||||
|
va_end(varying_list);
|
||||||
|
return copy_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define snprintf xr_snprintf
|
||||||
|
#define vsnprintf xr_vsnprintf
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static std::string DescribeError(uint32_t code, bool prefixErrorCode = true) {
|
||||||
|
std::string str;
|
||||||
|
|
||||||
|
if (prefixErrorCode) {
|
||||||
|
char prefixBuffer[64];
|
||||||
|
snprintf(prefixBuffer, sizeof(prefixBuffer), "0x%llx (%lld): ", (uint64_t)code, (int64_t)code);
|
||||||
|
str = prefixBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Could use FORMAT_MESSAGE_FROM_HMODULE to specify an error source.
|
||||||
|
WCHAR errorBufferW[1024]{};
|
||||||
|
const DWORD errorBufferWCapacity = sizeof(errorBufferW) / sizeof(errorBufferW[0]);
|
||||||
|
const DWORD length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, (DWORD)code,
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errorBufferW, errorBufferWCapacity, nullptr);
|
||||||
|
|
||||||
|
if (length) { // If errorBufferW contains what we are looking for...
|
||||||
|
str += wide_to_utf8(errorBufferW);
|
||||||
|
} else {
|
||||||
|
str = "(unknown)";
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dynamic Loading:
|
||||||
|
typedef HMODULE LoaderPlatformLibraryHandle;
|
||||||
|
static LoaderPlatformLibraryHandle LoaderPlatformLibraryOpen(const std::string &path) {
|
||||||
|
const std::wstring pathW = utf8_to_wide(path);
|
||||||
|
|
||||||
|
// Try loading the library the original way first.
|
||||||
|
LoaderPlatformLibraryHandle handle = LoadLibraryW(pathW.c_str());
|
||||||
|
|
||||||
|
if (handle == NULL && GetLastError() == ERROR_MOD_NOT_FOUND) {
|
||||||
|
const DWORD dwAttrib = GetFileAttributesW(pathW.c_str());
|
||||||
|
const bool fileExists = (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||||
|
if (fileExists) {
|
||||||
|
// If that failed, then try loading it with broader search folders.
|
||||||
|
handle = LoadLibraryExW(pathW.c_str(), NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string LoaderPlatformLibraryOpenError(const std::string &path) {
|
||||||
|
std::stringstream ss;
|
||||||
|
const DWORD dwLastError = GetLastError();
|
||||||
|
const std::string strError = DescribeError(dwLastError);
|
||||||
|
ss << "Failed to open dynamic library " << path << " with error " << dwLastError << ": " << strError;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LoaderPlatformLibraryClose(LoaderPlatformLibraryHandle library) { FreeLibrary(library); }
|
||||||
|
|
||||||
|
static void *LoaderPlatformLibraryGetProcAddr(LoaderPlatformLibraryHandle library, const std::string &name) {
|
||||||
|
assert(library);
|
||||||
|
assert(name.size() > 0);
|
||||||
|
return GetProcAddress(library, name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string LoaderPlatformLibraryGetProcAddrAddrError(const std::string &name) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "Failed to find function " << name << " in dynamic library";
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // Not Linux or Windows
|
||||||
|
|
||||||
|
#define PATH_SEPARATOR ':'
|
||||||
|
#define DIRECTORY_SYMBOL '/'
|
||||||
|
|
||||||
|
static inline LoaderPlatformLibraryHandle LoaderPlatformLibraryOpen(const std::string &path) {
|
||||||
|
// Stub func
|
||||||
|
#error("Unknown platform, undefined dynamic library routines resulting");
|
||||||
|
(void)path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const char *LoaderPlatformLibraryOpenError(const std::string &path) {
|
||||||
|
// Stub func
|
||||||
|
(void)path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void LoaderPlatformLibraryClose(LoaderPlatformLibraryHandle library) {
|
||||||
|
// Stub func
|
||||||
|
(void)library;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void *LoaderPlatformLibraryGetProcAddr(LoaderPlatformLibraryHandle library, const std::string &name) {
|
||||||
|
// Stub func
|
||||||
|
void(library);
|
||||||
|
void(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const char *LoaderPlatformLibraryGetProcAddrError(const std::string &name) {
|
||||||
|
// Stub func
|
||||||
|
(void)name;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
977
extern/openxr/src/loader/manifest_file.cpp
vendored
Normal file
977
extern/openxr/src/loader/manifest_file.cpp
vendored
Normal file
@@ -0,0 +1,977 @@
|
|||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef XR_OS_WINDOWS
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "manifest_file.hpp"
|
||||||
|
|
||||||
|
#include "common_cmake_config.h"
|
||||||
|
#include "filesystem_utils.hpp"
|
||||||
|
#include "loader_platform.hpp"
|
||||||
|
#include "platform_utils.hpp"
|
||||||
|
#include "loader_logger.hpp"
|
||||||
|
|
||||||
|
#include <json/json.h>
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
#include <fstream>
|
||||||
|
#include <memory>
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// OpenXR paths and registry key locations
|
||||||
|
#define OPENXR_RELATIVE_PATH "openxr/"
|
||||||
|
#define OPENXR_IMPLICIT_API_LAYER_RELATIVE_PATH "/api_layers/implicit.d"
|
||||||
|
#define OPENXR_EXPLICIT_API_LAYER_RELATIVE_PATH "/api_layers/explicit.d"
|
||||||
|
#ifdef XR_OS_WINDOWS
|
||||||
|
#define OPENXR_REGISTRY_LOCATION "SOFTWARE\\Khronos\\OpenXR\\"
|
||||||
|
#define OPENXR_IMPLICIT_API_LAYER_REGISTRY_LOCATION "\\ApiLayers\\Implicit"
|
||||||
|
#define OPENXR_EXPLICIT_API_LAYER_REGISTRY_LOCATION "\\ApiLayers\\Explicit"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// OpenXR Loader environment variables of interest
|
||||||
|
#define OPENXR_RUNTIME_JSON_ENV_VAR "XR_RUNTIME_JSON"
|
||||||
|
#define OPENXR_API_LAYER_PATH_ENV_VAR "XR_API_LAYER_PATH"
|
||||||
|
|
||||||
|
#ifndef XRLOADER_ENABLE_EXCEPTION_HANDLING
|
||||||
|
#if JSON_USE_EXCEPTIONS
|
||||||
|
#error \
|
||||||
|
"Loader is configured to not catch exceptions, but jsoncpp was built with exception-throwing enabled, which could violate the C ABI. One of those two things needs to change."
|
||||||
|
#endif // JSON_USE_EXCEPTIONS
|
||||||
|
#endif // !XRLOADER_ENABLE_EXCEPTION_HANDLING
|
||||||
|
|
||||||
|
// Utility functions for finding files in the appropriate paths
|
||||||
|
|
||||||
|
static inline bool StringEndsWith(const std::string &value, const std::string &ending) {
|
||||||
|
if (ending.size() > value.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the file found is a manifest file name, add it to the out_files manifest list.
|
||||||
|
static void AddIfJson(const std::string &full_file, std::vector<std::string> &manifest_files) {
|
||||||
|
if (full_file.empty() || !StringEndsWith(full_file, ".json")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
manifest_files.push_back(full_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the current path for any manifest files. If the provided search_path is a directory, look for
|
||||||
|
// all included JSON files in that directory. Otherwise, just check the provided search_path which should
|
||||||
|
// be a single filename.
|
||||||
|
static void CheckAllFilesInThePath(const std::string &search_path, bool is_directory_list,
|
||||||
|
std::vector<std::string> &manifest_files) {
|
||||||
|
if (FileSysUtilsPathExists(search_path)) {
|
||||||
|
std::string absolute_path;
|
||||||
|
if (!is_directory_list) {
|
||||||
|
// If the file exists, try to add it
|
||||||
|
if (FileSysUtilsIsRegularFile(search_path)) {
|
||||||
|
FileSysUtilsGetAbsolutePath(search_path, absolute_path);
|
||||||
|
AddIfJson(absolute_path, manifest_files);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::vector<std::string> files;
|
||||||
|
if (FileSysUtilsFindFilesInPath(search_path, files)) {
|
||||||
|
for (std::string &cur_file : files) {
|
||||||
|
std::string relative_path;
|
||||||
|
FileSysUtilsCombinePaths(search_path, cur_file, relative_path);
|
||||||
|
if (!FileSysUtilsGetAbsolutePath(relative_path, absolute_path)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
AddIfJson(absolute_path, manifest_files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add all manifest files in the provided paths to the manifest_files list. If search_path
|
||||||
|
// is made up of directory listings (versus direct manifest file names) search each path for
|
||||||
|
// any manifest files.
|
||||||
|
static void AddFilesInPath(const std::string &search_path, bool is_directory_list, std::vector<std::string> &manifest_files) {
|
||||||
|
std::size_t last_found = 0;
|
||||||
|
std::size_t found = search_path.find_first_of(PATH_SEPARATOR);
|
||||||
|
std::string cur_search;
|
||||||
|
|
||||||
|
// Handle any path listings in the string (separated by the appropriate path separator)
|
||||||
|
while (found != std::string::npos) {
|
||||||
|
// substr takes a start index and length.
|
||||||
|
std::size_t length = found - last_found;
|
||||||
|
cur_search = search_path.substr(last_found, length);
|
||||||
|
|
||||||
|
CheckAllFilesInThePath(cur_search, is_directory_list, manifest_files);
|
||||||
|
|
||||||
|
// This works around issue if multiple path separator follow each other directly.
|
||||||
|
last_found = found;
|
||||||
|
while (found == last_found) {
|
||||||
|
last_found = found + 1;
|
||||||
|
found = search_path.find_first_of(PATH_SEPARATOR, last_found);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's something remaining in the string, copy it over
|
||||||
|
if (last_found < search_path.size()) {
|
||||||
|
cur_search = search_path.substr(last_found);
|
||||||
|
CheckAllFilesInThePath(cur_search, is_directory_list, manifest_files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy all paths listed in the cur_path string into output_path and append the appropriate relative_path onto the end of each.
|
||||||
|
static void CopyIncludedPaths(bool is_directory_list, const std::string &cur_path, const std::string &relative_path,
|
||||||
|
std::string &output_path) {
|
||||||
|
if (!cur_path.empty()) {
|
||||||
|
std::size_t last_found = 0;
|
||||||
|
std::size_t found = cur_path.find_first_of(PATH_SEPARATOR);
|
||||||
|
|
||||||
|
// Handle any path listings in the string (separated by the appropriate path separator)
|
||||||
|
while (found != std::string::npos) {
|
||||||
|
std::size_t length = found - last_found;
|
||||||
|
output_path += cur_path.substr(last_found, length);
|
||||||
|
if (is_directory_list && (cur_path[found - 1] != '\\' && cur_path[found - 1] != '/')) {
|
||||||
|
output_path += DIRECTORY_SYMBOL;
|
||||||
|
}
|
||||||
|
output_path += relative_path;
|
||||||
|
output_path += PATH_SEPARATOR;
|
||||||
|
|
||||||
|
last_found = found;
|
||||||
|
found = cur_path.find_first_of(PATH_SEPARATOR, found + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's something remaining in the string, copy it over
|
||||||
|
size_t last_char = cur_path.size() - 1;
|
||||||
|
if (last_found != last_char) {
|
||||||
|
output_path += cur_path.substr(last_found);
|
||||||
|
if (is_directory_list && (cur_path[last_char] != '\\' && cur_path[last_char] != '/')) {
|
||||||
|
output_path += DIRECTORY_SYMBOL;
|
||||||
|
}
|
||||||
|
output_path += relative_path;
|
||||||
|
output_path += PATH_SEPARATOR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for data files in the provided paths, but first check the environment override to determine if we should use that instead.
|
||||||
|
static void ReadDataFilesInSearchPaths(ManifestFileType type, const std::string &override_env_var, const std::string &relative_path,
|
||||||
|
bool &override_active, std::vector<std::string> &manifest_files) {
|
||||||
|
bool is_directory_list = true;
|
||||||
|
bool is_runtime = (type == MANIFEST_TYPE_RUNTIME);
|
||||||
|
char *override_env = nullptr;
|
||||||
|
std::string override_path;
|
||||||
|
std::string search_path;
|
||||||
|
|
||||||
|
if (!override_env_var.empty()) {
|
||||||
|
#ifndef XR_OS_WINDOWS
|
||||||
|
if (geteuid() != getuid() || getegid() != getgid()) {
|
||||||
|
// Don't allow setuid apps to use the env var:
|
||||||
|
override_env = nullptr;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
override_env = PlatformUtilsGetSecureEnv(override_env_var.c_str());
|
||||||
|
if (nullptr != override_env) {
|
||||||
|
// The runtime override is actually a specific list of filenames, not directories
|
||||||
|
if (is_runtime) {
|
||||||
|
is_directory_list = false;
|
||||||
|
}
|
||||||
|
override_path = override_env;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullptr != override_env && !override_path.empty()) {
|
||||||
|
CopyIncludedPaths(is_directory_list, override_path, "", search_path);
|
||||||
|
PlatformUtilsFreeEnv(override_env);
|
||||||
|
override_active = true;
|
||||||
|
} else {
|
||||||
|
override_active = false;
|
||||||
|
#ifndef XR_OS_WINDOWS
|
||||||
|
bool xdg_conf_dirs_alloc = true;
|
||||||
|
bool xdg_data_dirs_alloc = true;
|
||||||
|
const char home_additional[] = ".local/share/";
|
||||||
|
|
||||||
|
// Determine how much space is needed to generate the full search path
|
||||||
|
// for the current manifest files.
|
||||||
|
char *xdg_conf_dirs = PlatformUtilsGetSecureEnv("XDG_CONFIG_DIRS");
|
||||||
|
char *xdg_data_dirs = PlatformUtilsGetSecureEnv("XDG_DATA_DIRS");
|
||||||
|
char *xdg_data_home = PlatformUtilsGetSecureEnv("XDG_DATA_HOME");
|
||||||
|
char *home = PlatformUtilsGetSecureEnv("HOME");
|
||||||
|
|
||||||
|
if (nullptr == xdg_conf_dirs) {
|
||||||
|
xdg_conf_dirs_alloc = false;
|
||||||
|
}
|
||||||
|
if (nullptr == xdg_data_dirs) {
|
||||||
|
xdg_data_dirs_alloc = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullptr == xdg_conf_dirs || xdg_conf_dirs[0] == '\0') {
|
||||||
|
CopyIncludedPaths(true, FALLBACK_CONFIG_DIRS, relative_path, search_path);
|
||||||
|
} else {
|
||||||
|
CopyIncludedPaths(true, xdg_conf_dirs, relative_path, search_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyIncludedPaths(true, SYSCONFDIR, relative_path, search_path);
|
||||||
|
#if defined(EXTRASYSCONFDIR)
|
||||||
|
CopyIncludedPaths(true, EXTRASYSCONFDIR, relative_path, search_path);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (xdg_data_dirs == nullptr || xdg_data_dirs[0] == '\0') {
|
||||||
|
CopyIncludedPaths(true, FALLBACK_DATA_DIRS, relative_path, search_path);
|
||||||
|
} else {
|
||||||
|
CopyIncludedPaths(true, xdg_data_dirs, relative_path, search_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullptr != xdg_data_home) {
|
||||||
|
CopyIncludedPaths(true, xdg_data_home, relative_path, search_path);
|
||||||
|
} else if (nullptr != home) {
|
||||||
|
std::string relative_home_path = home_additional;
|
||||||
|
relative_home_path += relative_path;
|
||||||
|
CopyIncludedPaths(true, home, relative_home_path, search_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xdg_conf_dirs_alloc) {
|
||||||
|
PlatformUtilsFreeEnv(xdg_conf_dirs);
|
||||||
|
}
|
||||||
|
if (xdg_data_dirs_alloc) {
|
||||||
|
PlatformUtilsFreeEnv(xdg_data_dirs);
|
||||||
|
}
|
||||||
|
if (nullptr != xdg_data_home) {
|
||||||
|
PlatformUtilsFreeEnv(xdg_data_home);
|
||||||
|
}
|
||||||
|
if (nullptr != home) {
|
||||||
|
PlatformUtilsFreeEnv(home);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, parse the paths and add any manifest files found in them.
|
||||||
|
AddFilesInPath(search_path, is_directory_list, manifest_files);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef XR_OS_LINUX
|
||||||
|
|
||||||
|
// If ${name} has a nonempty value, return it; if both other arguments are supplied return
|
||||||
|
// ${fallback_env}/fallback_path; otherwise, return whichever of ${fallback_env} and fallback_path
|
||||||
|
// is supplied. If ${fallback_env} or ${fallback_env}/... would be returned but that environment
|
||||||
|
// variable is unset or empty, return the empty string.
|
||||||
|
static std::string GetXDGEnv(const char *name, const char *fallback_env, const char *fallback_path) {
|
||||||
|
char *path = PlatformUtilsGetSecureEnv(name);
|
||||||
|
std::string result;
|
||||||
|
if (path != nullptr) {
|
||||||
|
result = path;
|
||||||
|
PlatformUtilsFreeEnv(path);
|
||||||
|
if (!result.empty()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fallback_env != nullptr) {
|
||||||
|
char *path = PlatformUtilsGetSecureEnv(fallback_env);
|
||||||
|
if (path != nullptr) {
|
||||||
|
result = path;
|
||||||
|
PlatformUtilsFreeEnv(path);
|
||||||
|
}
|
||||||
|
if (result.empty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (fallback_path != nullptr) {
|
||||||
|
result += "/";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fallback_path != nullptr) {
|
||||||
|
result += fallback_path;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the first instance of relative_path occurring in an XDG config dir according to standard
|
||||||
|
// precedence order.
|
||||||
|
static bool FindXDGConfigFile(const std::string &relative_path, std::string &out) {
|
||||||
|
out = GetXDGEnv("XDG_CONFIG_HOME", "HOME", ".config");
|
||||||
|
if (!out.empty()) {
|
||||||
|
out += "/";
|
||||||
|
out += relative_path;
|
||||||
|
if (FileSysUtilsPathExists(out)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istringstream iss(GetXDGEnv("XDG_CONFIG_DIRS", nullptr, FALLBACK_CONFIG_DIRS));
|
||||||
|
std::string path;
|
||||||
|
while (std::getline(iss, path, PATH_SEPARATOR)) {
|
||||||
|
if (path.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
out = path;
|
||||||
|
out += "/";
|
||||||
|
out += relative_path;
|
||||||
|
if (FileSysUtilsPathExists(out)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out = SYSCONFDIR;
|
||||||
|
out += "/";
|
||||||
|
out += relative_path;
|
||||||
|
if (FileSysUtilsPathExists(out)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(EXTRASYSCONFDIR)
|
||||||
|
out = EXTRASYSCONFDIR;
|
||||||
|
out += "/";
|
||||||
|
out += relative_path;
|
||||||
|
if (FileSysUtilsPathExists(out)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
out.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XR_OS_WINDOWS
|
||||||
|
|
||||||
|
// Look for runtime data files in the provided paths, but first check the environment override to determine
|
||||||
|
// if we should use that instead.
|
||||||
|
static void ReadRuntimeDataFilesInRegistry(ManifestFileType type, const std::string &runtime_registry_location,
|
||||||
|
const std::string &default_runtime_value_name,
|
||||||
|
std::vector<std::string> &manifest_files) {
|
||||||
|
HKEY hkey;
|
||||||
|
DWORD access_flags;
|
||||||
|
wchar_t value_w[1024];
|
||||||
|
DWORD value_size_w = sizeof(value_w); // byte size of the buffer.
|
||||||
|
|
||||||
|
// Generate the full registry location for the registry information
|
||||||
|
std::string full_registry_location = OPENXR_REGISTRY_LOCATION;
|
||||||
|
full_registry_location += std::to_string(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION));
|
||||||
|
full_registry_location += runtime_registry_location;
|
||||||
|
|
||||||
|
const std::wstring full_registry_location_w = utf8_to_wide(full_registry_location);
|
||||||
|
const std::wstring default_runtime_value_name_w = utf8_to_wide(default_runtime_value_name);
|
||||||
|
|
||||||
|
// Use 64 bit regkey for 64bit application, and use 32 bit regkey in WOW for 32bit application.
|
||||||
|
access_flags = KEY_QUERY_VALUE;
|
||||||
|
LONG open_value = RegOpenKeyExW(HKEY_LOCAL_MACHINE, full_registry_location_w.c_str(), 0, access_flags, &hkey);
|
||||||
|
|
||||||
|
if (ERROR_SUCCESS != open_value) {
|
||||||
|
std::string warning_message = "ReadLayerDataFilesInRegistry - failed to open registry key ";
|
||||||
|
warning_message += full_registry_location;
|
||||||
|
LoaderLogger::LogWarningMessage("", warning_message);
|
||||||
|
} else if (ERROR_SUCCESS != RegGetValueW(hkey, nullptr, default_runtime_value_name_w.c_str(),
|
||||||
|
RRF_RT_REG_SZ | REG_EXPAND_SZ | RRF_ZEROONFAILURE, NULL,
|
||||||
|
reinterpret_cast<LPBYTE>(&value_w), &value_size_w)) {
|
||||||
|
std::string warning_message = "ReadLayerDataFilesInRegistry - failed to read registry value ";
|
||||||
|
warning_message += default_runtime_value_name;
|
||||||
|
LoaderLogger::LogWarningMessage("", warning_message);
|
||||||
|
} else {
|
||||||
|
AddFilesInPath(wide_to_utf8(value_w), false, manifest_files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for layer data files in the provided paths, but first check the environment override to determine
|
||||||
|
// if we should use that instead.
|
||||||
|
static void ReadLayerDataFilesInRegistry(ManifestFileType type, const std::string ®istry_location,
|
||||||
|
std::vector<std::string> &manifest_files) {
|
||||||
|
HKEY hive[2] = {HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER};
|
||||||
|
bool found[2] = {false, false};
|
||||||
|
HKEY hkey;
|
||||||
|
DWORD access_flags;
|
||||||
|
LONG rtn_value;
|
||||||
|
wchar_t name_w[1024]{};
|
||||||
|
DWORD value;
|
||||||
|
DWORD name_size = 1023;
|
||||||
|
DWORD value_size = sizeof(value);
|
||||||
|
|
||||||
|
for (uint8_t hive_index = 0; hive_index < 2; ++hive_index) {
|
||||||
|
DWORD key_index = 0;
|
||||||
|
std::string full_registry_location = OPENXR_REGISTRY_LOCATION;
|
||||||
|
full_registry_location += std::to_string(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION));
|
||||||
|
full_registry_location += registry_location;
|
||||||
|
|
||||||
|
access_flags = KEY_QUERY_VALUE;
|
||||||
|
std::wstring full_registry_location_w = utf8_to_wide(full_registry_location);
|
||||||
|
LONG open_value = RegOpenKeyExW(hive[hive_index], full_registry_location_w.c_str(), 0, access_flags, &hkey);
|
||||||
|
if (ERROR_SUCCESS != open_value) {
|
||||||
|
if (hive_index == 1 && !found[0]) {
|
||||||
|
std::string warning_message = "ReadLayerDataFilesInRegistry - failed to read registry location ";
|
||||||
|
warning_message += registry_location;
|
||||||
|
warning_message += " in either HKEY_LOCAL_MACHINE or KHEY_CURRENT_USER";
|
||||||
|
LoaderLogger::LogWarningMessage("", warning_message);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
found[hive_index] = true;
|
||||||
|
while (ERROR_SUCCESS ==
|
||||||
|
(rtn_value = RegEnumValueW(hkey, key_index++, name_w, &name_size, NULL, NULL, (LPBYTE)&value, &value_size))) {
|
||||||
|
if (value_size == sizeof(value) && value == 0) {
|
||||||
|
const std::string filename = wide_to_utf8(name_w);
|
||||||
|
AddFilesInPath(filename, false, manifest_files);
|
||||||
|
}
|
||||||
|
// Reset some items for the next loop
|
||||||
|
name_size = 1023;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // XR_OS_WINDOWS
|
||||||
|
|
||||||
|
ManifestFile::ManifestFile(ManifestFileType type, const std::string &filename, const std::string &library_path)
|
||||||
|
: _filename(filename), _type(type), _library_path(library_path) {}
|
||||||
|
|
||||||
|
ManifestFile::~ManifestFile() = default;
|
||||||
|
|
||||||
|
bool ManifestFile::IsValidJson(const Json::Value &root_node, JsonVersion &version) {
|
||||||
|
if (root_node["file_format_version"].isNull() || !root_node["file_format_version"].isString()) {
|
||||||
|
LoaderLogger::LogErrorMessage("", "ManifestFile::IsValidJson - JSON file missing \"file_format_version\"");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::string file_format = root_node["file_format_version"].asString();
|
||||||
|
sscanf(file_format.c_str(), "%d.%d.%d", &version.major, &version.minor, &version.patch);
|
||||||
|
|
||||||
|
// Only version 1.0.0 is defined currently. Eventually we may have more version, but
|
||||||
|
// some of the versions may only be valid for layers or runtimes specifically.
|
||||||
|
if (version.major != 1 || version.minor != 0 || version.patch != 0) {
|
||||||
|
std::string error_message = "ManifestFile::IsValidJson - JSON \"file_format_version\" ";
|
||||||
|
error_message += std::to_string(version.major);
|
||||||
|
error_message += ".";
|
||||||
|
error_message += std::to_string(version.minor);
|
||||||
|
error_message += ".";
|
||||||
|
error_message += std::to_string(version.patch);
|
||||||
|
error_message += " is not supported";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GetExtensionProperties(const std::vector<ExtensionListing> &extensions, std::vector<XrExtensionProperties> &props) {
|
||||||
|
for (const auto &ext : extensions) {
|
||||||
|
auto it =
|
||||||
|
std::find_if(props.begin(), props.end(), [&](XrExtensionProperties &prop) { return prop.extensionName == ext.name; });
|
||||||
|
if (it != props.end()) {
|
||||||
|
it->extensionVersion = std::max(it->extensionVersion, ext.extension_version);
|
||||||
|
} else {
|
||||||
|
XrExtensionProperties prop = {};
|
||||||
|
prop.type = XR_TYPE_EXTENSION_PROPERTIES;
|
||||||
|
prop.next = nullptr;
|
||||||
|
strncpy(prop.extensionName, ext.name.c_str(), XR_MAX_EXTENSION_NAME_SIZE - 1);
|
||||||
|
prop.extensionName[XR_MAX_EXTENSION_NAME_SIZE - 1] = '\0';
|
||||||
|
prop.extensionVersion = ext.extension_version;
|
||||||
|
props.push_back(prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return any instance extensions found in the manifest files in the proper form for
|
||||||
|
// OpenXR (XrExtensionProperties).
|
||||||
|
void ManifestFile::GetInstanceExtensionProperties(std::vector<XrExtensionProperties> &props) {
|
||||||
|
GetExtensionProperties(_instance_extensions, props);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return any device extensions found in the manifest files in the proper form for
|
||||||
|
// OpenXR (XrExtensionProperties).
|
||||||
|
void ManifestFile::GetDeviceExtensionProperties(std::vector<XrExtensionProperties> &props) {
|
||||||
|
GetExtensionProperties(_device_extensions, props);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string &ManifestFile::GetFunctionName(const std::string &func_name) {
|
||||||
|
if (!_functions_renamed.empty()) {
|
||||||
|
auto found = _functions_renamed.find(func_name);
|
||||||
|
if (found != _functions_renamed.end()) {
|
||||||
|
return found->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return func_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
RuntimeManifestFile::RuntimeManifestFile(const std::string &filename, const std::string &library_path)
|
||||||
|
: ManifestFile(MANIFEST_TYPE_RUNTIME, filename, library_path) {}
|
||||||
|
|
||||||
|
RuntimeManifestFile::~RuntimeManifestFile() = default;
|
||||||
|
|
||||||
|
void RuntimeManifestFile::CreateIfValid(const std::string &filename,
|
||||||
|
std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files) {
|
||||||
|
std::ifstream json_stream = std::ifstream(filename, std::ifstream::in);
|
||||||
|
if (!json_stream.is_open()) {
|
||||||
|
std::string error_message = "RuntimeManifestFile::createIfValid failed to open ";
|
||||||
|
error_message += filename;
|
||||||
|
error_message += ". Does it exist?";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Json::Reader reader;
|
||||||
|
Json::Value root_node = Json::nullValue;
|
||||||
|
Json::Value runtime_root_node = Json::nullValue;
|
||||||
|
JsonVersion file_version = {};
|
||||||
|
if (!reader.parse(json_stream, root_node, false) || root_node.isNull()) {
|
||||||
|
std::string error_message = "RuntimeManifestFile::CreateIfValid failed to parse ";
|
||||||
|
error_message += filename;
|
||||||
|
error_message += ". Is it a valid runtime manifest file? Error was:\n ";
|
||||||
|
error_message += reader.getFormattedErrorMessages();
|
||||||
|
LoaderLogger::LogErrorMessage("", error_message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!ManifestFile::IsValidJson(root_node, file_version)) {
|
||||||
|
std::string error_message = "RuntimeManifestFile::CreateIfValid isValidJson indicates ";
|
||||||
|
error_message += filename;
|
||||||
|
error_message += " is not a valid manifest file.";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
runtime_root_node = root_node["runtime"];
|
||||||
|
// The Runtime manifest file needs the "runtime" root as well as sub-nodes for "api_version" and
|
||||||
|
// "library_path". If any of those aren't there, fail.
|
||||||
|
if (runtime_root_node.isNull() || runtime_root_node["library_path"].isNull() || !runtime_root_node["library_path"].isString()) {
|
||||||
|
std::string error_message = "RuntimeManifestFile::CreateIfValid ";
|
||||||
|
error_message += filename;
|
||||||
|
error_message += " is missing required fields. Verify all proper fields exist.";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string lib_path = runtime_root_node["library_path"].asString();
|
||||||
|
|
||||||
|
// If the library_path variable has no directory symbol, it's just a file name and should be accessible on the
|
||||||
|
// global library path.
|
||||||
|
if (lib_path.find('\\') != std::string::npos || lib_path.find('/') != std::string::npos) {
|
||||||
|
// If the library_path is an absolute path, just use that if it exists
|
||||||
|
if (FileSysUtilsIsAbsolutePath(lib_path)) {
|
||||||
|
if (!FileSysUtilsPathExists(lib_path)) {
|
||||||
|
std::string error_message = "RuntimeManifestFile::CreateIfValid ";
|
||||||
|
error_message += filename;
|
||||||
|
error_message += " library ";
|
||||||
|
error_message += lib_path;
|
||||||
|
error_message += " does not appear to exist";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Otherwise, treat the library path as a relative path based on the JSON file.
|
||||||
|
std::string combined_path;
|
||||||
|
std::string file_parent;
|
||||||
|
if (!FileSysUtilsGetParentPath(filename, file_parent) ||
|
||||||
|
!FileSysUtilsCombinePaths(file_parent, lib_path, combined_path) || !FileSysUtilsPathExists(combined_path)) {
|
||||||
|
std::string error_message = "RuntimeManifestFile::CreateIfValid ";
|
||||||
|
error_message += filename;
|
||||||
|
error_message += " library ";
|
||||||
|
error_message += combined_path;
|
||||||
|
error_message += " does not appear to exist";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lib_path = combined_path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add this runtime manifest file
|
||||||
|
manifest_files.emplace_back(new RuntimeManifestFile(filename, lib_path));
|
||||||
|
|
||||||
|
// Add any extensions to it after the fact.
|
||||||
|
Json::Value dev_exts = runtime_root_node["device_extensions"];
|
||||||
|
if (!dev_exts.isNull() && dev_exts.isArray()) {
|
||||||
|
for (Json::ValueIterator dev_ext_it = dev_exts.begin(); dev_ext_it != dev_exts.end(); ++dev_ext_it) {
|
||||||
|
Json::Value dev_ext = (*dev_ext_it);
|
||||||
|
Json::Value dev_ext_name = dev_ext["name"];
|
||||||
|
Json::Value dev_ext_version = dev_ext["extension_version"];
|
||||||
|
Json::Value dev_ext_entries = dev_ext["entrypoints"];
|
||||||
|
if (!dev_ext_name.isNull() && dev_ext_name.isString() && !dev_ext_version.isNull() && dev_ext_version.isUInt() &&
|
||||||
|
!dev_ext_entries.isNull() && dev_ext_entries.isArray()) {
|
||||||
|
ExtensionListing ext = {};
|
||||||
|
ext.name = dev_ext_name.asString();
|
||||||
|
ext.extension_version = dev_ext_version.asUInt();
|
||||||
|
for (Json::ValueIterator entry_it = dev_ext_entries.begin(); entry_it != dev_ext_entries.end(); ++entry_it) {
|
||||||
|
Json::Value entry = (*entry_it);
|
||||||
|
if (!entry.isNull() && entry.isString()) {
|
||||||
|
ext.entrypoints.push_back(entry.asString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
manifest_files.back()->_device_extensions.push_back(ext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Value inst_exts = runtime_root_node["instance_extensions"];
|
||||||
|
if (!inst_exts.isNull() && inst_exts.isArray()) {
|
||||||
|
for (Json::ValueIterator inst_ext_it = inst_exts.begin(); inst_ext_it != inst_exts.end(); ++inst_ext_it) {
|
||||||
|
Json::Value inst_ext = (*inst_ext_it);
|
||||||
|
Json::Value inst_ext_name = inst_ext["name"];
|
||||||
|
Json::Value inst_ext_version = inst_ext["extension_version"];
|
||||||
|
if (!inst_ext_name.isNull() && inst_ext_name.isString() && !inst_ext_version.isNull() && inst_ext_version.isUInt()) {
|
||||||
|
ExtensionListing ext = {};
|
||||||
|
ext.name = inst_ext_name.asString();
|
||||||
|
ext.extension_version = inst_ext_version.asUInt();
|
||||||
|
manifest_files.back()->_instance_extensions.push_back(ext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Value funcs_renamed = runtime_root_node["functions"];
|
||||||
|
if (!funcs_renamed.isNull() && !funcs_renamed.empty()) {
|
||||||
|
for (Json::ValueIterator func_it = funcs_renamed.begin(); func_it != funcs_renamed.end(); ++func_it) {
|
||||||
|
if (!(*func_it).isString()) {
|
||||||
|
std::string warning_message = "RuntimeManifestFile::CreateIfValid ";
|
||||||
|
warning_message += filename;
|
||||||
|
warning_message += " \"functions\" section contains non-string values.";
|
||||||
|
LoaderLogger::LogWarningMessage("", warning_message);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string original_name = func_it.key().asString();
|
||||||
|
std::string new_name = (*func_it).asString();
|
||||||
|
manifest_files.back()->_functions_renamed.insert(std::make_pair(original_name, new_name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find all manifest files in the appropriate search paths/registries for the given type.
|
||||||
|
XrResult RuntimeManifestFile::FindManifestFiles(ManifestFileType type,
|
||||||
|
std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files) {
|
||||||
|
XrResult result = XR_SUCCESS;
|
||||||
|
if (MANIFEST_TYPE_RUNTIME != type) {
|
||||||
|
LoaderLogger::LogErrorMessage("", "RuntimeManifestFile::FindManifestFiles - unknown manifest file requested");
|
||||||
|
return XR_ERROR_FILE_ACCESS_ERROR;
|
||||||
|
}
|
||||||
|
std::string filename;
|
||||||
|
char *override_path = PlatformUtilsGetSecureEnv(OPENXR_RUNTIME_JSON_ENV_VAR);
|
||||||
|
if (override_path != nullptr && *override_path != '\0') {
|
||||||
|
filename = override_path;
|
||||||
|
PlatformUtilsFreeEnv(override_path);
|
||||||
|
std::string info_message = "RuntimeManifestFile::FindManifestFiles - using environment variable override runtime file ";
|
||||||
|
info_message += filename;
|
||||||
|
LoaderLogger::LogInfoMessage("", info_message);
|
||||||
|
} else {
|
||||||
|
PlatformUtilsFreeEnv(override_path);
|
||||||
|
#ifdef XR_OS_WINDOWS
|
||||||
|
std::vector<std::string> filenames;
|
||||||
|
ReadRuntimeDataFilesInRegistry(type, "", "ActiveRuntime", filenames);
|
||||||
|
if (filenames.size() == 0) {
|
||||||
|
LoaderLogger::LogErrorMessage(
|
||||||
|
"", "RuntimeManifestFile::FindManifestFiles - failed to find active runtime file in registry");
|
||||||
|
return XR_ERROR_FILE_ACCESS_ERROR;
|
||||||
|
}
|
||||||
|
if (filenames.size() > 1) {
|
||||||
|
LoaderLogger::LogWarningMessage(
|
||||||
|
"", "RuntimeManifestFile::FindManifestFiles - found too many default runtime files in registry");
|
||||||
|
}
|
||||||
|
filename = filenames[0];
|
||||||
|
#elif defined(XR_OS_LINUX)
|
||||||
|
const std::string relative_path =
|
||||||
|
"openxr/" + std::to_string(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION)) + "/active_runtime.json";
|
||||||
|
if (!FindXDGConfigFile(relative_path, filename)) {
|
||||||
|
LoaderLogger::LogErrorMessage(
|
||||||
|
"", "RuntimeManifestFile::FindManifestFiles - failed to determine active runtime file path for this environment");
|
||||||
|
return XR_ERROR_FILE_ACCESS_ERROR;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (!PlatformGetGlobalRuntimeFileName(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION), filename)) {
|
||||||
|
LoaderLogger::LogErrorMessage(
|
||||||
|
"", "RuntimeManifestFile::FindManifestFiles - failed to determine active runtime file path for this environment");
|
||||||
|
return XR_ERROR_FILE_ACCESS_ERROR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
std::string info_message = "RuntimeManifestFile::FindManifestFiles - using global runtime file ";
|
||||||
|
info_message += filename;
|
||||||
|
LoaderLogger::LogInfoMessage("", info_message);
|
||||||
|
}
|
||||||
|
RuntimeManifestFile::CreateIfValid(filename, manifest_files);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ApiLayerManifestFile::ApiLayerManifestFile(ManifestFileType type, const std::string &filename, const std::string &layer_name,
|
||||||
|
const std::string &description, const JsonVersion &api_version,
|
||||||
|
const uint32_t &implementation_version, const std::string &library_path)
|
||||||
|
: ManifestFile(type, filename, library_path),
|
||||||
|
_api_version(api_version),
|
||||||
|
_layer_name(layer_name),
|
||||||
|
_description(description),
|
||||||
|
_implementation_version(implementation_version) {}
|
||||||
|
|
||||||
|
ApiLayerManifestFile::~ApiLayerManifestFile() = default;
|
||||||
|
|
||||||
|
void ApiLayerManifestFile::CreateIfValid(ManifestFileType type, const std::string &filename,
|
||||||
|
std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files) {
|
||||||
|
std::ifstream json_stream = std::ifstream(filename, std::ifstream::in);
|
||||||
|
Json::Reader reader;
|
||||||
|
Json::Value root_node = Json::nullValue;
|
||||||
|
if (!reader.parse(json_stream, root_node, false) || root_node.isNull()) {
|
||||||
|
std::string error_message = "ApiLayerManifestFile::CreateIfValid failed to parse ";
|
||||||
|
error_message += filename;
|
||||||
|
error_message += ". Is it a valid layer manifest file? Error was:\n";
|
||||||
|
error_message += reader.getFormattedErrorMessages();
|
||||||
|
LoaderLogger::LogErrorMessage("", error_message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
JsonVersion file_version = {};
|
||||||
|
if (!ManifestFile::IsValidJson(root_node, file_version)) {
|
||||||
|
std::string error_message = "ApiLayerManifestFile::CreateIfValid isValidJson indicates ";
|
||||||
|
error_message += filename;
|
||||||
|
error_message += " is not a valid manifest file.";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Value layer_root_node = root_node["api_layer"];
|
||||||
|
|
||||||
|
// The API Layer manifest file needs the "api_layer" root as well as other sub-nodes.
|
||||||
|
// If any of those aren't there, fail.
|
||||||
|
if (layer_root_node.isNull() || layer_root_node["name"].isNull() || !layer_root_node["name"].isString() ||
|
||||||
|
layer_root_node["api_version"].isNull() || !layer_root_node["api_version"].isString() ||
|
||||||
|
layer_root_node["library_path"].isNull() || !layer_root_node["library_path"].isString() ||
|
||||||
|
layer_root_node["implementation_version"].isNull() || !layer_root_node["implementation_version"].isString()) {
|
||||||
|
std::string error_message = "ApiLayerManifestFile::CreateIfValid ";
|
||||||
|
error_message += filename;
|
||||||
|
error_message += " is missing required fields. Verify all proper fields exist.";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (MANIFEST_TYPE_IMPLICIT_API_LAYER == type) {
|
||||||
|
bool enabled = true;
|
||||||
|
// Implicit layers require the disable environment variable.
|
||||||
|
if (layer_root_node["disable_environment"].isNull() || !layer_root_node["disable_environment"].isString()) {
|
||||||
|
std::string error_message = "ApiLayerManifestFile::CreateIfValid Implicit layer ";
|
||||||
|
error_message += filename;
|
||||||
|
error_message += " is missing \"disable_environment\"";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Check if there's an enable environment variable provided
|
||||||
|
if (!layer_root_node["enable_environment"].isNull() && layer_root_node["enable_environment"].isString()) {
|
||||||
|
char *enable_val = PlatformUtilsGetEnv(layer_root_node["enable_environment"].asString().c_str());
|
||||||
|
// If it's not set in the environment, disable the layer
|
||||||
|
if (nullptr == enable_val) {
|
||||||
|
enabled = false;
|
||||||
|
}
|
||||||
|
PlatformUtilsFreeEnv(enable_val);
|
||||||
|
}
|
||||||
|
// Check for the disable environment variable, which must be provided in the JSON
|
||||||
|
char *disable_val = PlatformUtilsGetEnv(layer_root_node["disable_environment"].asString().c_str());
|
||||||
|
// If the envar is set, disable the layer. Disable envar overrides enable above
|
||||||
|
if (nullptr != disable_val) {
|
||||||
|
enabled = false;
|
||||||
|
}
|
||||||
|
PlatformUtilsFreeEnv(disable_val);
|
||||||
|
|
||||||
|
// Not enabled, so pretend like it isn't even there.
|
||||||
|
if (!enabled) {
|
||||||
|
std::string info_message = "ApiLayerManifestFile::CreateIfValid Implicit layer ";
|
||||||
|
info_message += filename;
|
||||||
|
info_message += " is disabled";
|
||||||
|
LoaderLogger::LogInfoMessage("", info_message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::string layer_name = layer_root_node["name"].asString();
|
||||||
|
std::string api_version_string = layer_root_node["api_version"].asString();
|
||||||
|
JsonVersion api_version = {};
|
||||||
|
sscanf(api_version_string.c_str(), "%d.%d", &api_version.major, &api_version.minor);
|
||||||
|
api_version.patch = 0;
|
||||||
|
|
||||||
|
if ((api_version.major == 0 && api_version.minor == 0) || api_version.major > XR_VERSION_MAJOR(XR_CURRENT_API_VERSION)) {
|
||||||
|
std::string warning_message = "ApiLayerManifestFile::CreateIfValid layer ";
|
||||||
|
warning_message += filename;
|
||||||
|
warning_message += " has invalid API Version. Skipping layer.";
|
||||||
|
LoaderLogger::LogWarningMessage("", warning_message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t implementation_version = atoi(layer_root_node["implementation_version"].asString().c_str());
|
||||||
|
std::string library_path = layer_root_node["library_path"].asString();
|
||||||
|
|
||||||
|
// If the library_path variable has no directory symbol, it's just a file name and should be accessible on the
|
||||||
|
// global library path.
|
||||||
|
if (library_path.find('\\') != std::string::npos || library_path.find('/') != std::string::npos) {
|
||||||
|
// If the library_path is an absolute path, just use that if it exists
|
||||||
|
if (FileSysUtilsIsAbsolutePath(library_path)) {
|
||||||
|
if (!FileSysUtilsPathExists(library_path)) {
|
||||||
|
std::string error_message = "ApiLayerManifestFile::CreateIfValid ";
|
||||||
|
error_message += filename;
|
||||||
|
error_message += " library ";
|
||||||
|
error_message += library_path;
|
||||||
|
error_message += " does not appear to exist";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Otherwise, treat the library path as a relative path based on the JSON file.
|
||||||
|
std::string combined_path;
|
||||||
|
std::string file_parent;
|
||||||
|
if (!FileSysUtilsGetParentPath(filename, file_parent) ||
|
||||||
|
!FileSysUtilsCombinePaths(file_parent, library_path, combined_path) || !FileSysUtilsPathExists(combined_path)) {
|
||||||
|
std::string error_message = "ApiLayerManifestFile::CreateIfValid ";
|
||||||
|
error_message += filename;
|
||||||
|
error_message += " library ";
|
||||||
|
error_message += combined_path;
|
||||||
|
error_message += " does not appear to exist";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
library_path = combined_path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string description;
|
||||||
|
if (!layer_root_node["description"].isNull() && layer_root_node["description"].isString()) {
|
||||||
|
description = layer_root_node["description"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add this layer manifest file
|
||||||
|
manifest_files.emplace_back(
|
||||||
|
new ApiLayerManifestFile(type, filename, layer_name, description, api_version, implementation_version, library_path));
|
||||||
|
|
||||||
|
// Add any extensions to it after the fact.
|
||||||
|
Json::Value dev_exts = layer_root_node["device_extensions"];
|
||||||
|
if (!dev_exts.isNull() && dev_exts.isArray()) {
|
||||||
|
for (Json::ValueIterator dev_ext_it = dev_exts.begin(); dev_ext_it != dev_exts.end(); ++dev_ext_it) {
|
||||||
|
Json::Value dev_ext = (*dev_ext_it);
|
||||||
|
Json::Value dev_ext_name = dev_ext["name"];
|
||||||
|
Json::Value dev_ext_version = dev_ext["extension_version"];
|
||||||
|
Json::Value dev_ext_entries = dev_ext["entrypoints"];
|
||||||
|
if (!dev_ext_name.isNull() && dev_ext_name.isString() && !dev_ext_version.isNull() && dev_ext_version.isString() &&
|
||||||
|
!dev_ext_entries.isNull() && dev_ext_entries.isArray()) {
|
||||||
|
ExtensionListing ext = {};
|
||||||
|
ext.name = dev_ext_name.asString();
|
||||||
|
ext.extension_version = atoi(dev_ext_version.asString().c_str());
|
||||||
|
for (Json::ValueIterator entry_it = dev_ext_entries.begin(); entry_it != dev_ext_entries.end(); ++entry_it) {
|
||||||
|
Json::Value entry = (*entry_it);
|
||||||
|
if (!entry.isNull() && entry.isString()) {
|
||||||
|
ext.entrypoints.push_back(entry.asString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
manifest_files.back()->_device_extensions.push_back(ext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Value inst_exts = layer_root_node["instance_extensions"];
|
||||||
|
if (!inst_exts.isNull() && inst_exts.isArray()) {
|
||||||
|
for (Json::ValueIterator inst_ext_it = inst_exts.begin(); inst_ext_it != inst_exts.end(); ++inst_ext_it) {
|
||||||
|
Json::Value inst_ext = (*inst_ext_it);
|
||||||
|
Json::Value inst_ext_name = inst_ext["name"];
|
||||||
|
Json::Value inst_ext_version = inst_ext["extension_version"];
|
||||||
|
if (!inst_ext_name.isNull() && inst_ext_name.isString() && !inst_ext_version.isNull() && inst_ext_version.isString()) {
|
||||||
|
ExtensionListing ext = {};
|
||||||
|
ext.name = inst_ext_name.asString();
|
||||||
|
ext.extension_version = atoi(inst_ext_version.asString().c_str());
|
||||||
|
manifest_files.back()->_instance_extensions.push_back(ext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Value funcs_renamed = layer_root_node["functions"];
|
||||||
|
if (!funcs_renamed.isNull() && !funcs_renamed.empty()) {
|
||||||
|
for (Json::ValueIterator func_it = funcs_renamed.begin(); func_it != funcs_renamed.end(); ++func_it) {
|
||||||
|
if (!(*func_it).isString()) {
|
||||||
|
std::string warning_message = "ApiLayerManifestFile::CreateIfValid ";
|
||||||
|
warning_message += filename;
|
||||||
|
warning_message += " \"functions\" section contains non-string values.";
|
||||||
|
LoaderLogger::LogWarningMessage("", warning_message);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string original_name = func_it.key().asString();
|
||||||
|
std::string new_name = (*func_it).asString();
|
||||||
|
manifest_files.back()->_functions_renamed.insert(std::make_pair(original_name, new_name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XrApiLayerProperties ApiLayerManifestFile::GetApiLayerProperties() {
|
||||||
|
XrApiLayerProperties props = {};
|
||||||
|
props.type = XR_TYPE_API_LAYER_PROPERTIES;
|
||||||
|
props.next = nullptr;
|
||||||
|
props.layerVersion = _implementation_version;
|
||||||
|
props.specVersion = XR_MAKE_VERSION(_api_version.major, _api_version.minor, _api_version.patch);
|
||||||
|
strncpy(props.layerName, _layer_name.c_str(), XR_MAX_API_LAYER_NAME_SIZE - 1);
|
||||||
|
if (_layer_name.size() >= XR_MAX_API_LAYER_NAME_SIZE - 1) {
|
||||||
|
props.layerName[XR_MAX_API_LAYER_NAME_SIZE - 1] = '\0';
|
||||||
|
}
|
||||||
|
strncpy(props.description, _description.c_str(), XR_MAX_API_LAYER_DESCRIPTION_SIZE - 1);
|
||||||
|
if (_description.size() >= XR_MAX_API_LAYER_DESCRIPTION_SIZE - 1) {
|
||||||
|
props.description[XR_MAX_API_LAYER_DESCRIPTION_SIZE - 1] = '\0';
|
||||||
|
}
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find all layer manifest files in the appropriate search paths/registries for the given type.
|
||||||
|
XrResult ApiLayerManifestFile::FindManifestFiles(ManifestFileType type,
|
||||||
|
std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files) {
|
||||||
|
std::string relative_path;
|
||||||
|
std::string override_env_var;
|
||||||
|
std::string registry_location;
|
||||||
|
|
||||||
|
// Add the appropriate top-level folders for the relative path. These should be
|
||||||
|
// the string "openxr/" followed by the API major version as a string.
|
||||||
|
relative_path = OPENXR_RELATIVE_PATH;
|
||||||
|
relative_path += std::to_string(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION));
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case MANIFEST_TYPE_IMPLICIT_API_LAYER:
|
||||||
|
relative_path += OPENXR_IMPLICIT_API_LAYER_RELATIVE_PATH;
|
||||||
|
override_env_var = "";
|
||||||
|
#ifdef XR_OS_WINDOWS
|
||||||
|
registry_location = OPENXR_IMPLICIT_API_LAYER_REGISTRY_LOCATION;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case MANIFEST_TYPE_EXPLICIT_API_LAYER:
|
||||||
|
relative_path += OPENXR_EXPLICIT_API_LAYER_RELATIVE_PATH;
|
||||||
|
override_env_var = OPENXR_API_LAYER_PATH_ENV_VAR;
|
||||||
|
#ifdef XR_OS_WINDOWS
|
||||||
|
registry_location = OPENXR_EXPLICIT_API_LAYER_REGISTRY_LOCATION;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LoaderLogger::LogErrorMessage("", "ApiLayerManifestFile::FindManifestFiles - unknown manifest file requested");
|
||||||
|
return XR_ERROR_FILE_ACCESS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool override_active = false;
|
||||||
|
std::vector<std::string> filenames;
|
||||||
|
ReadDataFilesInSearchPaths(type, override_env_var, relative_path, override_active, filenames);
|
||||||
|
|
||||||
|
#ifdef XR_OS_WINDOWS
|
||||||
|
// Read the registry if the override wasn't active.
|
||||||
|
if (!override_active) {
|
||||||
|
ReadLayerDataFilesInRegistry(type, registry_location, filenames);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case MANIFEST_TYPE_IMPLICIT_API_LAYER:
|
||||||
|
case MANIFEST_TYPE_EXPLICIT_API_LAYER:
|
||||||
|
for (std::string &cur_file : filenames) {
|
||||||
|
ApiLayerManifestFile::CreateIfValid(type, cur_file, manifest_files);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
121
extern/openxr/src/loader/manifest_file.hpp
vendored
Normal file
121
extern/openxr/src/loader/manifest_file.hpp
vendored
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
// Copyright (c) 2017 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017 Valve Corporation
|
||||||
|
// Copyright (c) 2017 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
class Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ManifestFileType {
|
||||||
|
MANIFEST_TYPE_UNDEFINED = 0,
|
||||||
|
MANIFEST_TYPE_RUNTIME,
|
||||||
|
MANIFEST_TYPE_IMPLICIT_API_LAYER,
|
||||||
|
MANIFEST_TYPE_EXPLICIT_API_LAYER,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct JsonVersion {
|
||||||
|
uint32_t major;
|
||||||
|
uint32_t minor;
|
||||||
|
uint32_t patch;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExtensionListing {
|
||||||
|
std::string name;
|
||||||
|
uint32_t extension_version;
|
||||||
|
std::vector<std::string> entrypoints;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ManifestFile class -
|
||||||
|
// Base class responsible for finding and parsing manifest files.
|
||||||
|
class ManifestFile {
|
||||||
|
public:
|
||||||
|
ManifestFile(ManifestFileType type, const std::string &filename, const std::string &library_path);
|
||||||
|
virtual ~ManifestFile();
|
||||||
|
static bool IsValidJson(const Json::Value &root, JsonVersion &version);
|
||||||
|
|
||||||
|
// We don't want any copy constructors
|
||||||
|
ManifestFile &operator=(const ManifestFile &manifest_file) = delete;
|
||||||
|
|
||||||
|
ManifestFileType Type() { return _type; }
|
||||||
|
std::string Filename() { return _filename; }
|
||||||
|
std::string LibraryPath() { return _library_path; }
|
||||||
|
void GetInstanceExtensionProperties(std::vector<XrExtensionProperties> &props);
|
||||||
|
void GetDeviceExtensionProperties(std::vector<XrExtensionProperties> &props);
|
||||||
|
const std::string &GetFunctionName(const std::string &func_name);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string _filename;
|
||||||
|
ManifestFileType _type;
|
||||||
|
std::string _library_path;
|
||||||
|
std::vector<ExtensionListing> _instance_extensions;
|
||||||
|
std::vector<ExtensionListing> _device_extensions;
|
||||||
|
std::unordered_map<std::string, std::string> _functions_renamed;
|
||||||
|
};
|
||||||
|
|
||||||
|
// RuntimeManifestFile class -
|
||||||
|
// Responsible for finding and parsing Runtime-specific manifest files.
|
||||||
|
class RuntimeManifestFile : public ManifestFile {
|
||||||
|
public:
|
||||||
|
// Factory method
|
||||||
|
static XrResult FindManifestFiles(ManifestFileType type, std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files);
|
||||||
|
|
||||||
|
RuntimeManifestFile(const std::string &filename, const std::string &library_path);
|
||||||
|
~RuntimeManifestFile() override;
|
||||||
|
static void CreateIfValid(const std::string &filename, std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files);
|
||||||
|
|
||||||
|
// Non-copyable
|
||||||
|
RuntimeManifestFile(const RuntimeManifestFile &) = delete;
|
||||||
|
RuntimeManifestFile &operator=(const RuntimeManifestFile &) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ApiLayerManifestFile class -
|
||||||
|
// Responsible for finding and parsing API Layer-specific manifest files.
|
||||||
|
class ApiLayerManifestFile : public ManifestFile {
|
||||||
|
public:
|
||||||
|
// Factory method
|
||||||
|
static XrResult FindManifestFiles(ManifestFileType type, std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files);
|
||||||
|
|
||||||
|
ApiLayerManifestFile(ManifestFileType type, const std::string &filename, const std::string &layer_name,
|
||||||
|
const std::string &description, const JsonVersion &api_version, const uint32_t &implementation_version,
|
||||||
|
const std::string &library_path);
|
||||||
|
~ApiLayerManifestFile() override;
|
||||||
|
static void CreateIfValid(ManifestFileType type, const std::string &filename,
|
||||||
|
std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files);
|
||||||
|
|
||||||
|
std::string LayerName() { return _layer_name; }
|
||||||
|
XrApiLayerProperties GetApiLayerProperties();
|
||||||
|
|
||||||
|
// Non-copyable
|
||||||
|
ApiLayerManifestFile(const ApiLayerManifestFile &) = delete;
|
||||||
|
ApiLayerManifestFile &operator=(const ApiLayerManifestFile &) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
JsonVersion _api_version;
|
||||||
|
std::string _layer_name;
|
||||||
|
std::string _description;
|
||||||
|
uint32_t _implementation_version;
|
||||||
|
};
|
||||||
11
extern/openxr/src/loader/openxr.pc.in
vendored
Normal file
11
extern/openxr/src/loader/openxr.pc.in
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
prefix=@CMAKE_INSTALL_PREFIX@
|
||||||
|
exec_prefix=@CMAKE_INSTALL_PREFIX@
|
||||||
|
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
|
||||||
|
includedir=${prefix}/include
|
||||||
|
|
||||||
|
Name: @CMAKE_PROJECT_NAME@
|
||||||
|
Description: OpenXR Loader
|
||||||
|
Version: @XR_API_VERSION@
|
||||||
|
Libs: -L${libdir} -lopenxr_loader @PRIVATE_LIBS@
|
||||||
|
Cflags: -I${includedir}
|
||||||
|
|
||||||
342
extern/openxr/src/loader/runtime_interface.cpp
vendored
Normal file
342
extern/openxr/src/loader/runtime_interface.cpp
vendored
Normal file
@@ -0,0 +1,342 @@
|
|||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "runtime_interface.hpp"
|
||||||
|
|
||||||
|
#include "manifest_file.hpp"
|
||||||
|
#include "loader_interfaces.h"
|
||||||
|
#include "loader_logger.hpp"
|
||||||
|
#include "loader_platform.hpp"
|
||||||
|
#include "xr_generated_dispatch_table.h"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
std::unique_ptr<RuntimeInterface> RuntimeInterface::_single_runtime_interface;
|
||||||
|
uint32_t RuntimeInterface::_single_runtime_count = 0;
|
||||||
|
|
||||||
|
XrResult RuntimeInterface::LoadRuntime(const std::string& openxr_command) {
|
||||||
|
XrResult last_error = XR_SUCCESS;
|
||||||
|
bool any_loaded = false;
|
||||||
|
|
||||||
|
// If something's already loaded, we're done here.
|
||||||
|
if (_single_runtime_interface != nullptr) {
|
||||||
|
_single_runtime_count++;
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<RuntimeManifestFile>> runtime_manifest_files = {};
|
||||||
|
|
||||||
|
// Find the available runtimes which we may need to report information for.
|
||||||
|
last_error = RuntimeManifestFile::FindManifestFiles(MANIFEST_TYPE_RUNTIME, runtime_manifest_files);
|
||||||
|
if (XR_SUCCESS != last_error) {
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command, "RuntimeInterface::LoadRuntimes - unknown error");
|
||||||
|
last_error = XR_ERROR_FILE_ACCESS_ERROR;
|
||||||
|
} else {
|
||||||
|
for (std::unique_ptr<RuntimeManifestFile>& manifest_file : runtime_manifest_files) {
|
||||||
|
LoaderPlatformLibraryHandle runtime_library = LoaderPlatformLibraryOpen(manifest_file->LibraryPath());
|
||||||
|
if (nullptr == runtime_library) {
|
||||||
|
if (!any_loaded) {
|
||||||
|
last_error = XR_ERROR_INSTANCE_LOST;
|
||||||
|
}
|
||||||
|
std::string library_message = LoaderPlatformLibraryOpenError(manifest_file->LibraryPath());
|
||||||
|
std::string warning_message = "RuntimeInterface::LoadRuntime skipping manifest file ";
|
||||||
|
warning_message += manifest_file->Filename();
|
||||||
|
warning_message += ", failed to load with message \"";
|
||||||
|
warning_message += library_message;
|
||||||
|
warning_message += "\"";
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command, warning_message);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get and settle on an runtime interface version (using any provided name if required).
|
||||||
|
std::string function_name = manifest_file->GetFunctionName("xrNegotiateLoaderRuntimeInterface");
|
||||||
|
auto negotiate = reinterpret_cast<PFN_xrNegotiateLoaderRuntimeInterface>(
|
||||||
|
LoaderPlatformLibraryGetProcAddr(runtime_library, function_name));
|
||||||
|
|
||||||
|
// Loader info for negotiation
|
||||||
|
XrNegotiateLoaderInfo loader_info = {};
|
||||||
|
loader_info.structType = XR_LOADER_INTERFACE_STRUCT_LOADER_INFO;
|
||||||
|
loader_info.structVersion = XR_LOADER_INFO_STRUCT_VERSION;
|
||||||
|
loader_info.structSize = sizeof(XrNegotiateLoaderInfo);
|
||||||
|
loader_info.minInterfaceVersion = 1;
|
||||||
|
loader_info.maxInterfaceVersion = XR_CURRENT_LOADER_RUNTIME_VERSION;
|
||||||
|
loader_info.minApiVersion = XR_MAKE_VERSION(1, 0, 0);
|
||||||
|
loader_info.maxApiVersion = XR_MAKE_VERSION(1, 0x3ff, 0xfff); // Maximum allowed version for this major version.
|
||||||
|
|
||||||
|
// Set up the runtime return structure
|
||||||
|
XrNegotiateRuntimeRequest runtime_info = {};
|
||||||
|
runtime_info.structType = XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST;
|
||||||
|
runtime_info.structVersion = XR_RUNTIME_INFO_STRUCT_VERSION;
|
||||||
|
runtime_info.structSize = sizeof(XrNegotiateRuntimeRequest);
|
||||||
|
|
||||||
|
// Skip calling the negotiate function and fail if the function pointer
|
||||||
|
// could not get loaded
|
||||||
|
XrResult res = XR_ERROR_RUNTIME_FAILURE;
|
||||||
|
if (nullptr != negotiate) {
|
||||||
|
res = negotiate(&loader_info, &runtime_info);
|
||||||
|
}
|
||||||
|
// If we supposedly succeeded, but got a nullptr for GetInstanceProcAddr
|
||||||
|
// then something still went wrong, so return with an error.
|
||||||
|
if (XR_SUCCESS == res) {
|
||||||
|
uint32_t runtime_major = XR_VERSION_MAJOR(runtime_info.runtimeApiVersion);
|
||||||
|
uint32_t runtime_minor = XR_VERSION_MINOR(runtime_info.runtimeApiVersion);
|
||||||
|
uint32_t loader_major = XR_VERSION_MAJOR(XR_CURRENT_API_VERSION);
|
||||||
|
if (nullptr == runtime_info.getInstanceProcAddr) {
|
||||||
|
std::string error_message = "RuntimeInterface::LoadRuntime skipping manifest file ";
|
||||||
|
error_message += manifest_file->Filename();
|
||||||
|
error_message += ", negotiation succeeded but returned NULL getInstanceProcAddr";
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command, error_message);
|
||||||
|
res = XR_ERROR_FILE_CONTENTS_INVALID;
|
||||||
|
} else if (0 >= runtime_info.runtimeInterfaceVersion ||
|
||||||
|
XR_CURRENT_LOADER_RUNTIME_VERSION < runtime_info.runtimeInterfaceVersion) {
|
||||||
|
std::string error_message = "RuntimeInterface::LoadRuntime skipping manifest file ";
|
||||||
|
error_message += manifest_file->Filename();
|
||||||
|
error_message += ", negotiation succeeded but returned invalid interface version";
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command, error_message);
|
||||||
|
res = XR_ERROR_FILE_CONTENTS_INVALID;
|
||||||
|
} else if (runtime_major != loader_major || (runtime_major == 0 && runtime_minor == 0)) {
|
||||||
|
std::string error_message = "RuntimeInterface::LoadRuntime skipping manifest file ";
|
||||||
|
error_message += manifest_file->Filename();
|
||||||
|
error_message += ", OpenXR version returned not compatible with this loader";
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command, error_message);
|
||||||
|
res = XR_ERROR_FILE_CONTENTS_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (XR_SUCCESS != res) {
|
||||||
|
if (!any_loaded) {
|
||||||
|
last_error = res;
|
||||||
|
}
|
||||||
|
std::string warning_message = "RuntimeInterface::LoadRuntime skipping manifest file ";
|
||||||
|
warning_message += manifest_file->Filename();
|
||||||
|
warning_message += ", negotiation failed with error ";
|
||||||
|
warning_message += std::to_string(res);
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command, warning_message);
|
||||||
|
LoaderPlatformLibraryClose(runtime_library);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string info_message = "RuntimeInterface::LoadRuntime succeeded loading runtime defined in manifest file ";
|
||||||
|
info_message += manifest_file->Filename();
|
||||||
|
info_message += " using interface version ";
|
||||||
|
info_message += std::to_string(runtime_info.runtimeInterfaceVersion);
|
||||||
|
info_message += " and OpenXR API version ";
|
||||||
|
info_message += std::to_string(XR_VERSION_MAJOR(runtime_info.runtimeApiVersion));
|
||||||
|
info_message += ".";
|
||||||
|
info_message += std::to_string(XR_VERSION_MINOR(runtime_info.runtimeApiVersion));
|
||||||
|
LoaderLogger::LogInfoMessage(openxr_command, info_message);
|
||||||
|
|
||||||
|
// Use this runtime
|
||||||
|
_single_runtime_interface.reset(new RuntimeInterface(runtime_library, runtime_info.getInstanceProcAddr));
|
||||||
|
_single_runtime_count++;
|
||||||
|
|
||||||
|
// Grab the list of extensions this runtime supports for easy filtering after the
|
||||||
|
// xrCreateInstance call
|
||||||
|
std::vector<std::string> supported_extensions;
|
||||||
|
std::vector<XrExtensionProperties> extension_properties;
|
||||||
|
_single_runtime_interface->GetInstanceExtensionProperties(extension_properties);
|
||||||
|
supported_extensions.reserve(extension_properties.size());
|
||||||
|
for (XrExtensionProperties ext_prop : extension_properties) {
|
||||||
|
supported_extensions.emplace_back(ext_prop.extensionName);
|
||||||
|
}
|
||||||
|
_single_runtime_interface->SetSupportedExtensions(supported_extensions);
|
||||||
|
|
||||||
|
// If we load one, clear all errors.
|
||||||
|
any_loaded = true;
|
||||||
|
last_error = XR_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always clear the manifest file list. Either we use them or we don't.
|
||||||
|
runtime_manifest_files.clear();
|
||||||
|
|
||||||
|
// We found no valid runtimes, throw the initialization failed message
|
||||||
|
if (!any_loaded) {
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command, "RuntimeInterface::LoadRuntimes - failed to find a valid runtime");
|
||||||
|
last_error = XR_ERROR_INSTANCE_LOST;
|
||||||
|
}
|
||||||
|
|
||||||
|
return last_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuntimeInterface::UnloadRuntime(const std::string& openxr_command) {
|
||||||
|
if (_single_runtime_count == 1) {
|
||||||
|
_single_runtime_count = 0;
|
||||||
|
_single_runtime_interface.reset();
|
||||||
|
} else if (_single_runtime_count > 0) {
|
||||||
|
--_single_runtime_count;
|
||||||
|
}
|
||||||
|
LoaderLogger::LogInfoMessage(openxr_command, "RuntimeInterface being unloaded.");
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult RuntimeInterface::GetInstanceProcAddr(XrInstance instance, const char* name, PFN_xrVoidFunction* function) {
|
||||||
|
return _single_runtime_interface->_get_instant_proc_addr(instance, name, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
const XrGeneratedDispatchTable* RuntimeInterface::GetDispatchTable(XrInstance instance) {
|
||||||
|
XrGeneratedDispatchTable* table = nullptr;
|
||||||
|
std::lock_guard<std::mutex> mlock(_single_runtime_interface->_dispatch_table_mutex);
|
||||||
|
auto it = _single_runtime_interface->_dispatch_table_map.find(instance);
|
||||||
|
if (it != _single_runtime_interface->_dispatch_table_map.end()) {
|
||||||
|
table = it->second.get();
|
||||||
|
}
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
const XrGeneratedDispatchTable* RuntimeInterface::GetDebugUtilsMessengerDispatchTable(XrDebugUtilsMessengerEXT messenger) {
|
||||||
|
XrInstance runtime_instance = XR_NULL_HANDLE;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> mlock(_single_runtime_interface->_messenger_to_instance_mutex);
|
||||||
|
auto it = _single_runtime_interface->_messenger_to_instance_map.find(messenger);
|
||||||
|
if (it != _single_runtime_interface->_messenger_to_instance_map.end()) {
|
||||||
|
runtime_instance = it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return GetDispatchTable(runtime_instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
RuntimeInterface::RuntimeInterface(LoaderPlatformLibraryHandle runtime_library, PFN_xrGetInstanceProcAddr get_instant_proc_addr)
|
||||||
|
: _runtime_library(runtime_library), _get_instant_proc_addr(get_instant_proc_addr) {}
|
||||||
|
|
||||||
|
RuntimeInterface::~RuntimeInterface() {
|
||||||
|
std::string info_message = "RuntimeInterface being destroyed.";
|
||||||
|
LoaderLogger::LogInfoMessage("", info_message);
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> mlock(_dispatch_table_mutex);
|
||||||
|
_dispatch_table_map.clear();
|
||||||
|
}
|
||||||
|
LoaderPlatformLibraryClose(_runtime_library);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuntimeInterface::GetInstanceExtensionProperties(std::vector<XrExtensionProperties>& extension_properties) {
|
||||||
|
std::vector<XrExtensionProperties> runtime_extension_properties;
|
||||||
|
PFN_xrEnumerateInstanceExtensionProperties rt_xrEnumerateInstanceExtensionProperties;
|
||||||
|
_get_instant_proc_addr(XR_NULL_HANDLE, "xrEnumerateInstanceExtensionProperties",
|
||||||
|
reinterpret_cast<PFN_xrVoidFunction*>(&rt_xrEnumerateInstanceExtensionProperties));
|
||||||
|
uint32_t count = 0;
|
||||||
|
uint32_t count_output = 0;
|
||||||
|
// Get the count from the runtime
|
||||||
|
rt_xrEnumerateInstanceExtensionProperties(nullptr, count, &count_output, nullptr);
|
||||||
|
if (count_output > 0) {
|
||||||
|
runtime_extension_properties.resize(count_output);
|
||||||
|
count = count_output;
|
||||||
|
for (XrExtensionProperties& ext_prop : runtime_extension_properties) {
|
||||||
|
ext_prop.type = XR_TYPE_EXTENSION_PROPERTIES;
|
||||||
|
ext_prop.next = nullptr;
|
||||||
|
}
|
||||||
|
rt_xrEnumerateInstanceExtensionProperties(nullptr, count, &count_output, runtime_extension_properties.data());
|
||||||
|
}
|
||||||
|
size_t ext_count = runtime_extension_properties.size();
|
||||||
|
size_t props_count = extension_properties.size();
|
||||||
|
for (size_t ext = 0; ext < ext_count; ++ext) {
|
||||||
|
bool found = false;
|
||||||
|
for (size_t prop = 0; prop < props_count; ++prop) {
|
||||||
|
// If we find it, then make sure the spec version matches that of the runtime instead of the
|
||||||
|
// layer.
|
||||||
|
if (strcmp(extension_properties[prop].extensionName, runtime_extension_properties[ext].extensionName) == 0) {
|
||||||
|
// Make sure the spec version used is the runtime's
|
||||||
|
extension_properties[prop].extensionVersion = runtime_extension_properties[ext].extensionVersion;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
extension_properties.push_back(runtime_extension_properties[ext]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult RuntimeInterface::CreateInstance(const XrInstanceCreateInfo* info, XrInstance* instance) {
|
||||||
|
XrResult res = XR_SUCCESS;
|
||||||
|
bool create_succeeded = false;
|
||||||
|
PFN_xrCreateInstance rt_xrCreateInstance;
|
||||||
|
_get_instant_proc_addr(XR_NULL_HANDLE, "xrCreateInstance", reinterpret_cast<PFN_xrVoidFunction*>(&rt_xrCreateInstance));
|
||||||
|
res = rt_xrCreateInstance(info, instance);
|
||||||
|
if (XR_SUCCESS == res) {
|
||||||
|
create_succeeded = true;
|
||||||
|
std::unique_ptr<XrGeneratedDispatchTable> dispatch_table(new XrGeneratedDispatchTable());
|
||||||
|
GeneratedXrPopulateDispatchTable(dispatch_table.get(), *instance, _get_instant_proc_addr);
|
||||||
|
std::lock_guard<std::mutex> mlock(_dispatch_table_mutex);
|
||||||
|
_dispatch_table_map[*instance] = std::move(dispatch_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the failure occurred during the populate, clean up the instance we had picked up from the runtime
|
||||||
|
if (XR_SUCCESS != res && create_succeeded) {
|
||||||
|
PFN_xrDestroyInstance rt_xrDestroyInstance;
|
||||||
|
_get_instant_proc_addr(*instance, "xrDestroyInstance", reinterpret_cast<PFN_xrVoidFunction*>(&rt_xrDestroyInstance));
|
||||||
|
rt_xrDestroyInstance(*instance);
|
||||||
|
*instance = XR_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult RuntimeInterface::DestroyInstance(XrInstance instance) {
|
||||||
|
if (XR_NULL_HANDLE != instance) {
|
||||||
|
// Destroy the dispatch table for this instance first
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> mlock(_dispatch_table_mutex);
|
||||||
|
auto map_iter = _dispatch_table_map.find(instance);
|
||||||
|
if (map_iter != _dispatch_table_map.end()) {
|
||||||
|
_dispatch_table_map.erase(map_iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Now delete the instance
|
||||||
|
PFN_xrDestroyInstance rt_xrDestroyInstance;
|
||||||
|
_get_instant_proc_addr(instance, "xrDestroyInstance", reinterpret_cast<PFN_xrVoidFunction*>(&rt_xrDestroyInstance));
|
||||||
|
rt_xrDestroyInstance(instance);
|
||||||
|
}
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RuntimeInterface::TrackDebugMessenger(XrInstance instance, XrDebugUtilsMessengerEXT messenger) {
|
||||||
|
std::lock_guard<std::mutex> mlock(_messenger_to_instance_mutex);
|
||||||
|
_messenger_to_instance_map[messenger] = instance;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuntimeInterface::ForgetDebugMessenger(XrDebugUtilsMessengerEXT messenger) {
|
||||||
|
if (XR_NULL_HANDLE != messenger) {
|
||||||
|
std::lock_guard<std::mutex> mlock(_messenger_to_instance_mutex);
|
||||||
|
_messenger_to_instance_map.erase(messenger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuntimeInterface::SetSupportedExtensions(std::vector<std::string>& supported_extensions) {
|
||||||
|
_supported_extensions = supported_extensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RuntimeInterface::SupportsExtension(const std::string& extension_name) {
|
||||||
|
bool found_prop = false;
|
||||||
|
for (const std::string& supported_extension : _supported_extensions) {
|
||||||
|
if (supported_extension == extension_name) {
|
||||||
|
found_prop = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found_prop;
|
||||||
|
}
|
||||||
73
extern/openxr/src/loader/runtime_interface.hpp
vendored
Normal file
73
extern/openxr/src/loader/runtime_interface.hpp
vendored
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "loader_platform.hpp"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <mutex>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
struct XrGeneratedDispatchTable;
|
||||||
|
|
||||||
|
class RuntimeInterface {
|
||||||
|
public:
|
||||||
|
virtual ~RuntimeInterface();
|
||||||
|
|
||||||
|
// Helper functions for loading and unloading the runtime (but only when necessary)
|
||||||
|
static XrResult LoadRuntime(const std::string& openxr_command);
|
||||||
|
static void UnloadRuntime(const std::string& openxr_command);
|
||||||
|
static RuntimeInterface& GetRuntime() { return *(_single_runtime_interface.get()); }
|
||||||
|
static XrResult GetInstanceProcAddr(XrInstance instance, const char* name, PFN_xrVoidFunction* function);
|
||||||
|
static const XrGeneratedDispatchTable* GetDispatchTable(XrInstance instance);
|
||||||
|
static const XrGeneratedDispatchTable* GetDebugUtilsMessengerDispatchTable(XrDebugUtilsMessengerEXT messenger);
|
||||||
|
|
||||||
|
void GetInstanceExtensionProperties(std::vector<XrExtensionProperties>& extension_properties);
|
||||||
|
bool SupportsExtension(const std::string& extension_name);
|
||||||
|
XrResult CreateInstance(const XrInstanceCreateInfo* info, XrInstance* instance);
|
||||||
|
XrResult DestroyInstance(XrInstance instance);
|
||||||
|
bool TrackDebugMessenger(XrInstance instance, XrDebugUtilsMessengerEXT messenger);
|
||||||
|
void ForgetDebugMessenger(XrDebugUtilsMessengerEXT messenger);
|
||||||
|
|
||||||
|
// No default construction
|
||||||
|
RuntimeInterface() = delete;
|
||||||
|
|
||||||
|
// Non-copyable
|
||||||
|
RuntimeInterface(const RuntimeInterface&) = delete;
|
||||||
|
RuntimeInterface& operator=(const RuntimeInterface&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
RuntimeInterface(LoaderPlatformLibraryHandle runtime_library, PFN_xrGetInstanceProcAddr get_instant_proc_addr);
|
||||||
|
void SetSupportedExtensions(std::vector<std::string>& supported_extensions);
|
||||||
|
|
||||||
|
static std::unique_ptr<RuntimeInterface> _single_runtime_interface;
|
||||||
|
static uint32_t _single_runtime_count;
|
||||||
|
LoaderPlatformLibraryHandle _runtime_library;
|
||||||
|
PFN_xrGetInstanceProcAddr _get_instant_proc_addr;
|
||||||
|
std::unordered_map<XrInstance, std::unique_ptr<XrGeneratedDispatchTable>> _dispatch_table_map;
|
||||||
|
std::mutex _dispatch_table_mutex;
|
||||||
|
std::unordered_map<XrDebugUtilsMessengerEXT, XrInstance> _messenger_to_instance_map;
|
||||||
|
std::mutex _messenger_to_instance_mutex;
|
||||||
|
std::vector<std::string> _supported_extensions;
|
||||||
|
};
|
||||||
2568
extern/openxr/src/loader/xr_generated_loader.cpp
vendored
Normal file
2568
extern/openxr/src/loader/xr_generated_loader.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
307
extern/openxr/src/loader/xr_generated_loader.hpp
vendored
Normal file
307
extern/openxr/src/loader/xr_generated_loader.hpp
vendored
Normal file
@@ -0,0 +1,307 @@
|
|||||||
|
// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
|
||||||
|
// See loader_source_generator.py for modifications
|
||||||
|
// ************************************************************
|
||||||
|
|
||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "xr_dependencies.h"
|
||||||
|
#include "openxr/openxr.h"
|
||||||
|
#include "openxr/openxr_platform.h"
|
||||||
|
|
||||||
|
#include "loader_interfaces.h"
|
||||||
|
|
||||||
|
#include "loader_instance.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Loader manually generated function prototypes
|
||||||
|
|
||||||
|
|
||||||
|
// ---- Core 1.0 loader manual functions
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetInstanceProcAddr(
|
||||||
|
XrInstance instance,
|
||||||
|
const char* name,
|
||||||
|
PFN_xrVoidFunction* function);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermGetInstanceProcAddr(
|
||||||
|
XrInstance instance,
|
||||||
|
const char* name,
|
||||||
|
PFN_xrVoidFunction* function);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateApiLayerProperties(
|
||||||
|
uint32_t propertyCapacityInput,
|
||||||
|
uint32_t* propertyCountOutput,
|
||||||
|
XrApiLayerProperties* properties);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateInstanceExtensionProperties(
|
||||||
|
const char* layerName,
|
||||||
|
uint32_t propertyCapacityInput,
|
||||||
|
uint32_t* propertyCountOutput,
|
||||||
|
XrExtensionProperties* properties);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrCreateInstance(
|
||||||
|
const XrInstanceCreateInfo* createInfo,
|
||||||
|
XrInstance* instance);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateInstance(
|
||||||
|
const XrInstanceCreateInfo* createInfo,
|
||||||
|
XrInstance* instance);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrDestroyInstance(
|
||||||
|
XrInstance instance);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyInstance(
|
||||||
|
XrInstance instance);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetInstanceProperties(
|
||||||
|
XrInstance instance,
|
||||||
|
XrInstanceProperties* instanceProperties);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrPollEvent(
|
||||||
|
XrInstance instance,
|
||||||
|
XrEventDataBuffer* eventData);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrResultToString(
|
||||||
|
XrInstance instance,
|
||||||
|
XrResult value,
|
||||||
|
char buffer[XR_MAX_RESULT_STRING_SIZE]);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrStructureTypeToString(
|
||||||
|
XrInstance instance,
|
||||||
|
XrStructureType value,
|
||||||
|
char buffer[XR_MAX_STRUCTURE_NAME_SIZE]);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetSystem(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrSystemGetInfo* getInfo,
|
||||||
|
XrSystemId* systemId);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetSystemProperties(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrSystemProperties* properties);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateEnvironmentBlendModes(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrViewConfigurationType viewConfigurationType,
|
||||||
|
uint32_t environmentBlendModeCapacityInput,
|
||||||
|
uint32_t* environmentBlendModeCountOutput,
|
||||||
|
XrEnvironmentBlendMode* environmentBlendModes);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrCreateSession(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrSessionCreateInfo* createInfo,
|
||||||
|
XrSession* session);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViewConfigurations(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
uint32_t viewConfigurationTypeCapacityInput,
|
||||||
|
uint32_t* viewConfigurationTypeCountOutput,
|
||||||
|
XrViewConfigurationType* viewConfigurationTypes);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetViewConfigurationProperties(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrViewConfigurationType viewConfigurationType,
|
||||||
|
XrViewConfigurationProperties* configurationProperties);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViewConfigurationViews(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrViewConfigurationType viewConfigurationType,
|
||||||
|
uint32_t viewCapacityInput,
|
||||||
|
uint32_t* viewCountOutput,
|
||||||
|
XrViewConfigurationView* views);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrStringToPath(
|
||||||
|
XrInstance instance,
|
||||||
|
const char* pathString,
|
||||||
|
XrPath* path);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrPathToString(
|
||||||
|
XrInstance instance,
|
||||||
|
XrPath path,
|
||||||
|
uint32_t bufferCapacityInput,
|
||||||
|
uint32_t* bufferCountOutput,
|
||||||
|
char* buffer);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrCreateActionSet(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrActionSetCreateInfo* createInfo,
|
||||||
|
XrActionSet* actionSet);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrSuggestInteractionProfileBindings(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrInteractionProfileSuggestedBinding* suggestedBindings);
|
||||||
|
|
||||||
|
// ---- XR_KHR_opengl_enable loader manual functions
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_OPENGL)
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLGraphicsRequirementsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrGraphicsRequirementsOpenGLKHR* graphicsRequirements);
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
|
||||||
|
|
||||||
|
// ---- XR_KHR_opengl_es_enable loader manual functions
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLESGraphicsRequirementsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements);
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
|
||||||
|
|
||||||
|
// ---- XR_KHR_vulkan_enable loader manual functions
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanInstanceExtensionsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
uint32_t bufferCapacityInput,
|
||||||
|
uint32_t* bufferCountOutput,
|
||||||
|
char* buffer);
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanDeviceExtensionsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
uint32_t bufferCapacityInput,
|
||||||
|
uint32_t* bufferCountOutput,
|
||||||
|
char* buffer);
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsDeviceKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
VkInstance vkInstance,
|
||||||
|
VkPhysicalDevice* vkPhysicalDevice);
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsRequirementsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
|
||||||
|
// ---- XR_KHR_D3D11_enable loader manual functions
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_D3D11)
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D11GraphicsRequirementsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrGraphicsRequirementsD3D11KHR* graphicsRequirements);
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_D3D11)
|
||||||
|
|
||||||
|
// ---- XR_KHR_D3D12_enable loader manual functions
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_D3D12)
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D12GraphicsRequirementsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrGraphicsRequirementsD3D12KHR* graphicsRequirements);
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_D3D12)
|
||||||
|
|
||||||
|
// ---- XR_KHR_win32_convert_performance_counter_time loader manual functions
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrConvertWin32PerformanceCounterToTimeKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
const LARGE_INTEGER* performanceCounter,
|
||||||
|
XrTime* time);
|
||||||
|
#endif // defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToWin32PerformanceCounterKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrTime time,
|
||||||
|
LARGE_INTEGER* performanceCounter);
|
||||||
|
#endif // defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
|
||||||
|
// ---- XR_KHR_convert_timespec_time loader manual functions
|
||||||
|
#if defined(XR_USE_TIMESPEC)
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimespecTimeToTimeKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
const struct timespec* timespecTime,
|
||||||
|
XrTime* time);
|
||||||
|
#endif // defined(XR_USE_TIMESPEC)
|
||||||
|
#if defined(XR_USE_TIMESPEC)
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToTimespecTimeKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrTime time,
|
||||||
|
struct timespec* timespecTime);
|
||||||
|
#endif // defined(XR_USE_TIMESPEC)
|
||||||
|
|
||||||
|
// ---- XR_EXT_debug_utils loader manual functions
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrSetDebugUtilsObjectNameEXT(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrDebugUtilsObjectNameInfoEXT* nameInfo);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermSetDebugUtilsObjectNameEXT(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrDebugUtilsObjectNameInfoEXT* nameInfo);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrCreateDebugUtilsMessengerEXT(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrDebugUtilsMessengerCreateInfoEXT* createInfo,
|
||||||
|
XrDebugUtilsMessengerEXT* messenger);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateDebugUtilsMessengerEXT(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrDebugUtilsMessengerCreateInfoEXT* createInfo,
|
||||||
|
XrDebugUtilsMessengerEXT* messenger);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrDestroyDebugUtilsMessengerEXT(
|
||||||
|
XrDebugUtilsMessengerEXT messenger);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyDebugUtilsMessengerEXT(
|
||||||
|
XrDebugUtilsMessengerEXT messenger);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrSubmitDebugUtilsMessageEXT(
|
||||||
|
XrInstance instance,
|
||||||
|
XrDebugUtilsMessageSeverityFlagsEXT messageSeverity,
|
||||||
|
XrDebugUtilsMessageTypeFlagsEXT messageTypes,
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT* callbackData);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermSubmitDebugUtilsMessageEXT(
|
||||||
|
XrInstance instance,
|
||||||
|
XrDebugUtilsMessageSeverityFlagsEXT messageSeverity,
|
||||||
|
XrDebugUtilsMessageTypeFlagsEXT messageTypes,
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT* callbackData);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrSessionBeginDebugUtilsLabelRegionEXT(
|
||||||
|
XrSession session,
|
||||||
|
const XrDebugUtilsLabelEXT* labelInfo);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrSessionEndDebugUtilsLabelRegionEXT(
|
||||||
|
XrSession session);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrSessionInsertDebugUtilsLabelEXT(
|
||||||
|
XrSession session,
|
||||||
|
const XrDebugUtilsLabelEXT* labelInfo);
|
||||||
|
|
||||||
|
// Special use function to handle creating API Layer information during xrCreateInstance
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateApiLayerInstance(const XrInstanceCreateInfo* info,
|
||||||
|
const struct XrApiLayerCreateInfo* apiLayerInfo,
|
||||||
|
XrInstance* instance);
|
||||||
|
|
||||||
|
|
||||||
|
// Generated loader terminator prototypes
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderGenTermXrResultToString(
|
||||||
|
XrInstance instance,
|
||||||
|
XrResult value,
|
||||||
|
char buffer[XR_MAX_RESULT_STRING_SIZE]);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderGenTermXrStructureTypeToString(
|
||||||
|
XrInstance instance,
|
||||||
|
XrStructureType value,
|
||||||
|
char buffer[XR_MAX_STRUCTURE_NAME_SIZE]);
|
||||||
|
// Instance Init Dispatch Table (put all terminators in first)
|
||||||
|
void LoaderGenInitInstanceDispatchTable(XrInstance runtime_instance,
|
||||||
|
std::unique_ptr<XrGeneratedDispatchTable>& table);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Unordered maps and mutexes to lookup the instance for a given object type
|
||||||
|
extern HandleLoaderMap<XrInstance> g_instance_map;
|
||||||
|
extern HandleLoaderMap<XrSession> g_session_map;
|
||||||
|
extern HandleLoaderMap<XrSpace> g_space_map;
|
||||||
|
extern HandleLoaderMap<XrAction> g_action_map;
|
||||||
|
extern HandleLoaderMap<XrSwapchain> g_swapchain_map;
|
||||||
|
extern HandleLoaderMap<XrActionSet> g_actionset_map;
|
||||||
|
extern HandleLoaderMap<XrDebugUtilsMessengerEXT> g_debugutilsmessengerext_map;
|
||||||
|
|
||||||
|
// Function used to clean up any residual map values that point to an instance prior to that
|
||||||
|
// instance being deleted.
|
||||||
|
void LoaderCleanUpMapsForInstance(LoaderInstance *instance);
|
||||||
|
|
||||||
|
|
||||||
41
extern/openxr/src/version.cmake
vendored
Normal file
41
extern/openxr/src/version.cmake
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
# Set up the OpenXR version variables, used by several targets in this project.
|
||||||
|
set(MAJOR "0")
|
||||||
|
set(MINOR "0")
|
||||||
|
set(PATCH "0")
|
||||||
|
|
||||||
|
if(EXISTS "${OPENXR_ROOT_DIR}/specification/registry/xr.xml")
|
||||||
|
file(STRINGS ${OPENXR_ROOT_DIR}/specification/registry/xr.xml lines REGEX "#define <name>XR_CURRENT_API_VERSION")
|
||||||
|
else()
|
||||||
|
file(STRINGS ${OPENXR_ROOT_DIR}/include/openxr/openxr.h lines REGEX "#define XR_CURRENT_API_VERSION")
|
||||||
|
endif()
|
||||||
|
list(LENGTH lines len)
|
||||||
|
if(${len} EQUAL 1)
|
||||||
|
list(GET lines 0 cur_line)
|
||||||
|
# Erase everything up to the open parentheses
|
||||||
|
string(REGEX REPLACE "^[^\(]+" "" VERSION_BEFORE_ERASED ${cur_line})
|
||||||
|
# Erase everything after the close parentheses
|
||||||
|
string(REGEX REPLACE "[^\)]+$" "" VERSION_AFTER_ERASED ${VERSION_BEFORE_ERASED})
|
||||||
|
# Erase the parentheses
|
||||||
|
string(REPLACE "(" "" VERSION_AFTER_ERASED2 ${VERSION_AFTER_ERASED})
|
||||||
|
string(REPLACE ")" "" VERSION_AFTER_ERASED3 ${VERSION_AFTER_ERASED2})
|
||||||
|
string(REPLACE " " "" VERSION_AFTER_ERASED4 ${VERSION_AFTER_ERASED3})
|
||||||
|
string(REGEX REPLACE "^([0-9]+)\\,[0-9]+\\,[0-9]+" "\\1" MAJOR "${VERSION_AFTER_ERASED4}")
|
||||||
|
string(REGEX REPLACE "^[0-9]+\\,([0-9]+)\\,[0-9]+" "\\1" MINOR "${VERSION_AFTER_ERASED4}")
|
||||||
|
string(REGEX REPLACE "^[0-9]+\\,[0-9]+\\,([0-9]+)" "\\1" PATCH "${VERSION_AFTER_ERASED4}")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Unable to fetch major/minor version from registry or header")
|
||||||
|
endif()
|
||||||
175
extern/openxr/src/xr_generated_dispatch_table.c
vendored
Normal file
175
extern/openxr/src/xr_generated_dispatch_table.c
vendored
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
|
||||||
|
// See utility_source_generator.py for modifications
|
||||||
|
// ************************************************************
|
||||||
|
|
||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "xr_dependencies.h"
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
#include <openxr/openxr_platform.h>
|
||||||
|
|
||||||
|
#include "xr_generated_dispatch_table.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
// Helper function to populate an instance dispatch table
|
||||||
|
void GeneratedXrPopulateDispatchTable(struct XrGeneratedDispatchTable *table,
|
||||||
|
XrInstance instance,
|
||||||
|
PFN_xrGetInstanceProcAddr get_inst_proc_addr) {
|
||||||
|
|
||||||
|
// ---- Core 1.0 commands
|
||||||
|
table->GetInstanceProcAddr = get_inst_proc_addr;
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateInstance", (PFN_xrVoidFunction*)&table->CreateInstance));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroyInstance", (PFN_xrVoidFunction*)&table->DestroyInstance));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetInstanceProperties", (PFN_xrVoidFunction*)&table->GetInstanceProperties));
|
||||||
|
(get_inst_proc_addr(instance, "xrPollEvent", (PFN_xrVoidFunction*)&table->PollEvent));
|
||||||
|
(get_inst_proc_addr(instance, "xrResultToString", (PFN_xrVoidFunction*)&table->ResultToString));
|
||||||
|
(get_inst_proc_addr(instance, "xrStructureTypeToString", (PFN_xrVoidFunction*)&table->StructureTypeToString));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetSystem", (PFN_xrVoidFunction*)&table->GetSystem));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetSystemProperties", (PFN_xrVoidFunction*)&table->GetSystemProperties));
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumerateEnvironmentBlendModes", (PFN_xrVoidFunction*)&table->EnumerateEnvironmentBlendModes));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateSession", (PFN_xrVoidFunction*)&table->CreateSession));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroySession", (PFN_xrVoidFunction*)&table->DestroySession));
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumerateReferenceSpaces", (PFN_xrVoidFunction*)&table->EnumerateReferenceSpaces));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateReferenceSpace", (PFN_xrVoidFunction*)&table->CreateReferenceSpace));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetReferenceSpaceBoundsRect", (PFN_xrVoidFunction*)&table->GetReferenceSpaceBoundsRect));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateActionSpace", (PFN_xrVoidFunction*)&table->CreateActionSpace));
|
||||||
|
(get_inst_proc_addr(instance, "xrLocateSpace", (PFN_xrVoidFunction*)&table->LocateSpace));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroySpace", (PFN_xrVoidFunction*)&table->DestroySpace));
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumerateViewConfigurations", (PFN_xrVoidFunction*)&table->EnumerateViewConfigurations));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetViewConfigurationProperties", (PFN_xrVoidFunction*)&table->GetViewConfigurationProperties));
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumerateViewConfigurationViews", (PFN_xrVoidFunction*)&table->EnumerateViewConfigurationViews));
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumerateSwapchainFormats", (PFN_xrVoidFunction*)&table->EnumerateSwapchainFormats));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateSwapchain", (PFN_xrVoidFunction*)&table->CreateSwapchain));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroySwapchain", (PFN_xrVoidFunction*)&table->DestroySwapchain));
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumerateSwapchainImages", (PFN_xrVoidFunction*)&table->EnumerateSwapchainImages));
|
||||||
|
(get_inst_proc_addr(instance, "xrAcquireSwapchainImage", (PFN_xrVoidFunction*)&table->AcquireSwapchainImage));
|
||||||
|
(get_inst_proc_addr(instance, "xrWaitSwapchainImage", (PFN_xrVoidFunction*)&table->WaitSwapchainImage));
|
||||||
|
(get_inst_proc_addr(instance, "xrReleaseSwapchainImage", (PFN_xrVoidFunction*)&table->ReleaseSwapchainImage));
|
||||||
|
(get_inst_proc_addr(instance, "xrBeginSession", (PFN_xrVoidFunction*)&table->BeginSession));
|
||||||
|
(get_inst_proc_addr(instance, "xrEndSession", (PFN_xrVoidFunction*)&table->EndSession));
|
||||||
|
(get_inst_proc_addr(instance, "xrRequestExitSession", (PFN_xrVoidFunction*)&table->RequestExitSession));
|
||||||
|
(get_inst_proc_addr(instance, "xrWaitFrame", (PFN_xrVoidFunction*)&table->WaitFrame));
|
||||||
|
(get_inst_proc_addr(instance, "xrBeginFrame", (PFN_xrVoidFunction*)&table->BeginFrame));
|
||||||
|
(get_inst_proc_addr(instance, "xrEndFrame", (PFN_xrVoidFunction*)&table->EndFrame));
|
||||||
|
(get_inst_proc_addr(instance, "xrLocateViews", (PFN_xrVoidFunction*)&table->LocateViews));
|
||||||
|
(get_inst_proc_addr(instance, "xrStringToPath", (PFN_xrVoidFunction*)&table->StringToPath));
|
||||||
|
(get_inst_proc_addr(instance, "xrPathToString", (PFN_xrVoidFunction*)&table->PathToString));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateActionSet", (PFN_xrVoidFunction*)&table->CreateActionSet));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroyActionSet", (PFN_xrVoidFunction*)&table->DestroyActionSet));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateAction", (PFN_xrVoidFunction*)&table->CreateAction));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroyAction", (PFN_xrVoidFunction*)&table->DestroyAction));
|
||||||
|
(get_inst_proc_addr(instance, "xrSuggestInteractionProfileBindings", (PFN_xrVoidFunction*)&table->SuggestInteractionProfileBindings));
|
||||||
|
(get_inst_proc_addr(instance, "xrAttachSessionActionSets", (PFN_xrVoidFunction*)&table->AttachSessionActionSets));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetCurrentInteractionProfile", (PFN_xrVoidFunction*)&table->GetCurrentInteractionProfile));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetActionStateBoolean", (PFN_xrVoidFunction*)&table->GetActionStateBoolean));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetActionStateFloat", (PFN_xrVoidFunction*)&table->GetActionStateFloat));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetActionStateVector2f", (PFN_xrVoidFunction*)&table->GetActionStateVector2f));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetActionStatePose", (PFN_xrVoidFunction*)&table->GetActionStatePose));
|
||||||
|
(get_inst_proc_addr(instance, "xrSyncActions", (PFN_xrVoidFunction*)&table->SyncActions));
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumerateBoundSourcesForAction", (PFN_xrVoidFunction*)&table->EnumerateBoundSourcesForAction));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetInputSourceLocalizedName", (PFN_xrVoidFunction*)&table->GetInputSourceLocalizedName));
|
||||||
|
(get_inst_proc_addr(instance, "xrApplyHapticFeedback", (PFN_xrVoidFunction*)&table->ApplyHapticFeedback));
|
||||||
|
(get_inst_proc_addr(instance, "xrStopHapticFeedback", (PFN_xrVoidFunction*)&table->StopHapticFeedback));
|
||||||
|
|
||||||
|
// ---- XR_KHR_android_thread_settings extension commands
|
||||||
|
#if defined(XR_USE_PLATFORM_ANDROID)
|
||||||
|
(get_inst_proc_addr(instance, "xrSetAndroidApplicationThreadKHR", (PFN_xrVoidFunction*)&table->SetAndroidApplicationThreadKHR));
|
||||||
|
#endif // defined(XR_USE_PLATFORM_ANDROID)
|
||||||
|
|
||||||
|
// ---- XR_KHR_android_surface_swapchain extension commands
|
||||||
|
#if defined(XR_USE_PLATFORM_ANDROID)
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateSwapchainAndroidSurfaceKHR", (PFN_xrVoidFunction*)&table->CreateSwapchainAndroidSurfaceKHR));
|
||||||
|
#endif // defined(XR_USE_PLATFORM_ANDROID)
|
||||||
|
|
||||||
|
// ---- XR_KHR_opengl_enable extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_OPENGL)
|
||||||
|
(get_inst_proc_addr(instance, "xrGetOpenGLGraphicsRequirementsKHR", (PFN_xrVoidFunction*)&table->GetOpenGLGraphicsRequirementsKHR));
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
|
||||||
|
|
||||||
|
// ---- XR_KHR_opengl_es_enable extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
|
||||||
|
(get_inst_proc_addr(instance, "xrGetOpenGLESGraphicsRequirementsKHR", (PFN_xrVoidFunction*)&table->GetOpenGLESGraphicsRequirementsKHR));
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
|
||||||
|
|
||||||
|
// ---- XR_KHR_vulkan_enable extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
(get_inst_proc_addr(instance, "xrGetVulkanInstanceExtensionsKHR", (PFN_xrVoidFunction*)&table->GetVulkanInstanceExtensionsKHR));
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
(get_inst_proc_addr(instance, "xrGetVulkanDeviceExtensionsKHR", (PFN_xrVoidFunction*)&table->GetVulkanDeviceExtensionsKHR));
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
(get_inst_proc_addr(instance, "xrGetVulkanGraphicsDeviceKHR", (PFN_xrVoidFunction*)&table->GetVulkanGraphicsDeviceKHR));
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
(get_inst_proc_addr(instance, "xrGetVulkanGraphicsRequirementsKHR", (PFN_xrVoidFunction*)&table->GetVulkanGraphicsRequirementsKHR));
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
|
||||||
|
// ---- XR_KHR_D3D11_enable extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_D3D11)
|
||||||
|
(get_inst_proc_addr(instance, "xrGetD3D11GraphicsRequirementsKHR", (PFN_xrVoidFunction*)&table->GetD3D11GraphicsRequirementsKHR));
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_D3D11)
|
||||||
|
|
||||||
|
// ---- XR_KHR_D3D12_enable extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_D3D12)
|
||||||
|
(get_inst_proc_addr(instance, "xrGetD3D12GraphicsRequirementsKHR", (PFN_xrVoidFunction*)&table->GetD3D12GraphicsRequirementsKHR));
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_D3D12)
|
||||||
|
|
||||||
|
// ---- XR_KHR_visibility_mask extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrGetVisibilityMaskKHR", (PFN_xrVoidFunction*)&table->GetVisibilityMaskKHR));
|
||||||
|
|
||||||
|
// ---- XR_KHR_win32_convert_performance_counter_time extension commands
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
(get_inst_proc_addr(instance, "xrConvertWin32PerformanceCounterToTimeKHR", (PFN_xrVoidFunction*)&table->ConvertWin32PerformanceCounterToTimeKHR));
|
||||||
|
#endif // defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
(get_inst_proc_addr(instance, "xrConvertTimeToWin32PerformanceCounterKHR", (PFN_xrVoidFunction*)&table->ConvertTimeToWin32PerformanceCounterKHR));
|
||||||
|
#endif // defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
|
||||||
|
// ---- XR_KHR_convert_timespec_time extension commands
|
||||||
|
#if defined(XR_USE_TIMESPEC)
|
||||||
|
(get_inst_proc_addr(instance, "xrConvertTimespecTimeToTimeKHR", (PFN_xrVoidFunction*)&table->ConvertTimespecTimeToTimeKHR));
|
||||||
|
#endif // defined(XR_USE_TIMESPEC)
|
||||||
|
#if defined(XR_USE_TIMESPEC)
|
||||||
|
(get_inst_proc_addr(instance, "xrConvertTimeToTimespecTimeKHR", (PFN_xrVoidFunction*)&table->ConvertTimeToTimespecTimeKHR));
|
||||||
|
#endif // defined(XR_USE_TIMESPEC)
|
||||||
|
|
||||||
|
// ---- XR_EXT_performance_settings extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrPerfSettingsSetPerformanceLevelEXT", (PFN_xrVoidFunction*)&table->PerfSettingsSetPerformanceLevelEXT));
|
||||||
|
|
||||||
|
// ---- XR_EXT_thermal_query extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrThermalGetTemperatureTrendEXT", (PFN_xrVoidFunction*)&table->ThermalGetTemperatureTrendEXT));
|
||||||
|
|
||||||
|
// ---- XR_EXT_debug_utils extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrSetDebugUtilsObjectNameEXT", (PFN_xrVoidFunction*)&table->SetDebugUtilsObjectNameEXT));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateDebugUtilsMessengerEXT", (PFN_xrVoidFunction*)&table->CreateDebugUtilsMessengerEXT));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroyDebugUtilsMessengerEXT", (PFN_xrVoidFunction*)&table->DestroyDebugUtilsMessengerEXT));
|
||||||
|
(get_inst_proc_addr(instance, "xrSubmitDebugUtilsMessageEXT", (PFN_xrVoidFunction*)&table->SubmitDebugUtilsMessageEXT));
|
||||||
|
(get_inst_proc_addr(instance, "xrSessionBeginDebugUtilsLabelRegionEXT", (PFN_xrVoidFunction*)&table->SessionBeginDebugUtilsLabelRegionEXT));
|
||||||
|
(get_inst_proc_addr(instance, "xrSessionEndDebugUtilsLabelRegionEXT", (PFN_xrVoidFunction*)&table->SessionEndDebugUtilsLabelRegionEXT));
|
||||||
|
(get_inst_proc_addr(instance, "xrSessionInsertDebugUtilsLabelEXT", (PFN_xrVoidFunction*)&table->SessionInsertDebugUtilsLabelEXT));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
181
extern/openxr/src/xr_generated_dispatch_table.h
vendored
Normal file
181
extern/openxr/src/xr_generated_dispatch_table.h
vendored
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
|
||||||
|
// See utility_source_generator.py for modifications
|
||||||
|
// ************************************************************
|
||||||
|
|
||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "xr_dependencies.h"
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
#include <openxr/openxr_platform.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
// Generated dispatch table
|
||||||
|
struct XrGeneratedDispatchTable {
|
||||||
|
|
||||||
|
// ---- Core 1.0 commands
|
||||||
|
PFN_xrGetInstanceProcAddr GetInstanceProcAddr;
|
||||||
|
PFN_xrEnumerateApiLayerProperties EnumerateApiLayerProperties;
|
||||||
|
PFN_xrEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
|
||||||
|
PFN_xrCreateInstance CreateInstance;
|
||||||
|
PFN_xrDestroyInstance DestroyInstance;
|
||||||
|
PFN_xrGetInstanceProperties GetInstanceProperties;
|
||||||
|
PFN_xrPollEvent PollEvent;
|
||||||
|
PFN_xrResultToString ResultToString;
|
||||||
|
PFN_xrStructureTypeToString StructureTypeToString;
|
||||||
|
PFN_xrGetSystem GetSystem;
|
||||||
|
PFN_xrGetSystemProperties GetSystemProperties;
|
||||||
|
PFN_xrEnumerateEnvironmentBlendModes EnumerateEnvironmentBlendModes;
|
||||||
|
PFN_xrCreateSession CreateSession;
|
||||||
|
PFN_xrDestroySession DestroySession;
|
||||||
|
PFN_xrEnumerateReferenceSpaces EnumerateReferenceSpaces;
|
||||||
|
PFN_xrCreateReferenceSpace CreateReferenceSpace;
|
||||||
|
PFN_xrGetReferenceSpaceBoundsRect GetReferenceSpaceBoundsRect;
|
||||||
|
PFN_xrCreateActionSpace CreateActionSpace;
|
||||||
|
PFN_xrLocateSpace LocateSpace;
|
||||||
|
PFN_xrDestroySpace DestroySpace;
|
||||||
|
PFN_xrEnumerateViewConfigurations EnumerateViewConfigurations;
|
||||||
|
PFN_xrGetViewConfigurationProperties GetViewConfigurationProperties;
|
||||||
|
PFN_xrEnumerateViewConfigurationViews EnumerateViewConfigurationViews;
|
||||||
|
PFN_xrEnumerateSwapchainFormats EnumerateSwapchainFormats;
|
||||||
|
PFN_xrCreateSwapchain CreateSwapchain;
|
||||||
|
PFN_xrDestroySwapchain DestroySwapchain;
|
||||||
|
PFN_xrEnumerateSwapchainImages EnumerateSwapchainImages;
|
||||||
|
PFN_xrAcquireSwapchainImage AcquireSwapchainImage;
|
||||||
|
PFN_xrWaitSwapchainImage WaitSwapchainImage;
|
||||||
|
PFN_xrReleaseSwapchainImage ReleaseSwapchainImage;
|
||||||
|
PFN_xrBeginSession BeginSession;
|
||||||
|
PFN_xrEndSession EndSession;
|
||||||
|
PFN_xrRequestExitSession RequestExitSession;
|
||||||
|
PFN_xrWaitFrame WaitFrame;
|
||||||
|
PFN_xrBeginFrame BeginFrame;
|
||||||
|
PFN_xrEndFrame EndFrame;
|
||||||
|
PFN_xrLocateViews LocateViews;
|
||||||
|
PFN_xrStringToPath StringToPath;
|
||||||
|
PFN_xrPathToString PathToString;
|
||||||
|
PFN_xrCreateActionSet CreateActionSet;
|
||||||
|
PFN_xrDestroyActionSet DestroyActionSet;
|
||||||
|
PFN_xrCreateAction CreateAction;
|
||||||
|
PFN_xrDestroyAction DestroyAction;
|
||||||
|
PFN_xrSuggestInteractionProfileBindings SuggestInteractionProfileBindings;
|
||||||
|
PFN_xrAttachSessionActionSets AttachSessionActionSets;
|
||||||
|
PFN_xrGetCurrentInteractionProfile GetCurrentInteractionProfile;
|
||||||
|
PFN_xrGetActionStateBoolean GetActionStateBoolean;
|
||||||
|
PFN_xrGetActionStateFloat GetActionStateFloat;
|
||||||
|
PFN_xrGetActionStateVector2f GetActionStateVector2f;
|
||||||
|
PFN_xrGetActionStatePose GetActionStatePose;
|
||||||
|
PFN_xrSyncActions SyncActions;
|
||||||
|
PFN_xrEnumerateBoundSourcesForAction EnumerateBoundSourcesForAction;
|
||||||
|
PFN_xrGetInputSourceLocalizedName GetInputSourceLocalizedName;
|
||||||
|
PFN_xrApplyHapticFeedback ApplyHapticFeedback;
|
||||||
|
PFN_xrStopHapticFeedback StopHapticFeedback;
|
||||||
|
|
||||||
|
// ---- XR_KHR_android_thread_settings extension commands
|
||||||
|
#if defined(XR_USE_PLATFORM_ANDROID)
|
||||||
|
PFN_xrSetAndroidApplicationThreadKHR SetAndroidApplicationThreadKHR;
|
||||||
|
#endif // defined(XR_USE_PLATFORM_ANDROID)
|
||||||
|
|
||||||
|
// ---- XR_KHR_android_surface_swapchain extension commands
|
||||||
|
#if defined(XR_USE_PLATFORM_ANDROID)
|
||||||
|
PFN_xrCreateSwapchainAndroidSurfaceKHR CreateSwapchainAndroidSurfaceKHR;
|
||||||
|
#endif // defined(XR_USE_PLATFORM_ANDROID)
|
||||||
|
|
||||||
|
// ---- XR_KHR_opengl_enable extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_OPENGL)
|
||||||
|
PFN_xrGetOpenGLGraphicsRequirementsKHR GetOpenGLGraphicsRequirementsKHR;
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
|
||||||
|
|
||||||
|
// ---- XR_KHR_opengl_es_enable extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
|
||||||
|
PFN_xrGetOpenGLESGraphicsRequirementsKHR GetOpenGLESGraphicsRequirementsKHR;
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
|
||||||
|
|
||||||
|
// ---- XR_KHR_vulkan_enable extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
PFN_xrGetVulkanInstanceExtensionsKHR GetVulkanInstanceExtensionsKHR;
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
PFN_xrGetVulkanDeviceExtensionsKHR GetVulkanDeviceExtensionsKHR;
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
PFN_xrGetVulkanGraphicsDeviceKHR GetVulkanGraphicsDeviceKHR;
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
PFN_xrGetVulkanGraphicsRequirementsKHR GetVulkanGraphicsRequirementsKHR;
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
|
||||||
|
// ---- XR_KHR_D3D11_enable extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_D3D11)
|
||||||
|
PFN_xrGetD3D11GraphicsRequirementsKHR GetD3D11GraphicsRequirementsKHR;
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_D3D11)
|
||||||
|
|
||||||
|
// ---- XR_KHR_D3D12_enable extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_D3D12)
|
||||||
|
PFN_xrGetD3D12GraphicsRequirementsKHR GetD3D12GraphicsRequirementsKHR;
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_D3D12)
|
||||||
|
|
||||||
|
// ---- XR_KHR_visibility_mask extension commands
|
||||||
|
PFN_xrGetVisibilityMaskKHR GetVisibilityMaskKHR;
|
||||||
|
|
||||||
|
// ---- XR_KHR_win32_convert_performance_counter_time extension commands
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
PFN_xrConvertWin32PerformanceCounterToTimeKHR ConvertWin32PerformanceCounterToTimeKHR;
|
||||||
|
#endif // defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
PFN_xrConvertTimeToWin32PerformanceCounterKHR ConvertTimeToWin32PerformanceCounterKHR;
|
||||||
|
#endif // defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
|
||||||
|
// ---- XR_KHR_convert_timespec_time extension commands
|
||||||
|
#if defined(XR_USE_TIMESPEC)
|
||||||
|
PFN_xrConvertTimespecTimeToTimeKHR ConvertTimespecTimeToTimeKHR;
|
||||||
|
#endif // defined(XR_USE_TIMESPEC)
|
||||||
|
#if defined(XR_USE_TIMESPEC)
|
||||||
|
PFN_xrConvertTimeToTimespecTimeKHR ConvertTimeToTimespecTimeKHR;
|
||||||
|
#endif // defined(XR_USE_TIMESPEC)
|
||||||
|
|
||||||
|
// ---- XR_EXT_performance_settings extension commands
|
||||||
|
PFN_xrPerfSettingsSetPerformanceLevelEXT PerfSettingsSetPerformanceLevelEXT;
|
||||||
|
|
||||||
|
// ---- XR_EXT_thermal_query extension commands
|
||||||
|
PFN_xrThermalGetTemperatureTrendEXT ThermalGetTemperatureTrendEXT;
|
||||||
|
|
||||||
|
// ---- XR_EXT_debug_utils extension commands
|
||||||
|
PFN_xrSetDebugUtilsObjectNameEXT SetDebugUtilsObjectNameEXT;
|
||||||
|
PFN_xrCreateDebugUtilsMessengerEXT CreateDebugUtilsMessengerEXT;
|
||||||
|
PFN_xrDestroyDebugUtilsMessengerEXT DestroyDebugUtilsMessengerEXT;
|
||||||
|
PFN_xrSubmitDebugUtilsMessageEXT SubmitDebugUtilsMessageEXT;
|
||||||
|
PFN_xrSessionBeginDebugUtilsLabelRegionEXT SessionBeginDebugUtilsLabelRegionEXT;
|
||||||
|
PFN_xrSessionEndDebugUtilsLabelRegionEXT SessionEndDebugUtilsLabelRegionEXT;
|
||||||
|
PFN_xrSessionInsertDebugUtilsLabelEXT SessionInsertDebugUtilsLabelEXT;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Prototype for dispatch table helper function
|
||||||
|
void GeneratedXrPopulateDispatchTable(struct XrGeneratedDispatchTable *table,
|
||||||
|
XrInstance instance,
|
||||||
|
PFN_xrGetInstanceProcAddr get_inst_proc_addr);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
488
extern/openxr/src/xr_generated_utilities.c
vendored
Normal file
488
extern/openxr/src/xr_generated_utilities.c
vendored
Normal file
@@ -0,0 +1,488 @@
|
|||||||
|
// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
|
||||||
|
// See utility_source_generator.py for modifications
|
||||||
|
// ************************************************************
|
||||||
|
|
||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// Disable Windows warning about using strncpy_s instead of strncpy
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS 1
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
|
#include "xr_generated_utilities.h"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
XrResult GeneratedXrUtilitiesResultToString(XrResult result,
|
||||||
|
char buffer[XR_MAX_RESULT_STRING_SIZE]) {
|
||||||
|
if (NULL == buffer) {
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
XrResult int_result = XR_SUCCESS;
|
||||||
|
switch (result) {
|
||||||
|
case XR_SUCCESS:
|
||||||
|
strncpy(buffer, "XR_SUCCESS", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TIMEOUT_EXPIRED:
|
||||||
|
strncpy(buffer, "XR_TIMEOUT_EXPIRED", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_SESSION_LOSS_PENDING:
|
||||||
|
strncpy(buffer, "XR_SESSION_LOSS_PENDING", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_EVENT_UNAVAILABLE:
|
||||||
|
strncpy(buffer, "XR_EVENT_UNAVAILABLE", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_SPACE_BOUNDS_UNAVAILABLE:
|
||||||
|
strncpy(buffer, "XR_SPACE_BOUNDS_UNAVAILABLE", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_SESSION_NOT_FOCUSED:
|
||||||
|
strncpy(buffer, "XR_SESSION_NOT_FOCUSED", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_FRAME_DISCARDED:
|
||||||
|
strncpy(buffer, "XR_FRAME_DISCARDED", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_VALIDATION_FAILURE:
|
||||||
|
strncpy(buffer, "XR_ERROR_VALIDATION_FAILURE", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_RUNTIME_FAILURE:
|
||||||
|
strncpy(buffer, "XR_ERROR_RUNTIME_FAILURE", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_OUT_OF_MEMORY:
|
||||||
|
strncpy(buffer, "XR_ERROR_OUT_OF_MEMORY", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_API_VERSION_UNSUPPORTED:
|
||||||
|
strncpy(buffer, "XR_ERROR_API_VERSION_UNSUPPORTED", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_INITIALIZATION_FAILED:
|
||||||
|
strncpy(buffer, "XR_ERROR_INITIALIZATION_FAILED", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_FUNCTION_UNSUPPORTED:
|
||||||
|
strncpy(buffer, "XR_ERROR_FUNCTION_UNSUPPORTED", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_FEATURE_UNSUPPORTED:
|
||||||
|
strncpy(buffer, "XR_ERROR_FEATURE_UNSUPPORTED", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_EXTENSION_NOT_PRESENT:
|
||||||
|
strncpy(buffer, "XR_ERROR_EXTENSION_NOT_PRESENT", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_LIMIT_REACHED:
|
||||||
|
strncpy(buffer, "XR_ERROR_LIMIT_REACHED", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_SIZE_INSUFFICIENT:
|
||||||
|
strncpy(buffer, "XR_ERROR_SIZE_INSUFFICIENT", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_HANDLE_INVALID:
|
||||||
|
strncpy(buffer, "XR_ERROR_HANDLE_INVALID", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_INSTANCE_LOST:
|
||||||
|
strncpy(buffer, "XR_ERROR_INSTANCE_LOST", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_SESSION_RUNNING:
|
||||||
|
strncpy(buffer, "XR_ERROR_SESSION_RUNNING", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_SESSION_NOT_RUNNING:
|
||||||
|
strncpy(buffer, "XR_ERROR_SESSION_NOT_RUNNING", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_SESSION_LOST:
|
||||||
|
strncpy(buffer, "XR_ERROR_SESSION_LOST", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_SYSTEM_INVALID:
|
||||||
|
strncpy(buffer, "XR_ERROR_SYSTEM_INVALID", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_PATH_INVALID:
|
||||||
|
strncpy(buffer, "XR_ERROR_PATH_INVALID", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_PATH_COUNT_EXCEEDED:
|
||||||
|
strncpy(buffer, "XR_ERROR_PATH_COUNT_EXCEEDED", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_PATH_FORMAT_INVALID:
|
||||||
|
strncpy(buffer, "XR_ERROR_PATH_FORMAT_INVALID", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_PATH_UNSUPPORTED:
|
||||||
|
strncpy(buffer, "XR_ERROR_PATH_UNSUPPORTED", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_LAYER_INVALID:
|
||||||
|
strncpy(buffer, "XR_ERROR_LAYER_INVALID", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_LAYER_LIMIT_EXCEEDED:
|
||||||
|
strncpy(buffer, "XR_ERROR_LAYER_LIMIT_EXCEEDED", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_SWAPCHAIN_RECT_INVALID:
|
||||||
|
strncpy(buffer, "XR_ERROR_SWAPCHAIN_RECT_INVALID", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED:
|
||||||
|
strncpy(buffer, "XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_ACTION_TYPE_MISMATCH:
|
||||||
|
strncpy(buffer, "XR_ERROR_ACTION_TYPE_MISMATCH", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_SESSION_NOT_READY:
|
||||||
|
strncpy(buffer, "XR_ERROR_SESSION_NOT_READY", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_SESSION_NOT_STOPPING:
|
||||||
|
strncpy(buffer, "XR_ERROR_SESSION_NOT_STOPPING", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_TIME_INVALID:
|
||||||
|
strncpy(buffer, "XR_ERROR_TIME_INVALID", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_REFERENCE_SPACE_UNSUPPORTED:
|
||||||
|
strncpy(buffer, "XR_ERROR_REFERENCE_SPACE_UNSUPPORTED", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_FILE_ACCESS_ERROR:
|
||||||
|
strncpy(buffer, "XR_ERROR_FILE_ACCESS_ERROR", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_FILE_CONTENTS_INVALID:
|
||||||
|
strncpy(buffer, "XR_ERROR_FILE_CONTENTS_INVALID", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_FORM_FACTOR_UNSUPPORTED:
|
||||||
|
strncpy(buffer, "XR_ERROR_FORM_FACTOR_UNSUPPORTED", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_FORM_FACTOR_UNAVAILABLE:
|
||||||
|
strncpy(buffer, "XR_ERROR_FORM_FACTOR_UNAVAILABLE", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_API_LAYER_NOT_PRESENT:
|
||||||
|
strncpy(buffer, "XR_ERROR_API_LAYER_NOT_PRESENT", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_CALL_ORDER_INVALID:
|
||||||
|
strncpy(buffer, "XR_ERROR_CALL_ORDER_INVALID", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_GRAPHICS_DEVICE_INVALID:
|
||||||
|
strncpy(buffer, "XR_ERROR_GRAPHICS_DEVICE_INVALID", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_POSE_INVALID:
|
||||||
|
strncpy(buffer, "XR_ERROR_POSE_INVALID", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_INDEX_OUT_OF_RANGE:
|
||||||
|
strncpy(buffer, "XR_ERROR_INDEX_OUT_OF_RANGE", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED:
|
||||||
|
strncpy(buffer, "XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED:
|
||||||
|
strncpy(buffer, "XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_NAME_DUPLICATED:
|
||||||
|
strncpy(buffer, "XR_ERROR_NAME_DUPLICATED", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_NAME_INVALID:
|
||||||
|
strncpy(buffer, "XR_ERROR_NAME_INVALID", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_ACTIONSET_NOT_ATTACHED:
|
||||||
|
strncpy(buffer, "XR_ERROR_ACTIONSET_NOT_ATTACHED", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_ACTIONSETS_ALREADY_ATTACHED:
|
||||||
|
strncpy(buffer, "XR_ERROR_ACTIONSETS_ALREADY_ATTACHED", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_LOCALIZED_NAME_DUPLICATED:
|
||||||
|
strncpy(buffer, "XR_ERROR_LOCALIZED_NAME_DUPLICATED", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_LOCALIZED_NAME_INVALID:
|
||||||
|
strncpy(buffer, "XR_ERROR_LOCALIZED_NAME_INVALID", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR:
|
||||||
|
strncpy(buffer, "XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR:
|
||||||
|
strncpy(buffer, "XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR", XR_MAX_RESULT_STRING_SIZE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Unknown result type
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
snprintf(buffer, XR_MAX_RESULT_STRING_SIZE, "XR_UNKNOWN_SUCCESS_%d", result);
|
||||||
|
} else {
|
||||||
|
snprintf(buffer, XR_MAX_RESULT_STRING_SIZE, "XR_UNKNOWN_FAILURE_%d", result);
|
||||||
|
}
|
||||||
|
int_result = XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return int_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult GeneratedXrUtilitiesStructureTypeToString(XrStructureType struct_type,
|
||||||
|
char buffer[XR_MAX_STRUCTURE_NAME_SIZE]) {
|
||||||
|
if (NULL == buffer) {
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
XrResult int_result = XR_SUCCESS;
|
||||||
|
switch (struct_type) {
|
||||||
|
case XR_TYPE_UNKNOWN:
|
||||||
|
strncpy(buffer, "XR_TYPE_UNKNOWN", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_API_LAYER_PROPERTIES:
|
||||||
|
strncpy(buffer, "XR_TYPE_API_LAYER_PROPERTIES", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_EXTENSION_PROPERTIES:
|
||||||
|
strncpy(buffer, "XR_TYPE_EXTENSION_PROPERTIES", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_INSTANCE_CREATE_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_INSTANCE_CREATE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_SYSTEM_GET_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_SYSTEM_GET_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_SYSTEM_PROPERTIES:
|
||||||
|
strncpy(buffer, "XR_TYPE_SYSTEM_PROPERTIES", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_VIEW_LOCATE_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_VIEW_LOCATE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_VIEW:
|
||||||
|
strncpy(buffer, "XR_TYPE_VIEW", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_SESSION_CREATE_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_SESSION_CREATE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_SWAPCHAIN_CREATE_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_SWAPCHAIN_CREATE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_SESSION_BEGIN_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_SESSION_BEGIN_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_VIEW_STATE:
|
||||||
|
strncpy(buffer, "XR_TYPE_VIEW_STATE", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_FRAME_END_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_FRAME_END_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_HAPTIC_VIBRATION:
|
||||||
|
strncpy(buffer, "XR_TYPE_HAPTIC_VIBRATION", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_EVENT_DATA_BUFFER:
|
||||||
|
strncpy(buffer, "XR_TYPE_EVENT_DATA_BUFFER", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING:
|
||||||
|
strncpy(buffer, "XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED:
|
||||||
|
strncpy(buffer, "XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_ACTION_STATE_BOOLEAN:
|
||||||
|
strncpy(buffer, "XR_TYPE_ACTION_STATE_BOOLEAN", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_ACTION_STATE_FLOAT:
|
||||||
|
strncpy(buffer, "XR_TYPE_ACTION_STATE_FLOAT", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_ACTION_STATE_VECTOR2F:
|
||||||
|
strncpy(buffer, "XR_TYPE_ACTION_STATE_VECTOR2F", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_ACTION_STATE_POSE:
|
||||||
|
strncpy(buffer, "XR_TYPE_ACTION_STATE_POSE", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_ACTION_SET_CREATE_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_ACTION_SET_CREATE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_ACTION_CREATE_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_ACTION_CREATE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_INSTANCE_PROPERTIES:
|
||||||
|
strncpy(buffer, "XR_TYPE_INSTANCE_PROPERTIES", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_FRAME_WAIT_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_FRAME_WAIT_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_COMPOSITION_LAYER_PROJECTION:
|
||||||
|
strncpy(buffer, "XR_TYPE_COMPOSITION_LAYER_PROJECTION", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_COMPOSITION_LAYER_QUAD:
|
||||||
|
strncpy(buffer, "XR_TYPE_COMPOSITION_LAYER_QUAD", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_REFERENCE_SPACE_CREATE_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_REFERENCE_SPACE_CREATE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_ACTION_SPACE_CREATE_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_ACTION_SPACE_CREATE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING:
|
||||||
|
strncpy(buffer, "XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_VIEW_CONFIGURATION_VIEW:
|
||||||
|
strncpy(buffer, "XR_TYPE_VIEW_CONFIGURATION_VIEW", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_SPACE_LOCATION:
|
||||||
|
strncpy(buffer, "XR_TYPE_SPACE_LOCATION", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_SPACE_VELOCITY:
|
||||||
|
strncpy(buffer, "XR_TYPE_SPACE_VELOCITY", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_FRAME_STATE:
|
||||||
|
strncpy(buffer, "XR_TYPE_FRAME_STATE", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_VIEW_CONFIGURATION_PROPERTIES:
|
||||||
|
strncpy(buffer, "XR_TYPE_VIEW_CONFIGURATION_PROPERTIES", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_FRAME_BEGIN_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_FRAME_BEGIN_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW:
|
||||||
|
strncpy(buffer, "XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_EVENT_DATA_EVENTS_LOST:
|
||||||
|
strncpy(buffer, "XR_TYPE_EVENT_DATA_EVENTS_LOST", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING:
|
||||||
|
strncpy(buffer, "XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED:
|
||||||
|
strncpy(buffer, "XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_INTERACTION_PROFILE_STATE:
|
||||||
|
strncpy(buffer, "XR_TYPE_INTERACTION_PROFILE_STATE", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_ACTION_STATE_GET_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_ACTION_STATE_GET_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_HAPTIC_ACTION_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_HAPTIC_ACTION_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_ACTIONS_SYNC_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_ACTIONS_SYNC_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO:
|
||||||
|
strncpy(buffer, "XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_COMPOSITION_LAYER_CUBE_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_COMPOSITION_LAYER_CUBE_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT:
|
||||||
|
strncpy(buffer, "XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT:
|
||||||
|
strncpy(buffer, "XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT:
|
||||||
|
strncpy(buffer, "XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT:
|
||||||
|
strncpy(buffer, "XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_DEBUG_UTILS_LABEL_EXT:
|
||||||
|
strncpy(buffer, "XR_TYPE_DEBUG_UTILS_LABEL_EXT", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_GRAPHICS_BINDING_D3D11_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_GRAPHICS_BINDING_D3D11_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_GRAPHICS_BINDING_D3D12_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_GRAPHICS_BINDING_D3D12_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_VISIBILITY_MASK_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_VISIBILITY_MASK_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
case XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR:
|
||||||
|
strncpy(buffer, "XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Unknown structure type
|
||||||
|
snprintf(buffer, XR_MAX_STRUCTURE_NAME_SIZE, "XR_UNKNOWN_STRUCTURE_TYPE_%d", struct_type);
|
||||||
|
int_result = XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return int_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
43
extern/openxr/src/xr_generated_utilities.h
vendored
Normal file
43
extern/openxr/src/xr_generated_utilities.h
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
|
||||||
|
// See utility_source_generator.py for modifications
|
||||||
|
// ************************************************************
|
||||||
|
|
||||||
|
// Copyright (c) 2017-2019 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
XrResult GeneratedXrUtilitiesResultToString(XrResult result,
|
||||||
|
char buffer[XR_MAX_RESULT_STRING_SIZE]);
|
||||||
|
XrResult GeneratedXrUtilitiesStructureTypeToString(XrStructureType struct_type,
|
||||||
|
char buffer[XR_MAX_STRUCTURE_NAME_SIZE]);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Current API version of the utililties
|
||||||
|
#define XR_UTILITIES_API_VERSION XR_CURRENT_API_VERSION
|
||||||
|
|
||||||
@@ -270,11 +270,13 @@ elseif(WIN32)
|
|||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND SRC
|
list(APPEND SRC
|
||||||
|
intern/GHOST_ContextD3D.cpp
|
||||||
intern/GHOST_DisplayManagerWin32.cpp
|
intern/GHOST_DisplayManagerWin32.cpp
|
||||||
intern/GHOST_DropTargetWin32.cpp
|
intern/GHOST_DropTargetWin32.cpp
|
||||||
intern/GHOST_SystemWin32.cpp
|
intern/GHOST_SystemWin32.cpp
|
||||||
intern/GHOST_WindowWin32.cpp
|
intern/GHOST_WindowWin32.cpp
|
||||||
|
|
||||||
|
intern/GHOST_ContextD3D.h
|
||||||
intern/GHOST_DisplayManagerWin32.h
|
intern/GHOST_DisplayManagerWin32.h
|
||||||
intern/GHOST_DropTargetWin32.h
|
intern/GHOST_DropTargetWin32.h
|
||||||
intern/GHOST_SystemWin32.h
|
intern/GHOST_SystemWin32.h
|
||||||
@@ -345,6 +347,43 @@ elseif(WIN32)
|
|||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_OPENXR)
|
||||||
|
list(APPEND SRC
|
||||||
|
intern/GHOST_Xr.cpp
|
||||||
|
intern/GHOST_XrContext.cpp
|
||||||
|
intern/GHOST_XrEvent.cpp
|
||||||
|
intern/GHOST_XrGraphicsBinding.cpp
|
||||||
|
intern/GHOST_XrSession.cpp
|
||||||
|
|
||||||
|
GHOST_IXrContext.h
|
||||||
|
intern/GHOST_Xr_intern.h
|
||||||
|
intern/GHOST_Xr_openxr_includes.h
|
||||||
|
intern/GHOST_XrContext.h
|
||||||
|
intern/GHOST_IXrGraphicsBinding.h
|
||||||
|
intern/GHOST_XrSession.h
|
||||||
|
)
|
||||||
|
list(APPEND INC
|
||||||
|
)
|
||||||
|
list(APPEND INC_SYS
|
||||||
|
${OPENXR_SDK_INCLUDES}
|
||||||
|
)
|
||||||
|
|
||||||
|
include(xr_platform_defines)
|
||||||
|
|
||||||
|
if(OPENXR_USE_BUNDLED_SRC)
|
||||||
|
if(WIN32)
|
||||||
|
set(OPENXR_LOADER_NAME openxr_loader-1_0)
|
||||||
|
else()
|
||||||
|
set(OPENXR_LOADER_NAME openxr_loader)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(APPEND LIB ${OPENXR_LOADER_NAME})
|
||||||
|
list(APPEND INC ../../extern/openxr/include)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_definitions(-DWITH_OPENXR)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_definitions(${GL_DEFINITIONS})
|
add_definitions(${GL_DEFINITIONS})
|
||||||
|
|
||||||
blender_add_lib(bf_intern_ghost "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
blender_add_lib(bf_intern_ghost "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||||
|
|||||||
@@ -30,21 +30,6 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a "handle" for a C++ GHOST object.
|
|
||||||
* A handle is just an opaque pointer to an empty struct.
|
|
||||||
* In the API the pointer is cast to the actual C++ class.
|
|
||||||
* The 'name' argument to the macro is the name of the handle to create.
|
|
||||||
*/
|
|
||||||
|
|
||||||
GHOST_DECLARE_HANDLE(GHOST_SystemHandle);
|
|
||||||
GHOST_DECLARE_HANDLE(GHOST_TimerTaskHandle);
|
|
||||||
GHOST_DECLARE_HANDLE(GHOST_WindowHandle);
|
|
||||||
GHOST_DECLARE_HANDLE(GHOST_EventHandle);
|
|
||||||
GHOST_DECLARE_HANDLE(GHOST_RectangleHandle);
|
|
||||||
GHOST_DECLARE_HANDLE(GHOST_EventConsumerHandle);
|
|
||||||
GHOST_DECLARE_HANDLE(GHOST_ContextHandle);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Definition of a callback routine that receives events.
|
* Definition of a callback routine that receives events.
|
||||||
* \param event The event received.
|
* \param event The event received.
|
||||||
@@ -193,6 +178,36 @@ extern GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemha
|
|||||||
extern GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle,
|
extern GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle,
|
||||||
GHOST_ContextHandle contexthandle);
|
GHOST_ContextHandle contexthandle);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
/**
|
||||||
|
* Create a new offscreen context.
|
||||||
|
* Never explicitly delete the context, use disposeContext() instead.
|
||||||
|
* \param systemhandle The handle to the system
|
||||||
|
* \return A handle to the new context ( == NULL if creation failed).
|
||||||
|
*/
|
||||||
|
GHOST_ContextHandle GHOST_CreateDirectXContext(GHOST_SystemHandle systemhandle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispose of a context.
|
||||||
|
* \param systemhandle The handle to the system
|
||||||
|
* \param contexthandle Handle to the context to be disposed.
|
||||||
|
* \return Indication of success.
|
||||||
|
*/
|
||||||
|
GHOST_TSuccess GHOST_DisposeDirectXContext(GHOST_SystemHandle systemhandle,
|
||||||
|
GHOST_ContextHandle contexthandle);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GHOST_TSuccess GHOST_BlitOpenGLOffscreenContext(GHOST_WindowHandle windowhandle,
|
||||||
|
GHOST_ContextHandle offscreen_contexthandle);
|
||||||
|
|
||||||
|
extern GHOST_TSuccess GHOST_ContextBlitOpenGLOffscreenContext(
|
||||||
|
GHOST_ContextHandle onscreen_contexthandle,
|
||||||
|
GHOST_ContextHandle offscreen_contexthandle,
|
||||||
|
GHOST_TInt32 width,
|
||||||
|
GHOST_TInt32 height);
|
||||||
|
|
||||||
|
extern GHOST_ContextHandle GHOST_GetWindowContext(GHOST_WindowHandle windowhandle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the window user data.
|
* Returns the window user data.
|
||||||
* \param windowhandle The handle to the window
|
* \param windowhandle The handle to the window
|
||||||
@@ -207,6 +222,11 @@ extern GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandl
|
|||||||
*/
|
*/
|
||||||
extern void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, GHOST_TUserDataPtr userdata);
|
extern void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, GHOST_TUserDataPtr userdata);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether a window is rendered upside down compared to OpenGL.
|
||||||
|
*/
|
||||||
|
extern int GHOST_isUpsideDownWindow(GHOST_WindowHandle windowhandle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dispose a window.
|
* Dispose a window.
|
||||||
* \param systemhandle The handle to the system
|
* \param systemhandle The handle to the system
|
||||||
@@ -662,6 +682,13 @@ extern GHOST_TSuccess GHOST_SetWindowOrder(GHOST_WindowHandle windowhandle,
|
|||||||
*/
|
*/
|
||||||
extern GHOST_TSuccess GHOST_SwapWindowBuffers(GHOST_WindowHandle windowhandle);
|
extern GHOST_TSuccess GHOST_SwapWindowBuffers(GHOST_WindowHandle windowhandle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swaps front and back buffers of a context.
|
||||||
|
* \param contexthandle The handle to the context
|
||||||
|
* \return A success indicator.
|
||||||
|
*/
|
||||||
|
extern GHOST_TSuccess GHOST_SwapContextBuffers(GHOST_ContextHandle contexthandle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the swap interval for swapBuffers.
|
* Sets the swap interval for swapBuffers.
|
||||||
* \param interval The swap interval to use.
|
* \param interval The swap interval to use.
|
||||||
@@ -706,6 +733,16 @@ extern GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthan
|
|||||||
*/
|
*/
|
||||||
extern GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle);
|
extern GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the OpenGL framebuffer handle that serves as a default framebuffer.
|
||||||
|
*/
|
||||||
|
extern unsigned int GHOST_GetContextDefaultOpenGLFramebuffer(GHOST_ContextHandle contexthandle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether a context is rendered upside down compared to OpenGL.
|
||||||
|
*/
|
||||||
|
extern int GHOST_isUpsideDownContext(GHOST_ContextHandle contexthandle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the OpenGL framebuffer handle that serves as a default framebuffer.
|
* Get the OpenGL framebuffer handle that serves as a default framebuffer.
|
||||||
*/
|
*/
|
||||||
@@ -941,6 +978,37 @@ extern void GHOST_BeginIME(GHOST_WindowHandle windowhandle,
|
|||||||
*/
|
*/
|
||||||
extern void GHOST_EndIME(GHOST_WindowHandle windowhandle);
|
extern void GHOST_EndIME(GHOST_WindowHandle windowhandle);
|
||||||
|
|
||||||
|
#ifdef WITH_OPENXR
|
||||||
|
|
||||||
|
/* xr-context */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a custom callback to be executed whenever an error occurs. Should be set before calling
|
||||||
|
* #GHOST_XrContextCreate().
|
||||||
|
*/
|
||||||
|
void GHOST_XrErrorHandler(GHOST_XrErrorHandlerFn handler_fn, void *customdata);
|
||||||
|
|
||||||
|
GHOST_XrContextHandle GHOST_XrContextCreate(const GHOST_XrContextCreateInfo *create_info);
|
||||||
|
void GHOST_XrContextDestroy(GHOST_XrContextHandle xr_context);
|
||||||
|
|
||||||
|
void GHOST_XrGraphicsContextBindFuncs(GHOST_XrContextHandle xr_context,
|
||||||
|
GHOST_XrGraphicsContextBindFn bind_fn,
|
||||||
|
GHOST_XrGraphicsContextUnbindFn unbind_fn);
|
||||||
|
|
||||||
|
void GHOST_XrDrawViewFunc(GHOST_XrContextHandle xr_context, GHOST_XrDrawViewFn draw_view_fn);
|
||||||
|
|
||||||
|
/* sessions */
|
||||||
|
void GHOST_XrSessionStart(GHOST_XrContextHandle xr_context,
|
||||||
|
const GHOST_XrSessionBeginInfo *begin_info);
|
||||||
|
void GHOST_XrSessionEnd(GHOST_XrContextHandle xr_context);
|
||||||
|
int GHOST_XrHasSession(const GHOST_XrContextHandle xr_contexthandle);
|
||||||
|
int GHOST_XrSessionShouldRunDrawLoop(const GHOST_XrContextHandle xr_context);
|
||||||
|
void GHOST_XrSessionDrawViews(GHOST_XrContextHandle xr_context, void *customdata);
|
||||||
|
|
||||||
|
/* events */
|
||||||
|
GHOST_TSuccess GHOST_XrEventsHandle(GHOST_XrContextHandle xr_context);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -56,6 +56,16 @@ class GHOST_IContext {
|
|||||||
*/
|
*/
|
||||||
virtual GHOST_TSuccess releaseDrawingContext() = 0;
|
virtual GHOST_TSuccess releaseDrawingContext() = 0;
|
||||||
|
|
||||||
|
virtual GHOST_TSuccess blitOpenGLOffscreenContext(class GHOST_Context *offscreen,
|
||||||
|
GHOST_TInt32 width,
|
||||||
|
GHOST_TInt32 height) = 0;
|
||||||
|
|
||||||
|
virtual unsigned int getDefaultFramebuffer() = 0;
|
||||||
|
|
||||||
|
virtual GHOST_TSuccess swapBuffers() = 0;
|
||||||
|
|
||||||
|
virtual bool isUpsideDown() const = 0;
|
||||||
|
|
||||||
#ifdef WITH_CXX_GUARDEDALLOC
|
#ifdef WITH_CXX_GUARDEDALLOC
|
||||||
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IContext")
|
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IContext")
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -264,6 +264,12 @@ class GHOST_ISystem {
|
|||||||
*/
|
*/
|
||||||
virtual GHOST_IContext *createOffscreenContext() = 0;
|
virtual GHOST_IContext *createOffscreenContext() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overload to allow requesting a different context type. By default only OpenGL is supported.
|
||||||
|
* However by explicitly overloading this a system may add support for others.
|
||||||
|
*/
|
||||||
|
virtual GHOST_IContext *createOffscreenContext(GHOST_TDrawingContextType type) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dispose of a context.
|
* Dispose of a context.
|
||||||
* \param context Pointer to the context to be disposed.
|
* \param context Pointer to the context to be disposed.
|
||||||
|
|||||||
@@ -77,6 +77,10 @@ class GHOST_IWindow {
|
|||||||
*/
|
*/
|
||||||
virtual GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type) = 0;
|
virtual GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type) = 0;
|
||||||
|
|
||||||
|
virtual class GHOST_IContext *getDrawingContext() = 0;
|
||||||
|
|
||||||
|
virtual GHOST_TSuccess blitOpenGLOffscreenContext(GHOST_IContext *offscreen) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the title displayed in the title bar.
|
* Sets the title displayed in the title bar.
|
||||||
* \param title The title to display in the title bar.
|
* \param title The title to display in the title bar.
|
||||||
@@ -241,6 +245,11 @@ class GHOST_IWindow {
|
|||||||
*/
|
*/
|
||||||
virtual void setUserData(const GHOST_TUserDataPtr userData) = 0;
|
virtual void setUserData(const GHOST_TUserDataPtr userData) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if the window is rendered upside down compared to OpenGL.
|
||||||
|
*/
|
||||||
|
virtual bool isUpsideDown() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the tablet data (pressure etc).
|
* Returns the tablet data (pressure etc).
|
||||||
* \return The tablet data (pressure etc).
|
* \return The tablet data (pressure etc).
|
||||||
|
|||||||
43
intern/ghost/GHOST_IXrContext.h
Normal file
43
intern/ghost/GHOST_IXrContext.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup GHOST
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GHOST_IXRCONTEXT_H__
|
||||||
|
#define __GHOST_IXRCONTEXT_H__
|
||||||
|
|
||||||
|
#include "GHOST_Types.h"
|
||||||
|
|
||||||
|
class GHOST_IXrContext {
|
||||||
|
public:
|
||||||
|
virtual ~GHOST_IXrContext() = default;
|
||||||
|
|
||||||
|
virtual void startSession(const GHOST_XrSessionBeginInfo *begin_info) = 0;
|
||||||
|
virtual void endSession() = 0;
|
||||||
|
virtual bool hasSession() const = 0;
|
||||||
|
virtual bool shouldRunSessionDrawLoop() const = 0;
|
||||||
|
virtual void drawSessionViews(void *draw_customdata) = 0;
|
||||||
|
|
||||||
|
virtual void dispatchErrorMessage(const class GHOST_XrException *) const = 0;
|
||||||
|
|
||||||
|
virtual void setGraphicsContextBindFuncs(GHOST_XrGraphicsContextBindFn bind_fn,
|
||||||
|
GHOST_XrGraphicsContextUnbindFn unbind_fn) = 0;
|
||||||
|
virtual void setDrawViewFunc(GHOST_XrDrawViewFn draw_view_fn) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __GHOST_IXRCONTEXT_H__
|
||||||
@@ -41,6 +41,22 @@
|
|||||||
} * name
|
} * name
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a "handle" for a C++ GHOST object.
|
||||||
|
* A handle is just an opaque pointer to an empty struct.
|
||||||
|
* In the API the pointer is cast to the actual C++ class.
|
||||||
|
* The 'name' argument to the macro is the name of the handle to create.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GHOST_DECLARE_HANDLE(GHOST_SystemHandle);
|
||||||
|
GHOST_DECLARE_HANDLE(GHOST_TimerTaskHandle);
|
||||||
|
GHOST_DECLARE_HANDLE(GHOST_WindowHandle);
|
||||||
|
GHOST_DECLARE_HANDLE(GHOST_EventHandle);
|
||||||
|
GHOST_DECLARE_HANDLE(GHOST_RectangleHandle);
|
||||||
|
GHOST_DECLARE_HANDLE(GHOST_EventConsumerHandle);
|
||||||
|
GHOST_DECLARE_HANDLE(GHOST_ContextHandle);
|
||||||
|
GHOST_DECLARE_HANDLE(GHOST_XrContextHandle);
|
||||||
|
|
||||||
typedef char GHOST_TInt8;
|
typedef char GHOST_TInt8;
|
||||||
typedef unsigned char GHOST_TUns8;
|
typedef unsigned char GHOST_TUns8;
|
||||||
typedef short GHOST_TInt16;
|
typedef short GHOST_TInt16;
|
||||||
@@ -129,7 +145,10 @@ typedef enum { GHOST_kWindowOrderTop = 0, GHOST_kWindowOrderBottom } GHOST_TWind
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GHOST_kDrawingContextTypeNone = 0,
|
GHOST_kDrawingContextTypeNone = 0,
|
||||||
GHOST_kDrawingContextTypeOpenGL
|
GHOST_kDrawingContextTypeOpenGL,
|
||||||
|
#ifdef WIN32
|
||||||
|
GHOST_kDrawingContextTypeD3D,
|
||||||
|
#endif
|
||||||
} GHOST_TDrawingContextType;
|
} GHOST_TDrawingContextType;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -542,4 +561,84 @@ struct GHOST_TimerTaskHandle__;
|
|||||||
typedef void (*GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__ *task, GHOST_TUns64 time);
|
typedef void (*GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__ *task, GHOST_TUns64 time);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_OPENXR
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The XR view (i.e. the OpenXR runtime) may require a different graphics library than OpenGL. An
|
||||||
|
* offscreen texture of the viewport will then be drawn into using OpenGL, but the final texture
|
||||||
|
* draw call will happen through another lib (say DirectX).
|
||||||
|
*
|
||||||
|
* This enum defines the possible graphics bindings to attempt to enable.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
GHOST_kXrGraphicsUnknown = 0,
|
||||||
|
GHOST_kXrGraphicsOpenGL,
|
||||||
|
# ifdef WIN32
|
||||||
|
GHOST_kXrGraphicsD3D11,
|
||||||
|
# endif
|
||||||
|
/* For later */
|
||||||
|
// GHOST_kXrGraphicsVulkan,
|
||||||
|
} GHOST_TXrGraphicsBinding;
|
||||||
|
/* An array of GHOST_TXrGraphicsBinding items defining the candidate bindings to use. The first
|
||||||
|
* available candidate will be chosen, so order defines priority. */
|
||||||
|
typedef const GHOST_TXrGraphicsBinding *GHOST_XrGraphicsBindingCandidates;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float position[3];
|
||||||
|
/* Blender convention (w, x, y, z) */
|
||||||
|
float orientation_quat[4];
|
||||||
|
} GHOST_XrPose;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
GHOST_kXrContextDebug = (1 << 0),
|
||||||
|
GHOST_kXrContextDebugTime = (1 << 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const GHOST_XrGraphicsBindingCandidates gpu_binding_candidates;
|
||||||
|
unsigned int gpu_binding_candidates_count;
|
||||||
|
|
||||||
|
unsigned int context_flag;
|
||||||
|
} GHOST_XrContextCreateInfo;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GHOST_XrPose base_pose;
|
||||||
|
} GHOST_XrSessionBeginInfo;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int ofsx, ofsy;
|
||||||
|
int width, height;
|
||||||
|
|
||||||
|
GHOST_XrPose pose;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
float angle_left, angle_right;
|
||||||
|
float angle_up, angle_down;
|
||||||
|
} fov;
|
||||||
|
|
||||||
|
/** Set if the buffer should be submitted with a srgb transfer applied. */
|
||||||
|
char expects_srgb_buffer;
|
||||||
|
} GHOST_XrDrawViewInfo;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *user_message;
|
||||||
|
|
||||||
|
/** File path and line number the error was found at. */
|
||||||
|
const char *source_location;
|
||||||
|
|
||||||
|
void *customdata;
|
||||||
|
} GHOST_XrError;
|
||||||
|
|
||||||
|
typedef void (*GHOST_XrErrorHandlerFn)(const GHOST_XrError *);
|
||||||
|
|
||||||
|
typedef void *(*GHOST_XrGraphicsContextBindFn)(GHOST_TXrGraphicsBinding graphics_lib);
|
||||||
|
typedef void (*GHOST_XrGraphicsContextUnbindFn)(GHOST_TXrGraphicsBinding graphics_lib,
|
||||||
|
void *graphics_context);
|
||||||
|
/* XXX hacky: returns GHOST_ContextHandle so DirectX binding can get a handle to the OpenGL
|
||||||
|
* offscreen context. */
|
||||||
|
typedef GHOST_ContextHandle (*GHOST_XrDrawViewFn)(const GHOST_XrDrawViewInfo *draw_view,
|
||||||
|
void *customdata);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // __GHOST_TYPES_H__
|
#endif // __GHOST_TYPES_H__
|
||||||
|
|||||||
@@ -30,7 +30,9 @@
|
|||||||
#include "GHOST_ISystem.h"
|
#include "GHOST_ISystem.h"
|
||||||
#include "GHOST_IEvent.h"
|
#include "GHOST_IEvent.h"
|
||||||
#include "GHOST_IEventConsumer.h"
|
#include "GHOST_IEventConsumer.h"
|
||||||
|
#include "GHOST_IXrContext.h"
|
||||||
#include "intern/GHOST_CallbackEventConsumer.h"
|
#include "intern/GHOST_CallbackEventConsumer.h"
|
||||||
|
#include "intern/GHOST_XrException.h"
|
||||||
|
|
||||||
GHOST_SystemHandle GHOST_CreateSystem(void)
|
GHOST_SystemHandle GHOST_CreateSystem(void)
|
||||||
{
|
{
|
||||||
@@ -127,6 +129,51 @@ GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle,
|
|||||||
return system->disposeContext(context);
|
return system->disposeContext(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
GHOST_ContextHandle GHOST_CreateDirectXContext(GHOST_SystemHandle systemhandle)
|
||||||
|
{
|
||||||
|
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
|
||||||
|
|
||||||
|
return (GHOST_ContextHandle)system->createOffscreenContext(GHOST_kDrawingContextTypeD3D);
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_TSuccess GHOST_DisposeDirectXContext(GHOST_SystemHandle systemhandle,
|
||||||
|
GHOST_ContextHandle contexthandle)
|
||||||
|
{
|
||||||
|
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
|
||||||
|
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
|
||||||
|
|
||||||
|
return system->disposeContext(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GHOST_TSuccess GHOST_BlitOpenGLOffscreenContext(GHOST_WindowHandle windowhandle,
|
||||||
|
GHOST_ContextHandle offscreen_contexthandle)
|
||||||
|
{
|
||||||
|
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
|
||||||
|
|
||||||
|
return window->blitOpenGLOffscreenContext((GHOST_IContext *)offscreen_contexthandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_TSuccess GHOST_ContextBlitOpenGLOffscreenContext(GHOST_ContextHandle onscreen_contexthandle,
|
||||||
|
GHOST_ContextHandle offscreen_contexthandle,
|
||||||
|
GHOST_TInt32 width,
|
||||||
|
GHOST_TInt32 height)
|
||||||
|
{
|
||||||
|
GHOST_IContext *context = (GHOST_IContext *)onscreen_contexthandle;
|
||||||
|
|
||||||
|
return context->blitOpenGLOffscreenContext(
|
||||||
|
(class GHOST_Context *)offscreen_contexthandle, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_ContextHandle GHOST_GetWindowContext(GHOST_WindowHandle windowhandle)
|
||||||
|
{
|
||||||
|
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
|
||||||
|
|
||||||
|
return (GHOST_ContextHandle)window->getDrawingContext();
|
||||||
|
}
|
||||||
|
|
||||||
GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
|
GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
|
||||||
const char *title,
|
const char *title,
|
||||||
GHOST_TInt32 left,
|
GHOST_TInt32 left,
|
||||||
@@ -156,6 +203,13 @@ void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, GHOST_TUserDataPtr
|
|||||||
window->setUserData(userdata);
|
window->setUserData(userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GHOST_isUpsideDownWindow(GHOST_WindowHandle windowhandle)
|
||||||
|
{
|
||||||
|
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
|
||||||
|
|
||||||
|
return window->isUpsideDown();
|
||||||
|
}
|
||||||
|
|
||||||
GHOST_TSuccess GHOST_DisposeWindow(GHOST_SystemHandle systemhandle,
|
GHOST_TSuccess GHOST_DisposeWindow(GHOST_SystemHandle systemhandle,
|
||||||
GHOST_WindowHandle windowhandle)
|
GHOST_WindowHandle windowhandle)
|
||||||
{
|
{
|
||||||
@@ -586,6 +640,13 @@ GHOST_TSuccess GHOST_SwapWindowBuffers(GHOST_WindowHandle windowhandle)
|
|||||||
return window->swapBuffers();
|
return window->swapBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GHOST_TSuccess GHOST_SwapContextBuffers(GHOST_ContextHandle contexthandle)
|
||||||
|
{
|
||||||
|
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
|
||||||
|
|
||||||
|
return context->swapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
GHOST_TSuccess GHOST_SetSwapInterval(GHOST_WindowHandle windowhandle, int interval)
|
GHOST_TSuccess GHOST_SetSwapInterval(GHOST_WindowHandle windowhandle, int interval)
|
||||||
{
|
{
|
||||||
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
|
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
|
||||||
@@ -621,6 +682,20 @@ GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle)
|
|||||||
return context->releaseDrawingContext();
|
return context->releaseDrawingContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int GHOST_GetContextDefaultOpenGLFramebuffer(GHOST_ContextHandle contexthandle)
|
||||||
|
{
|
||||||
|
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
|
||||||
|
|
||||||
|
return context->getDefaultFramebuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
int GHOST_isUpsideDownContext(GHOST_ContextHandle contexthandle)
|
||||||
|
{
|
||||||
|
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
|
||||||
|
|
||||||
|
return context->isUpsideDown();
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int GHOST_GetDefaultOpenGLFramebuffer(GHOST_WindowHandle windowhandle)
|
unsigned int GHOST_GetDefaultOpenGLFramebuffer(GHOST_WindowHandle windowhandle)
|
||||||
{
|
{
|
||||||
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
|
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
|
||||||
@@ -830,3 +905,70 @@ void GHOST_EndIME(GHOST_WindowHandle windowhandle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif /* WITH_INPUT_IME */
|
#endif /* WITH_INPUT_IME */
|
||||||
|
|
||||||
|
#ifdef WITH_OPENXR
|
||||||
|
|
||||||
|
# define GHOST_XR_CAPI_CALL(call, ctx) \
|
||||||
|
try { \
|
||||||
|
call; \
|
||||||
|
} \
|
||||||
|
catch (GHOST_XrException & e) { \
|
||||||
|
(ctx)->dispatchErrorMessage(&e); \
|
||||||
|
}
|
||||||
|
|
||||||
|
# define GHOST_XR_CAPI_CALL_RET(call, ctx) \
|
||||||
|
try { \
|
||||||
|
return call; \
|
||||||
|
} \
|
||||||
|
catch (GHOST_XrException & e) { \
|
||||||
|
(ctx)->dispatchErrorMessage(&e); \
|
||||||
|
}
|
||||||
|
|
||||||
|
void GHOST_XrSessionStart(GHOST_XrContextHandle xr_contexthandle,
|
||||||
|
const GHOST_XrSessionBeginInfo *begin_info)
|
||||||
|
{
|
||||||
|
GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
|
||||||
|
GHOST_XR_CAPI_CALL(xr_context->startSession(begin_info), xr_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GHOST_XrSessionEnd(GHOST_XrContextHandle xr_contexthandle)
|
||||||
|
{
|
||||||
|
GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
|
||||||
|
GHOST_XR_CAPI_CALL(xr_context->endSession(), xr_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GHOST_XrHasSession(const GHOST_XrContextHandle xr_contexthandle)
|
||||||
|
{
|
||||||
|
const GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
|
||||||
|
GHOST_XR_CAPI_CALL_RET(xr_context->hasSession(), xr_context);
|
||||||
|
return 0; // Only reached if exception is thrown.
|
||||||
|
}
|
||||||
|
|
||||||
|
int GHOST_XrSessionShouldRunDrawLoop(const GHOST_XrContextHandle xr_contexthandle)
|
||||||
|
{
|
||||||
|
const GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
|
||||||
|
GHOST_XR_CAPI_CALL_RET(xr_context->shouldRunSessionDrawLoop(), xr_context);
|
||||||
|
return 0; // Only reached if exception is thrown.
|
||||||
|
}
|
||||||
|
|
||||||
|
void GHOST_XrSessionDrawViews(GHOST_XrContextHandle xr_contexthandle, void *draw_customdata)
|
||||||
|
{
|
||||||
|
GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
|
||||||
|
GHOST_XR_CAPI_CALL(xr_context->drawSessionViews(draw_customdata), xr_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GHOST_XrGraphicsContextBindFuncs(GHOST_XrContextHandle xr_contexthandle,
|
||||||
|
GHOST_XrGraphicsContextBindFn bind_fn,
|
||||||
|
GHOST_XrGraphicsContextUnbindFn unbind_fn)
|
||||||
|
{
|
||||||
|
GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
|
||||||
|
GHOST_XR_CAPI_CALL(xr_context->setGraphicsContextBindFuncs(bind_fn, unbind_fn), xr_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GHOST_XrDrawViewFunc(GHOST_XrContextHandle xr_contexthandle, GHOST_XrDrawViewFn draw_view_fn)
|
||||||
|
{
|
||||||
|
GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
|
||||||
|
GHOST_XR_CAPI_CALL(xr_context->setDrawViewFunc(draw_view_fn), xr_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -149,3 +149,68 @@ void GHOST_Context::initClearGL()
|
|||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
glClearColor(0.000, 0.000, 0.000, 0.000);
|
glClearColor(0.000, 0.000, 0.000, 0.000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GHOST_TSuccess GHOST_Context::blitOpenGLOffscreenContext(GHOST_Context *offscreen,
|
||||||
|
GHOST_TInt32 width,
|
||||||
|
GHOST_TInt32 height)
|
||||||
|
{
|
||||||
|
GLuint fbo_offscreen;
|
||||||
|
GLuint fbo_onscreen;
|
||||||
|
GLuint render_buf_shared;
|
||||||
|
GLint fbo_prev_draw;
|
||||||
|
|
||||||
|
if ((m_type != GHOST_kDrawingContextTypeOpenGL) ||
|
||||||
|
(offscreen->m_type != GHOST_kDrawingContextTypeOpenGL)) {
|
||||||
|
return GHOST_kFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
offscreen->setDefaultFramebufferSize(width, height);
|
||||||
|
|
||||||
|
/* Logic here:
|
||||||
|
* We can't simply blit from one context's framebuffer into the other. Unlike Framebuffers/FBOs,
|
||||||
|
* Renderbuffers can be shared though. So create one, and blit the offscreen context framebuffer
|
||||||
|
* contents into it. To share it, an FBO has to be created for each context though, as the
|
||||||
|
* default framebuffer doesn't allow any attachments. */
|
||||||
|
|
||||||
|
offscreen->activateDrawingContext();
|
||||||
|
|
||||||
|
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &fbo_prev_draw);
|
||||||
|
|
||||||
|
/* Create shared renderbuffer */
|
||||||
|
glGenRenderbuffers(1, &render_buf_shared);
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, render_buf_shared);
|
||||||
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
|
||||||
|
|
||||||
|
/* Create offscreen FBO and assign renderbuffer */
|
||||||
|
glGenFramebuffers(1, &fbo_offscreen);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo_offscreen);
|
||||||
|
glFramebufferRenderbuffer(
|
||||||
|
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, render_buf_shared);
|
||||||
|
|
||||||
|
/* Blit offscreen framebuffer into renderbuffer */
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_prev_draw);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_offscreen);
|
||||||
|
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||||
|
|
||||||
|
glDeleteFramebuffers(1, &fbo_offscreen); /* Can delete already. Do before context change. */
|
||||||
|
|
||||||
|
activateDrawingContext();
|
||||||
|
|
||||||
|
/* Create onscreen FBO and assign renderbuffer */
|
||||||
|
glGenFramebuffers(1, &fbo_onscreen);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo_onscreen);
|
||||||
|
glFramebufferRenderbuffer(
|
||||||
|
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, render_buf_shared);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_onscreen);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getDefaultFramebuffer());
|
||||||
|
/* Finally, blit to onscreen buffer. */
|
||||||
|
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||||
|
|
||||||
|
glDeleteFramebuffers(1, &fbo_onscreen);
|
||||||
|
glDeleteRenderbuffers(1, &render_buf_shared);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
return GHOST_kSuccess;
|
||||||
|
}
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ class GHOST_Context : public GHOST_IContext {
|
|||||||
* Constructor.
|
* Constructor.
|
||||||
* \param stereoVisual Stereo visual for quad buffered stereo.
|
* \param stereoVisual Stereo visual for quad buffered stereo.
|
||||||
*/
|
*/
|
||||||
GHOST_Context(bool stereoVisual) : m_stereoVisual(stereoVisual)
|
GHOST_Context(GHOST_TDrawingContextType type, bool stereoVisual)
|
||||||
|
: m_type(type), m_stereoVisual(stereoVisual)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,6 +120,11 @@ class GHOST_Context : public GHOST_IContext {
|
|||||||
return m_stereoVisual;
|
return m_stereoVisual;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool isUpsideDown() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the OpenGL framebuffer associated with the OpenGL context
|
* Gets the OpenGL framebuffer associated with the OpenGL context
|
||||||
* \return The ID of an OpenGL framebuffer object.
|
* \return The ID of an OpenGL framebuffer object.
|
||||||
@@ -128,9 +134,26 @@ class GHOST_Context : public GHOST_IContext {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For offscreen rendering, we create an invisible window. So this can be used to update the
|
||||||
|
* offscreen buffer size by changing the size of this context's window.
|
||||||
|
*
|
||||||
|
* \note This actually changes the window size! That is the only way to change the default
|
||||||
|
* framebuffer size. Better only use for offscreen contexts.
|
||||||
|
*/
|
||||||
|
virtual GHOST_TSuccess setDefaultFramebufferSize(GHOST_TUns32 /*width*/, GHOST_TUns32 /*height*/)
|
||||||
|
{
|
||||||
|
return GHOST_kFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_TSuccess blitOpenGLOffscreenContext(GHOST_Context *offscreen,
|
||||||
|
GHOST_TInt32 width,
|
||||||
|
GHOST_TInt32 height);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void initContextGLEW();
|
void initContextGLEW();
|
||||||
|
|
||||||
|
GHOST_TDrawingContextType m_type;
|
||||||
bool m_stereoVisual;
|
bool m_stereoVisual;
|
||||||
|
|
||||||
static void initClearGL();
|
static void initClearGL();
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ GHOST_ContextCGL::GHOST_ContextCGL(bool stereoVisual,
|
|||||||
NSView *metalView,
|
NSView *metalView,
|
||||||
CAMetalLayer *metalLayer,
|
CAMetalLayer *metalLayer,
|
||||||
NSOpenGLView *openGLView)
|
NSOpenGLView *openGLView)
|
||||||
: GHOST_Context(stereoVisual),
|
: GHOST_Context(GHOST_kDrawingContextTypeOpenGL, stereoVisual),
|
||||||
m_metalView(metalView),
|
m_metalView(metalView),
|
||||||
m_metalLayer(metalLayer),
|
m_metalLayer(metalLayer),
|
||||||
m_metalCmdQueue(nil),
|
m_metalCmdQueue(nil),
|
||||||
|
|||||||
500
intern/ghost/intern/GHOST_ContextD3D.cpp
Normal file
500
intern/ghost/intern/GHOST_ContextD3D.cpp
Normal file
@@ -0,0 +1,500 @@
|
|||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup GHOST
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GL/wglew.h>
|
||||||
|
|
||||||
|
#include "GHOST_ContextWGL.h" /* For shared drawing */
|
||||||
|
#include "GHOST_ContextD3D.h"
|
||||||
|
|
||||||
|
// #define USE_DRAW_D3D_TEST_TRIANGLE
|
||||||
|
|
||||||
|
HMODULE GHOST_ContextD3D::s_d3d_lib = NULL;
|
||||||
|
PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN GHOST_ContextD3D::s_D3D11CreateDeviceAndSwapChainFn = NULL;
|
||||||
|
|
||||||
|
#ifdef USE_DRAW_D3D_TEST_TRIANGLE
|
||||||
|
static void drawTestTriangle(ID3D11Device *m_device,
|
||||||
|
ID3D11DeviceContext *m_device_ctx,
|
||||||
|
HWND hwnd,
|
||||||
|
GHOST_TInt32 width,
|
||||||
|
GHOST_TInt32 height);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class SharedOpenGLContext {
|
||||||
|
ID3D11Device *m_d3d_device;
|
||||||
|
GHOST_ContextWGL *m_wgl_ctx;
|
||||||
|
/* NV_DX_interop2 requires ID3D11Texture2D as backbuffer when sharing with GL_RENDERBUFFER */
|
||||||
|
ID3D11Texture2D *m_d3d_render_target;
|
||||||
|
GLuint m_gl_render_buf;
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct SharedData {
|
||||||
|
HANDLE device;
|
||||||
|
GLuint fbo;
|
||||||
|
HANDLE render_buf{nullptr};
|
||||||
|
} m_shared;
|
||||||
|
|
||||||
|
/* XXX Should have a map of render_target items to shared resource data (SharedData) to
|
||||||
|
* allow multiple shared surfaces in a context. Current code assumes a single one. That would be
|
||||||
|
* an issue if we wanted to use the OpenXR provided textures (changes for each eye and each
|
||||||
|
* redraw) and not the constant D3D swapchain texture like now. */
|
||||||
|
SharedOpenGLContext(ID3D11Device *d3d_device,
|
||||||
|
GHOST_ContextWGL *wgl_ctx,
|
||||||
|
ID3D11Texture2D *render_target)
|
||||||
|
: m_d3d_device(d3d_device), m_wgl_ctx(wgl_ctx), m_d3d_render_target(render_target)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~SharedOpenGLContext()
|
||||||
|
{
|
||||||
|
if (m_shared.render_buf) {
|
||||||
|
wglDXUnregisterObjectNV(m_shared.device, m_shared.render_buf);
|
||||||
|
}
|
||||||
|
if (m_shared.device) {
|
||||||
|
wglDXCloseDeviceNV(m_shared.device);
|
||||||
|
}
|
||||||
|
glDeleteFramebuffers(1, &m_shared.fbo);
|
||||||
|
glDeleteRenderbuffers(1, &m_gl_render_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reregisterSharedObject()
|
||||||
|
{
|
||||||
|
if (m_shared.render_buf) {
|
||||||
|
wglDXUnregisterObjectNV(m_shared.device, m_shared.render_buf);
|
||||||
|
m_shared.render_buf = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shared.render_buf = wglDXRegisterObjectNV(m_shared.device,
|
||||||
|
m_d3d_render_target,
|
||||||
|
m_gl_render_buf,
|
||||||
|
GL_RENDERBUFFER,
|
||||||
|
WGL_ACCESS_READ_WRITE_NV);
|
||||||
|
if (!m_shared.render_buf) {
|
||||||
|
fprintf(stderr, "Error registering shared object using wglDXRegisterObjectNV()\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_TSuccess initialize()
|
||||||
|
{
|
||||||
|
m_wgl_ctx->activateDrawingContext();
|
||||||
|
|
||||||
|
m_shared.device = wglDXOpenDeviceNV(m_d3d_device);
|
||||||
|
if (m_shared.device == NULL) {
|
||||||
|
fprintf(stderr, "Error opening shared device using wglDXOpenDeviceNV()\n");
|
||||||
|
return GHOST_kFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build the renderbuffer. */
|
||||||
|
glGenRenderbuffers(1, &m_gl_render_buf);
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, m_gl_render_buf);
|
||||||
|
|
||||||
|
reregisterSharedObject();
|
||||||
|
|
||||||
|
/* Build the framebuffer */
|
||||||
|
glGenFramebuffers(1, &m_shared.fbo);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, m_shared.fbo);
|
||||||
|
glFramebufferRenderbuffer(
|
||||||
|
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_gl_render_buf);
|
||||||
|
|
||||||
|
return GHOST_kSuccess;
|
||||||
|
}
|
||||||
|
void update(int width, int height)
|
||||||
|
{
|
||||||
|
m_wgl_ctx->setDefaultFramebufferSize(width, height);
|
||||||
|
m_wgl_ctx->activateDrawingContext();
|
||||||
|
/* TODO avoid re-registering if resource to share has not changed. */
|
||||||
|
reregisterSharedObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
void beginGLOnly()
|
||||||
|
{
|
||||||
|
wglDXLockObjectsNV(m_shared.device, 1, &m_shared.render_buf);
|
||||||
|
}
|
||||||
|
void endGLOnly()
|
||||||
|
{
|
||||||
|
wglDXUnlockObjectsNV(m_shared.device, 1, &m_shared.render_buf);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
GHOST_ContextD3D::GHOST_ContextD3D(bool stereoVisual, HWND hWnd)
|
||||||
|
: GHOST_Context(GHOST_kDrawingContextTypeD3D, stereoVisual), m_hWnd(hWnd)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_ContextD3D::~GHOST_ContextD3D()
|
||||||
|
{
|
||||||
|
delete glshared;
|
||||||
|
m_swapchain->Release();
|
||||||
|
m_backbuffer_view->Release();
|
||||||
|
m_device->Release();
|
||||||
|
m_device_ctx->ClearState();
|
||||||
|
m_device_ctx->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_TSuccess GHOST_ContextD3D::swapBuffers()
|
||||||
|
{
|
||||||
|
HRESULT res = m_swapchain->Present(0, 0);
|
||||||
|
return (res == S_OK) ? GHOST_kSuccess : GHOST_kFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_TSuccess GHOST_ContextD3D::activateDrawingContext()
|
||||||
|
{
|
||||||
|
return GHOST_kFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_TSuccess GHOST_ContextD3D::releaseDrawingContext()
|
||||||
|
{
|
||||||
|
return GHOST_kFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_TSuccess GHOST_ContextD3D::setDefaultFramebufferSize(GHOST_TUns32 width, GHOST_TUns32 height)
|
||||||
|
{
|
||||||
|
RECT rect = {0, 0, (long)width, (long)height};
|
||||||
|
RECT winrect;
|
||||||
|
|
||||||
|
/* To use swapchain buffers/textures with custom size, the hidden window has to be resized. */
|
||||||
|
|
||||||
|
GetWindowRect(m_hWnd, &winrect);
|
||||||
|
|
||||||
|
WIN32_CHK(AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, false, 0));
|
||||||
|
|
||||||
|
width = rect.right - rect.left;
|
||||||
|
height = rect.bottom - rect.top;
|
||||||
|
|
||||||
|
if (((winrect.right - winrect.left) != width) || ((winrect.bottom - winrect.top) != height)) {
|
||||||
|
return SetWindowPos(m_hWnd,
|
||||||
|
HWND_TOP,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOMOVE | SWP_NOZORDER) ?
|
||||||
|
GHOST_kSuccess :
|
||||||
|
GHOST_kFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GHOST_kSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_TSuccess GHOST_ContextD3D::updateSwapchain(GHOST_TUns32 width, GHOST_TUns32 height)
|
||||||
|
{
|
||||||
|
HRESULT hres;
|
||||||
|
DXGI_SWAP_CHAIN_DESC swapchain_desc;
|
||||||
|
|
||||||
|
m_swapchain->GetDesc(&swapchain_desc);
|
||||||
|
|
||||||
|
if ((swapchain_desc.BufferDesc.Width == width) && (swapchain_desc.BufferDesc.Height == height)) {
|
||||||
|
// Nothing to do.
|
||||||
|
return GHOST_kSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CHECK_HRES \
|
||||||
|
if (hres != S_OK) { \
|
||||||
|
printf("Error updating swapchain (error code %x): %s line %i\n", hres, __FILE__, __LINE__); \
|
||||||
|
} \
|
||||||
|
(void)0
|
||||||
|
|
||||||
|
setDefaultFramebufferSize(width, height);
|
||||||
|
|
||||||
|
m_device_ctx->OMSetRenderTargets(0, nullptr, nullptr);
|
||||||
|
|
||||||
|
m_backbuffer_view->Release();
|
||||||
|
m_device_ctx->ClearState();
|
||||||
|
|
||||||
|
hres = m_swapchain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
|
||||||
|
CHECK_HRES;
|
||||||
|
|
||||||
|
ID3D11Texture2D *buf;
|
||||||
|
hres = m_swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void **)&buf);
|
||||||
|
CHECK_HRES;
|
||||||
|
|
||||||
|
hres = m_device->CreateRenderTargetView(buf, NULL, &m_backbuffer_view);
|
||||||
|
CHECK_HRES;
|
||||||
|
buf->Release();
|
||||||
|
|
||||||
|
return GHOST_kSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_TSuccess GHOST_ContextD3D::setupD3DLib()
|
||||||
|
{
|
||||||
|
if (s_d3d_lib == NULL) {
|
||||||
|
s_d3d_lib = LoadLibraryA("d3d11.dll");
|
||||||
|
|
||||||
|
WIN32_CHK(s_d3d_lib != NULL);
|
||||||
|
|
||||||
|
if (s_d3d_lib == NULL) {
|
||||||
|
fprintf(stderr, "LoadLibrary(\"d3d11.dll\") failed!\n");
|
||||||
|
return GHOST_kFailure;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_D3D11CreateDeviceAndSwapChainFn == NULL) {
|
||||||
|
s_D3D11CreateDeviceAndSwapChainFn = (PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN)GetProcAddress(
|
||||||
|
s_d3d_lib, "D3D11CreateDeviceAndSwapChain");
|
||||||
|
|
||||||
|
WIN32_CHK(s_D3D11CreateDeviceAndSwapChainFn != NULL);
|
||||||
|
|
||||||
|
if (s_D3D11CreateDeviceAndSwapChainFn == NULL) {
|
||||||
|
fprintf(stderr, "GetProcAddress(s_d3d_lib, \"D3D11CreateDeviceAndSwapChain\") failed!\n");
|
||||||
|
return GHOST_kFailure;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GHOST_kSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_TSuccess GHOST_ContextD3D::initializeDrawingContext()
|
||||||
|
{
|
||||||
|
if (setupD3DLib() == GHOST_kFailure) {
|
||||||
|
return GHOST_kFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
DXGI_SWAP_CHAIN_DESC sd{};
|
||||||
|
|
||||||
|
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
sd.SampleDesc.Count = 1;
|
||||||
|
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||||
|
sd.BufferCount = 3;
|
||||||
|
sd.OutputWindow = m_hWnd;
|
||||||
|
sd.Windowed = TRUE;
|
||||||
|
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||||
|
|
||||||
|
HRESULT hres = s_D3D11CreateDeviceAndSwapChainFn(NULL,
|
||||||
|
D3D_DRIVER_TYPE_HARDWARE,
|
||||||
|
NULL,
|
||||||
|
// D3D11_CREATE_DEVICE_DEBUG,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
D3D11_SDK_VERSION,
|
||||||
|
&sd,
|
||||||
|
&m_swapchain,
|
||||||
|
&m_device,
|
||||||
|
NULL,
|
||||||
|
&m_device_ctx);
|
||||||
|
WIN32_CHK(hres == S_OK);
|
||||||
|
|
||||||
|
ID3D11Texture2D *back_buffer;
|
||||||
|
m_swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void **)&back_buffer);
|
||||||
|
|
||||||
|
m_device->CreateRenderTargetView(back_buffer, nullptr, &m_backbuffer_view);
|
||||||
|
back_buffer->Release();
|
||||||
|
|
||||||
|
m_swapchain->Present(0, 0);
|
||||||
|
|
||||||
|
return GHOST_kSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_TSuccess GHOST_ContextD3D::releaseNativeHandles()
|
||||||
|
{
|
||||||
|
return GHOST_kFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_TSuccess GHOST_ContextD3D::blitOpenGLOffscreenContext(GHOST_Context *offscreen_ctx,
|
||||||
|
ID3D11RenderTargetView *render_target,
|
||||||
|
GHOST_TInt32 width,
|
||||||
|
GHOST_TInt32 height)
|
||||||
|
{
|
||||||
|
if (!(WGL_NV_DX_interop && WGL_NV_DX_interop2)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error: Can't render OpenGL framebuffer using Direct3D. NV_DX_interop extension not "
|
||||||
|
"available.");
|
||||||
|
return GHOST_kFailure;
|
||||||
|
}
|
||||||
|
m_device_ctx->OMSetRenderTargets(1, &render_target, nullptr);
|
||||||
|
|
||||||
|
offscreen_ctx->activateDrawingContext();
|
||||||
|
|
||||||
|
GLint fbo;
|
||||||
|
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &fbo);
|
||||||
|
|
||||||
|
if (glshared == NULL) {
|
||||||
|
ID3D11Resource *backbuffer_res;
|
||||||
|
ID3D11Texture2D *backbuffer_tex;
|
||||||
|
render_target->GetResource(&backbuffer_res);
|
||||||
|
backbuffer_res->QueryInterface<ID3D11Texture2D>(&backbuffer_tex);
|
||||||
|
|
||||||
|
glshared = new SharedOpenGLContext(
|
||||||
|
m_device, (GHOST_ContextWGL *)offscreen_ctx, backbuffer_tex);
|
||||||
|
backbuffer_res->Release();
|
||||||
|
backbuffer_tex->Release();
|
||||||
|
|
||||||
|
if (glshared->initialize() == GHOST_kFailure) {
|
||||||
|
return GHOST_kFailure;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SharedOpenGLContext::SharedData *shared = &glshared->m_shared;
|
||||||
|
|
||||||
|
glshared->update(width, height);
|
||||||
|
|
||||||
|
const float clear_col[] = {0.8f, 0.5f, 1.0f, 1.0f};
|
||||||
|
m_device_ctx->ClearRenderTargetView(render_target, clear_col);
|
||||||
|
|
||||||
|
glshared->beginGLOnly();
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, shared->fbo);
|
||||||
|
GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
|
if (err != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
|
fprintf(stderr, "Error: Framebuffer incomplete %u\n", err);
|
||||||
|
return GHOST_kFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not needed, usefull for debugging. */
|
||||||
|
initClearGL();
|
||||||
|
|
||||||
|
/* No glBlitNamedFramebuffer, gotta be 3.3 compatible. */
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, shared->fbo);
|
||||||
|
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||||
|
|
||||||
|
glshared->endGLOnly();
|
||||||
|
|
||||||
|
#ifdef USE_DRAW_D3D_TEST_TRIANGLE
|
||||||
|
drawTestTriangle(m_device.Get(), m_device_ctx.Get(), m_hWnd, width, height);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return GHOST_kSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_TSuccess GHOST_ContextD3D::blitOpenGLOffscreenContext(GHOST_Context *offscreen_ctx,
|
||||||
|
GHOST_TInt32 width,
|
||||||
|
GHOST_TInt32 height)
|
||||||
|
{
|
||||||
|
updateSwapchain(width, height);
|
||||||
|
return blitOpenGLOffscreenContext(offscreen_ctx, m_backbuffer_view, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_DRAW_D3D_TEST_TRIANGLE
|
||||||
|
# pragma comment(lib, "D3DCompiler.lib")
|
||||||
|
|
||||||
|
const static std::string vertex_shader_str{
|
||||||
|
"struct VSOut {"
|
||||||
|
"float3 color : Color;"
|
||||||
|
"float4 pos : SV_POSITION;"
|
||||||
|
"};"
|
||||||
|
|
||||||
|
"VSOut main(float2 pos : Position, float3 color : Color)"
|
||||||
|
"{"
|
||||||
|
" VSOut vso;"
|
||||||
|
" vso.pos = float4(pos.x, pos.y, 0.0f, 1.0f);"
|
||||||
|
" vso.color = color;"
|
||||||
|
" return vso;"
|
||||||
|
"}"};
|
||||||
|
const static std::string pixel_shader_str{
|
||||||
|
" float4 main(float3 color : Color) : SV_TARGET"
|
||||||
|
"{"
|
||||||
|
" return float4(color, 1.0f);"
|
||||||
|
"}"};
|
||||||
|
|
||||||
|
# include <d3dcompiler.h>
|
||||||
|
|
||||||
|
static void drawTestTriangle(ID3D11Device *m_device,
|
||||||
|
ID3D11DeviceContext *m_device_ctx,
|
||||||
|
HWND hwnd,
|
||||||
|
GHOST_TInt32 width,
|
||||||
|
GHOST_TInt32 height)
|
||||||
|
{
|
||||||
|
struct Vertex {
|
||||||
|
float x, y;
|
||||||
|
unsigned char r, g, b, a;
|
||||||
|
};
|
||||||
|
Vertex vertices[] = {
|
||||||
|
{0.0f, 0.5f, 255, 0, 0},
|
||||||
|
{0.5f, -0.5f, 0, 255, 0},
|
||||||
|
{-0.5f, -0.5f, 0, 0, 255},
|
||||||
|
|
||||||
|
};
|
||||||
|
const unsigned int stride = sizeof(Vertex);
|
||||||
|
const unsigned int offset = 0;
|
||||||
|
ID3D11Buffer *vertex_buffer;
|
||||||
|
|
||||||
|
D3D11_BUFFER_DESC buffer_desc{};
|
||||||
|
buffer_desc.Usage = D3D11_USAGE_DEFAULT;
|
||||||
|
buffer_desc.ByteWidth = sizeof(vertices);
|
||||||
|
buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||||
|
|
||||||
|
D3D11_SUBRESOURCE_DATA init_data{};
|
||||||
|
init_data.pSysMem = vertices;
|
||||||
|
|
||||||
|
m_device->CreateBuffer(&buffer_desc, &init_data, &vertex_buffer);
|
||||||
|
m_device_ctx->IASetVertexBuffers(0, 1, &vertex_buffer, &stride, &offset);
|
||||||
|
|
||||||
|
Microsoft::WRL::ComPtr<ID3DBlob> blob;
|
||||||
|
D3DCompile(pixel_shader_str.c_str(),
|
||||||
|
pixel_shader_str.length(),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
"main",
|
||||||
|
"ps_5_0",
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
&blob,
|
||||||
|
NULL);
|
||||||
|
Microsoft::WRL::ComPtr<ID3D11PixelShader> pixel_shader;
|
||||||
|
m_device->CreatePixelShader(
|
||||||
|
blob->GetBufferPointer(), blob->GetBufferSize(), NULL, &pixel_shader);
|
||||||
|
|
||||||
|
D3DCompile(vertex_shader_str.c_str(),
|
||||||
|
vertex_shader_str.length(),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
"main",
|
||||||
|
"vs_5_0",
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
&blob,
|
||||||
|
NULL);
|
||||||
|
Microsoft::WRL::ComPtr<ID3D11VertexShader> vertex_shader;
|
||||||
|
m_device->CreateVertexShader(
|
||||||
|
blob->GetBufferPointer(), blob->GetBufferSize(), NULL, &vertex_shader);
|
||||||
|
|
||||||
|
m_device_ctx->PSSetShader(pixel_shader.Get(), NULL, 0);
|
||||||
|
m_device_ctx->VSSetShader(vertex_shader.Get(), 0, 0);
|
||||||
|
|
||||||
|
Microsoft::WRL::ComPtr<ID3D11InputLayout> input_layout;
|
||||||
|
const D3D11_INPUT_ELEMENT_DESC input_desc[] = {
|
||||||
|
{"Position", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||||
|
{"Color", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||||
|
};
|
||||||
|
m_device->CreateInputLayout(input_desc,
|
||||||
|
(unsigned int)std::size(input_desc),
|
||||||
|
blob->GetBufferPointer(),
|
||||||
|
blob->GetBufferSize(),
|
||||||
|
&input_layout);
|
||||||
|
m_device_ctx->IASetInputLayout(input_layout.Get());
|
||||||
|
|
||||||
|
m_device_ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||||
|
|
||||||
|
D3D11_VIEWPORT viewport = {};
|
||||||
|
viewport.Width = width;
|
||||||
|
viewport.Height = height;
|
||||||
|
viewport.MaxDepth = 1;
|
||||||
|
m_device_ctx->RSSetViewports(1, &viewport);
|
||||||
|
|
||||||
|
m_device_ctx->Draw(std::size(vertices), 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
141
intern/ghost/intern/GHOST_ContextD3D.h
Normal file
141
intern/ghost/intern/GHOST_ContextD3D.h
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup GHOST
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GHOST_CONTEXTD3D_H__
|
||||||
|
#define __GHOST_CONTEXTD3D_H__
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
# error WIN32 only!
|
||||||
|
#endif // WIN32
|
||||||
|
|
||||||
|
#include <D3D11.h>
|
||||||
|
|
||||||
|
#include "GHOST_Context.h"
|
||||||
|
|
||||||
|
class GHOST_ContextD3D : public GHOST_Context {
|
||||||
|
/* XR code needs low level graphics data to send to OpenXR. */
|
||||||
|
friend class GHOST_XrGraphicsBindingD3D;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GHOST_ContextD3D(bool stereoVisual, HWND hWnd);
|
||||||
|
~GHOST_ContextD3D();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swaps front and back buffers of a window.
|
||||||
|
* \return A boolean success indicator.
|
||||||
|
*/
|
||||||
|
GHOST_TSuccess swapBuffers();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activates the drawing context of this window.
|
||||||
|
* \return A boolean success indicator.
|
||||||
|
*/
|
||||||
|
GHOST_TSuccess activateDrawingContext();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release the drawing context of the calling thread.
|
||||||
|
* \return A boolean success indicator.
|
||||||
|
*/
|
||||||
|
GHOST_TSuccess releaseDrawingContext();
|
||||||
|
|
||||||
|
GHOST_TSuccess setDefaultFramebufferSize(GHOST_TUns32 width, GHOST_TUns32 height);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call immediately after new to initialize. If this fails then immediately delete the object.
|
||||||
|
* \return Indication as to whether initialization has succeeded.
|
||||||
|
*/
|
||||||
|
GHOST_TSuccess initializeDrawingContext();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the drawing context of this window. Needed
|
||||||
|
* whenever the window is changed.
|
||||||
|
* \return Indication of success.
|
||||||
|
*/
|
||||||
|
GHOST_TSuccess updateDrawingContext()
|
||||||
|
{
|
||||||
|
return GHOST_kFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if it is OK for a remove the native display
|
||||||
|
* \return Indication as to whether removal has succeeded.
|
||||||
|
*/
|
||||||
|
GHOST_TSuccess releaseNativeHandles();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the swap interval for swapBuffers.
|
||||||
|
* \param interval The swap interval to use.
|
||||||
|
* \return A boolean success indicator.
|
||||||
|
*/
|
||||||
|
GHOST_TSuccess setSwapInterval(int /*interval*/)
|
||||||
|
{
|
||||||
|
return GHOST_kFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current swap interval for swapBuffers.
|
||||||
|
* \param intervalOut Variable to store the swap interval if it can be read.
|
||||||
|
* \return Whether the swap interval can be read.
|
||||||
|
*/
|
||||||
|
GHOST_TSuccess getSwapInterval(int &)
|
||||||
|
{
|
||||||
|
return GHOST_kFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the OpenGL framebuffer associated with the OpenGL context
|
||||||
|
* \return The ID of an OpenGL framebuffer object.
|
||||||
|
*/
|
||||||
|
unsigned int getDefaultFramebuffer()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_TSuccess blitOpenGLOffscreenContext(GHOST_Context *offscreen_ctx,
|
||||||
|
GHOST_TInt32 width,
|
||||||
|
GHOST_TInt32 height);
|
||||||
|
GHOST_TSuccess blitOpenGLOffscreenContext(GHOST_Context *offscreen_ctx,
|
||||||
|
ID3D11RenderTargetView *render_target,
|
||||||
|
GHOST_TInt32 width,
|
||||||
|
GHOST_TInt32 height);
|
||||||
|
|
||||||
|
bool isUpsideDown() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GHOST_TSuccess setupD3DLib();
|
||||||
|
GHOST_TSuccess updateSwapchain(GHOST_TUns32 width, GHOST_TUns32 height);
|
||||||
|
|
||||||
|
static HMODULE s_d3d_lib;
|
||||||
|
static PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN s_D3D11CreateDeviceAndSwapChainFn;
|
||||||
|
|
||||||
|
HWND m_hWnd;
|
||||||
|
|
||||||
|
ID3D11Device *m_device;
|
||||||
|
ID3D11DeviceContext *m_device_ctx;
|
||||||
|
IDXGISwapChain *m_swapchain;
|
||||||
|
ID3D11RenderTargetView *m_backbuffer_view;
|
||||||
|
|
||||||
|
class SharedOpenGLContext *glshared{nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __GHOST_CONTEXTD3D_H__ */
|
||||||
@@ -208,7 +208,7 @@ GHOST_ContextEGL::GHOST_ContextEGL(bool stereoVisual,
|
|||||||
EGLint contextFlags,
|
EGLint contextFlags,
|
||||||
EGLint contextResetNotificationStrategy,
|
EGLint contextResetNotificationStrategy,
|
||||||
EGLenum api)
|
EGLenum api)
|
||||||
: GHOST_Context(stereoVisual),
|
: GHOST_Context(GHOST_kDrawingContextTypeOpenGL, stereoVisual),
|
||||||
m_nativeDisplay(nativeDisplay),
|
m_nativeDisplay(nativeDisplay),
|
||||||
m_nativeWindow(nativeWindow),
|
m_nativeWindow(nativeWindow),
|
||||||
m_contextProfileMask(contextProfileMask),
|
m_contextProfileMask(contextProfileMask),
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ GHOST_ContextGLX::GHOST_ContextGLX(bool stereoVisual,
|
|||||||
int contextMinorVersion,
|
int contextMinorVersion,
|
||||||
int contextFlags,
|
int contextFlags,
|
||||||
int contextResetNotificationStrategy)
|
int contextResetNotificationStrategy)
|
||||||
: GHOST_Context(stereoVisual),
|
: GHOST_Context(GHOST_kDrawingContextTypeOpenGL, stereoVisual),
|
||||||
m_display(display),
|
m_display(display),
|
||||||
m_fbconfig(fbconfig),
|
m_fbconfig(fbconfig),
|
||||||
m_window(window),
|
m_window(window),
|
||||||
@@ -273,6 +273,7 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext()
|
|||||||
m_window = (Window)glXCreatePbuffer(m_display, framebuffer_config[0], pbuffer_attribs);
|
m_window = (Window)glXCreatePbuffer(m_display, framebuffer_config[0], pbuffer_attribs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_fbconfig = framebuffer_config[0];
|
||||||
XFree(framebuffer_config);
|
XFree(framebuffer_config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
class GHOST_ContextGLX : public GHOST_Context {
|
class GHOST_ContextGLX : public GHOST_Context {
|
||||||
|
/* XR code needs low level graphics data to send to OpenXR. */
|
||||||
|
friend class GHOST_XrGraphicsBindingOpenGL;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user