The open source OpenXR runtime

st/oxr: Add extension XR_FB_passthrough

dengkail c57976c2 6876de1d

+864
+4
CMakeLists.txt
··· 422 422 if(NOT DEFINED XRT_FEATURE_OPENXR_LAYER_FB_DEPTH_TEST) 423 423 set(XRT_FEATURE_OPENXR_LAYER_FB_DEPTH_TEST OFF) 424 424 endif() 425 + if(NOT DEFINED XRT_FEATURE_OPENXR_LAYER_PASSTHROUGH) 426 + set(XRT_FEATURE_OPENXR_LAYER_PASSTHROUGH OFF) 427 + endif() 425 428 426 429 # Defaults for OpenXR spaces 427 430 if(NOT DEFINED XRT_FEATURE_OPENXR_SPACE_LOCAL_FLOOR) ··· 632 635 message(STATUS "# FEATURE_OPENXR_LAYER_EQUIRECT1: ${XRT_FEATURE_OPENXR_LAYER_EQUIRECT1}") 633 636 message(STATUS "# FEATURE_OPENXR_LAYER_EQUIRECT2: ${XRT_FEATURE_OPENXR_LAYER_EQUIRECT2}") 634 637 message(STATUS "# FEATURE_OPENXR_LAYER_FB_ALPHA_BLEND: ${XRT_FEATURE_OPENXR_LAYER_FB_ALPHA_BLEND}") 638 + message(STATUS "# FEATURE_OPENXR_LAYER_PASSTHROUGH: ${XRT_FEATURE_OPENXR_LAYER_PASSTHROUGH}") 635 639 message(STATUS "# FEATURE_OPENXR_LAYER_FB_IMAGE_LAYOUT ${XRT_FEATURE_OPENXR_LAYER_FB_IMAGE_LAYOUT}") 636 640 message(STATUS "# FEATURE_OPENXR_LAYER_FB_SETTINGS: ${XRT_FEATURE_OPENXR_LAYER_FB_SETTINGS}") 637 641 message(STATUS "# FEATURE_OPENXR_LAYER_FB_DEPTH_TEST: ${XRT_FEATURE_OPENXR_LAYER_FB_DEPTH_TEST}")
+1
scripts/generate_oxr_ext_support.py
··· 70 70 ['XR_FB_composition_layer_settings', 'XRT_FEATURE_OPENXR_LAYER_FB_SETTINGS'], 71 71 ['XR_FB_composition_layer_depth_test', 'XRT_FEATURE_OPENXR_LAYER_FB_DEPTH_TEST'], 72 72 ['XR_FB_display_refresh_rate', 'XRT_FEATURE_OPENXR_DISPLAY_REFRESH_RATE'], 73 + ['XR_FB_passthrough', 'XRT_FEATURE_OPENXR_LAYER_PASSTHROUGH'], 73 74 ['XR_ML_ml2_controller_interaction', 'XRT_FEATURE_OPENXR_INTERACTION_ML2'], 74 75 ['XR_MND_headless', 'XRT_FEATURE_OPENXR_HEADLESS'], 75 76 ['XR_MND_swapchain_usage_input_attachment_bit'],
+127
src/xrt/include/xrt/xrt_compositor.h
··· 82 82 XRT_LAYER_CYLINDER, 83 83 XRT_LAYER_EQUIRECT1, 84 84 XRT_LAYER_EQUIRECT2, 85 + XRT_LAYER_PASSTHROUGH 85 86 }; 86 87 87 88 /*! ··· 356 357 }; 357 358 358 359 /*! 360 + * @interface xrt_passthrough 361 + */ 362 + struct xrt_passthrough 363 + { 364 + bool paused; 365 + }; 366 + 367 + /*! 368 + * @interface xrt_passthrough_layer 369 + */ 370 + struct xrt_passthrough_layer 371 + { 372 + bool paused; 373 + }; 374 + 375 + /*! 376 + * All the pure data values associated with a passthrough layer. 377 + * 378 + * The @ref xrt_swapchain references and @ref xrt_device are provided outside of 379 + * this struct. 380 + */ 381 + struct xrt_layer_passthrough_data 382 + { 383 + struct xrt_passthrough xrt_pt; 384 + struct xrt_passthrough_layer xrt_pl; 385 + }; 386 + 387 + /*! 359 388 * All the pure data values associated with a composition layer. 360 389 * 361 390 * The @ref xrt_swapchain references and @ref xrt_device are provided outside of ··· 436 465 struct xrt_layer_cylinder_data cylinder; 437 466 struct xrt_layer_equirect1_data equirect1; 438 467 struct xrt_layer_equirect2_data equirect2; 468 + struct xrt_layer_passthrough_data passthrough; 439 469 }; 440 470 }; 441 471 ··· 862 892 }; 863 893 864 894 /*! 895 + * Passthrough creation info. 896 + */ 897 + struct xrt_passthrough_create_info 898 + { 899 + enum xrt_passthrough_create_flags create; 900 + }; 901 + 902 + /*! 903 + * Passthrough layer creation info. 904 + */ 905 + struct xrt_passthrough_layer_create_info 906 + { 907 + enum xrt_passthrough_create_flags create; 908 + enum xrt_passthrough_purpose_flags purpose; 909 + }; 910 + 911 + /*! 865 912 * Struct used to negotiate properties of a swapchain that is created outside 866 913 * of the compositor. Often used by a client compositor or IPC layer to allocate 867 914 * the swapchain images and then pass them into the native compositor. ··· 990 1037 xrt_graphics_sync_handle_t *out_handle, 991 1038 struct xrt_compositor_semaphore **out_xcsem); 992 1039 /*! @} */ 1040 + 1041 + /*! 1042 + * Create a passthrough. 1043 + */ 1044 + xrt_result_t (*create_passthrough)(struct xrt_compositor *xc, const struct xrt_passthrough_create_info *info); 1045 + 1046 + 1047 + /*! 1048 + * Create a passthrough layer. 1049 + */ 1050 + xrt_result_t (*create_passthrough_layer)(struct xrt_compositor *xc, 1051 + const struct xrt_passthrough_layer_create_info *info); 1052 + /*! 1053 + * Destroy a passthrough. 1054 + */ 1055 + xrt_result_t (*destroy_passthrough)(struct xrt_compositor *xc); 993 1056 994 1057 /*! 995 1058 * @name Function pointers for session functions ··· 1257 1320 const struct xrt_layer_data *data); 1258 1321 1259 1322 /*! 1323 + * Adds a passthrough layer for submission. 1324 + * 1325 + * @param xc Self pointer 1326 + * @param xdev The device the layer is relative to. 1327 + * @param data All of the pure data bits (not pointers/handles), 1328 + * including what part of the supplied swapchain 1329 + * object to use. 1330 + */ 1331 + xrt_result_t (*layer_passthrough)(struct xrt_compositor *xc, 1332 + struct xrt_device *xdev, 1333 + const struct xrt_layer_data *data); 1334 + 1335 + /*! 1260 1336 * @brief Commits all of the submitted layers. 1261 1337 * 1262 1338 * Only after this call will the compositor actually use the layers. ··· 1419 1495 1420 1496 /*! @} */ 1421 1497 1498 + /*! 1499 + * @copydoc xrt_compositor::create_passthrough 1500 + * 1501 + * Helper for calling through the function pointer. 1502 + * 1503 + * @public @memberof xrt_compositor 1504 + */ 1505 + static inline xrt_result_t 1506 + xrt_comp_create_passthrough(struct xrt_compositor *xc, const struct xrt_passthrough_create_info *info) 1507 + { 1508 + return xc->create_passthrough(xc, info); 1509 + } 1510 + 1511 + /*! 1512 + * @copydoc xrt_compositor::create_passthrough_layer 1513 + * 1514 + * Helper for calling through the function pointer. 1515 + * 1516 + * @public @memberof xrt_compositor 1517 + */ 1518 + static inline xrt_result_t 1519 + xrt_comp_create_passthrough_layer(struct xrt_compositor *xc, const struct xrt_passthrough_layer_create_info *info) 1520 + { 1521 + return xc->create_passthrough_layer(xc, info); 1522 + } 1523 + 1524 + /*! 1525 + * @copydoc xrt_compositor::destroy_passthrough 1526 + * 1527 + * Helper for calling through the function pointer. 1528 + * 1529 + * @public @memberof xrt_compositor 1530 + */ 1531 + static inline xrt_result_t 1532 + xrt_comp_destroy_passthrough(struct xrt_compositor *xc) 1533 + { 1534 + return xc->destroy_passthrough(xc); 1535 + } 1422 1536 1423 1537 /*! 1424 1538 * @name Session methods ··· 1679 1793 const struct xrt_layer_data *data) 1680 1794 { 1681 1795 return xc->layer_equirect2(xc, xdev, xsc, data); 1796 + } 1797 + 1798 + /*! 1799 + * @copydoc xrt_compositor::layer_passthrough 1800 + * 1801 + * Helper for calling through the function pointer. 1802 + * 1803 + * @public @memberof xrt_compositor 1804 + */ 1805 + static inline xrt_result_t 1806 + xrt_comp_layer_passthrough(struct xrt_compositor *xc, struct xrt_device *xdev, const struct xrt_layer_data *data) 1807 + { 1808 + return xc->layer_passthrough(xc, xdev, data); 1682 1809 } 1683 1810 1684 1811 /*!
+1
src/xrt/include/xrt/xrt_config_build.h.cmake_in
··· 47 47 #cmakedefine XRT_FEATURE_OPENXR_LAYER_EQUIRECT1 48 48 #cmakedefine XRT_FEATURE_OPENXR_LAYER_EQUIRECT2 49 49 #cmakedefine XRT_FEATURE_OPENXR_LAYER_FB_ALPHA_BLEND 50 + #cmakedefine XRT_FEATURE_OPENXR_LAYER_PASSTHROUGH 50 51 #cmakedefine XRT_FEATURE_OPENXR_LAYER_FB_IMAGE_LAYOUT 51 52 #cmakedefine XRT_FEATURE_OPENXR_LAYER_FB_SETTINGS 52 53 #cmakedefine XRT_FEATURE_OPENXR_LAYER_FB_DEPTH_TEST
+41
src/xrt/include/xrt/xrt_defines.h
··· 116 116 #define XRT_MAX_DEVICE_BLEND_MODES 3 117 117 118 118 /*! 119 + * Special flags for creating passthrough. 120 + */ 121 + enum xrt_passthrough_create_flags 122 + { 123 + //! Start the passthrough on creation 124 + XRT_PASSTHROUGH_IS_RUNNING_AT_CREATION = (1 << 0), 125 + //! Our compositor just ignores this bit. 126 + XRT_PASSTHROUGH_LAYER_DEPTH = (1 << 1), 127 + }; 128 + 129 + /*! 130 + * Specify additional state change behavior. 131 + */ 132 + enum xrt_passthrough_state 133 + { 134 + //! Passthrough system requires reinitialization. 135 + XRT_PASSTHROUGH_STATE_CHANGED_REINIT_REQUIRED_BIT = (1 << 0), 136 + //! Non-recoverable error has occurred. 137 + XRT_PASSTHROUGH_STATE_CHANGED_NON_RECOVERABLE_ERROR_BIT = (1 << 1), 138 + //! A recoverable error has occurred. 139 + XRT_PASSTHROUGH_STATE_CHANGED_RECOVERABLE_ERROR_BIT = (1 << 2), 140 + //! The runtime has recovered from a previous error and is functioning normally. 141 + XRT_PASSTHROUGH_STATE_CHANGED_RESTORED_ERROR_BIT = (1 << 3), 142 + }; 143 + 144 + /*! 145 + * Specify the kind of passthrough behavior the layer provides. 146 + */ 147 + enum xrt_passthrough_purpose_flags 148 + { 149 + //! Fullscreen layer 150 + XRT_PASSTHROUGH_LAYER_PURPOSE_RECONSTRUCTION = (1 << 0), 151 + //! Projected layer. 152 + XRT_PASSTHROUGH_LAYER_PURPOSE_PROJECTED = (1 << 1), 153 + //! Provided by XR_FB_passthrough_keyboard_hands 154 + XRT_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_HANDS = 1000203001, 155 + //! Provided by XR_FB_passthrough_keyboard_hands 156 + XRT_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_MASKED_HANDS = 1000203002, 157 + }; 158 + 159 + /*! 119 160 * Which distortion model does the device expose, 120 161 * used both as a bitfield and value. 121 162 */
+13
src/xrt/include/xrt/xrt_session.h
··· 58 58 59 59 //! The performance of the session has changed 60 60 XRT_SESSION_EVENT_PERFORMANCE_CHANGE = 7, 61 + 62 + //! The passthrough state of the session has changed 63 + XRT_SESSION_EVENT_PASSTHRU_STATE_CHANGE = 8, 61 64 }; 62 65 63 66 /*! ··· 153 156 }; 154 157 155 158 /*! 159 + * Passthrough state change event. 160 + */ 161 + struct xrt_session_event_passthrough_state_change 162 + { 163 + enum xrt_session_event_type type; 164 + enum xrt_passthrough_state state; 165 + }; 166 + 167 + /*! 156 168 * Union of all session events, used to return multiple events through one call. 157 169 * Each event struct must start with a @ref xrt_session_event_type field. 158 170 * ··· 168 180 struct xrt_session_event_display_refresh_rate_change display; 169 181 struct xrt_session_event_reference_space_change_pending ref_change; 170 182 struct xrt_session_event_perf_change performance; 183 + struct xrt_session_event_passthrough_state_change passthru; 171 184 }; 172 185 173 186 /*!
+4
src/xrt/state_trackers/oxr/CMakeLists.txt
··· 104 104 target_compile_definitions(st_oxr PRIVATE XR_USE_PLATFORM_WIN32) 105 105 endif() 106 106 107 + if(XRT_FEATURE_OPENXR_LAYER_PASSTHROUGH) 108 + target_sources(st_oxr PRIVATE oxr_api_passthrough.c oxr_passthrough.c) 109 + endif() 110 + 107 111 target_link_libraries( 108 112 st_oxr 109 113 PRIVATE
+38
src/xrt/state_trackers/oxr/oxr_api_funcs.h
··· 570 570 XRAPI_ATTR XrResult XRAPI_CALL 571 571 oxr_xrRequestDisplayRefreshRateFB(XrSession session, float displayRefreshRate); 572 572 573 + /* 574 + * 575 + * oxr_api_passthrough.c 576 + * 577 + */ 578 + #ifdef OXR_HAVE_FB_passthrough 579 + XRAPI_ATTR XrResult XRAPI_CALL 580 + oxr_xrCreateGeometryInstanceFB(XrSession session, 581 + const XrGeometryInstanceCreateInfoFB *createInfo, 582 + XrGeometryInstanceFB *outGeometryInstance); 583 + XRAPI_ATTR XrResult XRAPI_CALL 584 + oxr_xrCreatePassthroughFB(XrSession session, 585 + const XrPassthroughCreateInfoFB *createInfo, 586 + XrPassthroughFB *outPassthrough); 587 + XRAPI_ATTR XrResult XRAPI_CALL 588 + oxr_xrCreatePassthroughLayerFB(XrSession session, 589 + const XrPassthroughLayerCreateInfoFB *createInfo, 590 + XrPassthroughLayerFB *outLayer); 591 + XRAPI_ATTR XrResult XRAPI_CALL 592 + oxr_xrDestroyGeometryInstanceFB(XrGeometryInstanceFB instance); 593 + XRAPI_ATTR XrResult XRAPI_CALL 594 + oxr_xrDestroyPassthroughFB(XrPassthroughFB passthrough); 595 + XRAPI_ATTR XrResult XRAPI_CALL 596 + oxr_xrDestroyPassthroughLayerFB(XrPassthroughLayerFB layer); 597 + XRAPI_ATTR XrResult XRAPI_CALL 598 + oxr_xrGeometryInstanceSetTransformFB(XrGeometryInstanceFB instance, 599 + const XrGeometryInstanceTransformFB *transformation); 600 + XRAPI_ATTR XrResult XRAPI_CALL 601 + oxr_xrPassthroughLayerPauseFB(XrPassthroughLayerFB layer); 602 + XRAPI_ATTR XrResult XRAPI_CALL 603 + oxr_xrPassthroughLayerResumeFB(XrPassthroughLayerFB layer); 604 + XRAPI_ATTR XrResult XRAPI_CALL 605 + oxr_xrPassthroughLayerSetStyleFB(XrPassthroughLayerFB layer, const XrPassthroughStyleFB *style); 606 + XRAPI_ATTR XrResult XRAPI_CALL 607 + oxr_xrPassthroughPauseFB(XrPassthroughFB passthrough); 608 + XRAPI_ATTR XrResult XRAPI_CALL 609 + oxr_xrPassthroughStartFB(XrPassthroughFB passthrough); 610 + #endif 573 611 /*! 574 612 * @} 575 613 */
+15
src/xrt/state_trackers/oxr/oxr_api_negotiate.c
··· 246 246 ENTRY_IF_EXT(xrRequestDisplayRefreshRateFB, FB_display_refresh_rate); 247 247 #endif 248 248 249 + #ifdef OXR_HAVE_FB_passthrough 250 + ENTRY_IF_EXT(xrCreateGeometryInstanceFB, FB_passthrough); 251 + ENTRY_IF_EXT(xrCreatePassthroughFB, FB_passthrough); 252 + ENTRY_IF_EXT(xrCreatePassthroughLayerFB, FB_passthrough); 253 + ENTRY_IF_EXT(xrDestroyGeometryInstanceFB, FB_passthrough); 254 + ENTRY_IF_EXT(xrDestroyPassthroughFB, FB_passthrough); 255 + ENTRY_IF_EXT(xrDestroyPassthroughLayerFB, FB_passthrough); 256 + ENTRY_IF_EXT(xrGeometryInstanceSetTransformFB, FB_passthrough); 257 + ENTRY_IF_EXT(xrPassthroughLayerPauseFB, FB_passthrough); 258 + ENTRY_IF_EXT(xrPassthroughLayerResumeFB, FB_passthrough); 259 + ENTRY_IF_EXT(xrPassthroughLayerSetStyleFB, FB_passthrough); 260 + ENTRY_IF_EXT(xrPassthroughPauseFB, FB_passthrough); 261 + ENTRY_IF_EXT(xrPassthroughStartFB, FB_passthrough); 262 + #endif // OXR_HAVE_FB_passthrough 263 + 249 264 #ifdef OXR_HAVE_EXT_debug_utils 250 265 ENTRY_IF_EXT(xrSetDebugUtilsObjectNameEXT, EXT_debug_utils); 251 266 ENTRY_IF_EXT(xrCreateDebugUtilsMessengerEXT, EXT_debug_utils);
+205
src/xrt/state_trackers/oxr/oxr_api_passthrough.c
··· 1 + // Copyright 2023-2024, Qualcomm Innovation Center, Inc. 2 + // SPDX-License-Identifier: BSL-1.0 3 + /*! 4 + * @file 5 + * @brief passthrough related API entrypoint functions. 6 + * @author Knox Liu <quic_dengkail@qti.qualcomm.com> 7 + * @ingroup oxr_api 8 + */ 9 + 10 + #include "oxr_objects.h" 11 + #include "oxr_logger.h" 12 + #include "oxr_handle.h" 13 + 14 + #include "util/u_debug.h" 15 + #include "util/u_trace_marker.h" 16 + 17 + #include "oxr_api_funcs.h" 18 + #include "oxr_api_verify.h" 19 + #include "oxr_chain.h" 20 + #include "oxr_subaction.h" 21 + 22 + #include <stdio.h> 23 + #include <inttypes.h> 24 + 25 + XrResult 26 + oxr_xrCreateGeometryInstanceFB(XrSession session, 27 + const XrGeometryInstanceCreateInfoFB *createInfo, 28 + XrGeometryInstanceFB *outGeometryInstance) 29 + { 30 + OXR_TRACE_MARKER(); 31 + struct oxr_logger log; 32 + oxr_log_init(&log, "oxr_xrCreateGeometryInstanceFB"); 33 + return oxr_error(&log, XR_ERROR_RUNTIME_FAILURE, " not implemented"); 34 + } 35 + 36 + XrResult 37 + oxr_xrCreatePassthroughFB(XrSession session, 38 + const XrPassthroughCreateInfoFB *createInfo, 39 + XrPassthroughFB *outPassthrough) 40 + { 41 + OXR_TRACE_MARKER(); 42 + 43 + struct oxr_session *sess; 44 + struct oxr_logger log; 45 + OXR_VERIFY_SESSION_AND_INIT_LOG(&log, session, sess, "oxr_xrCreatePassthroughFB"); 46 + OXR_VERIFY_SESSION_NOT_LOST(&log, sess); 47 + OXR_VERIFY_ARG_TYPE_AND_NOT_NULL(&log, createInfo, XR_TYPE_PASSTHROUGH_CREATE_INFO_FB); 48 + OXR_VERIFY_PASSTHROUGH_FLAGS(&log, createInfo->flags); 49 + 50 + struct oxr_passthrough *passthrough; 51 + XrResult ret = oxr_passthrough_create(&log, sess, createInfo, &passthrough); 52 + if (ret != XR_SUCCESS) { 53 + return ret; 54 + } 55 + 56 + *outPassthrough = oxr_passthrough_to_openxr(passthrough); 57 + 58 + return oxr_session_success_result(sess); 59 + } 60 + 61 + XrResult 62 + oxr_xrCreatePassthroughLayerFB(XrSession session, 63 + const XrPassthroughLayerCreateInfoFB *createInfo, 64 + XrPassthroughLayerFB *outLayer) 65 + { 66 + OXR_TRACE_MARKER(); 67 + 68 + struct oxr_session *sess; 69 + struct oxr_logger log; 70 + OXR_VERIFY_SESSION_AND_INIT_LOG(&log, session, sess, "oxr_xrCreatePassthroughLayerFB"); 71 + OXR_VERIFY_SESSION_NOT_LOST(&log, sess); 72 + OXR_VERIFY_ARG_TYPE_AND_NOT_NULL(&log, createInfo, XR_TYPE_PASSTHROUGH_LAYER_CREATE_INFO_FB); 73 + OXR_VERIFY_ARG_NOT_NULL(&log, createInfo->passthrough); 74 + OXR_VERIFY_PASSTHROUGH_FLAGS(&log, createInfo->flags); 75 + OXR_VERIFY_PASSTHROUGH_LAYER_PURPOSE(&log, createInfo->purpose); 76 + 77 + struct oxr_passthrough_layer *passthroughLayer; 78 + XrResult ret = oxr_passthrough_layer_create(&log, sess, createInfo, &passthroughLayer); 79 + if (ret != XR_SUCCESS) { 80 + return ret; 81 + } 82 + 83 + *outLayer = oxr_passthrough_layer_to_openxr(passthroughLayer); 84 + 85 + return oxr_session_success_result(sess); 86 + } 87 + 88 + XrResult 89 + oxr_xrDestroyGeometryInstanceFB(XrGeometryInstanceFB instance) 90 + { 91 + OXR_TRACE_MARKER(); 92 + struct oxr_logger log; 93 + oxr_log_init(&log, "oxr_xrDestroyGeometryInstanceFB"); 94 + return oxr_error(&log, XR_ERROR_RUNTIME_FAILURE, " not implemented"); 95 + } 96 + 97 + XrResult 98 + oxr_xrDestroyPassthroughFB(XrPassthroughFB passthrough) 99 + { 100 + OXR_TRACE_MARKER(); 101 + 102 + struct oxr_passthrough *pt; 103 + struct oxr_logger log; 104 + OXR_VERIFY_PASSTHROUGH_AND_INIT_LOG(&log, passthrough, pt, "oxr_xrDestroyPassthroughFB"); 105 + 106 + xrt_comp_destroy_passthrough(pt->sess->compositor); 107 + 108 + return oxr_handle_destroy(&log, &pt->handle); 109 + } 110 + 111 + XrResult 112 + oxr_xrDestroyPassthroughLayerFB(XrPassthroughLayerFB layer) 113 + { 114 + OXR_TRACE_MARKER(); 115 + 116 + struct oxr_passthrough_layer *pl; 117 + struct oxr_logger log; 118 + OXR_VERIFY_PASSTHROUGH_LAYER_AND_INIT_LOG(&log, layer, pl, "oxr_xrDestroyPassthroughLayerFB"); 119 + 120 + return oxr_handle_destroy(&log, &pl->handle); 121 + } 122 + 123 + XrResult 124 + oxr_xrGeometryInstanceSetTransformFB(XrGeometryInstanceFB instance, const XrGeometryInstanceTransformFB *transformation) 125 + { 126 + OXR_TRACE_MARKER(); 127 + struct oxr_logger log; 128 + oxr_log_init(&log, "oxr_xrGeometryInstanceSetTransformFB"); 129 + return oxr_error(&log, XR_ERROR_RUNTIME_FAILURE, " not implemented"); 130 + } 131 + 132 + XrResult 133 + oxr_xrPassthroughLayerPauseFB(XrPassthroughLayerFB layer) 134 + { 135 + OXR_TRACE_MARKER(); 136 + struct oxr_passthrough_layer *pl; 137 + struct oxr_logger log; 138 + OXR_VERIFY_PASSTHROUGH_LAYER_AND_INIT_LOG(&log, layer, pl, "oxr_xrPassthroughLayerPauseFB"); 139 + pl->paused = true; 140 + return XR_SUCCESS; 141 + } 142 + 143 + XrResult 144 + oxr_xrPassthroughLayerResumeFB(XrPassthroughLayerFB layer) 145 + { 146 + OXR_TRACE_MARKER(); 147 + struct oxr_passthrough_layer *pl; 148 + struct oxr_logger log; 149 + OXR_VERIFY_PASSTHROUGH_LAYER_AND_INIT_LOG(&log, layer, pl, "oxr_xrPassthroughLayerResumeFB"); 150 + pl->paused = false; 151 + return XR_SUCCESS; 152 + } 153 + 154 + XrResult 155 + oxr_xrPassthroughLayerSetStyleFB(XrPassthroughLayerFB layer, const XrPassthroughStyleFB *style) 156 + { 157 + OXR_TRACE_MARKER(); 158 + struct oxr_passthrough_layer *pl; 159 + struct oxr_logger log; 160 + OXR_VERIFY_PASSTHROUGH_LAYER_AND_INIT_LOG(&log, layer, pl, "oxr_xrPassthroughLayerResumeFB"); 161 + OXR_VERIFY_ARG_TYPE_AND_NOT_NULL(&log, style, XR_TYPE_PASSTHROUGH_STYLE_FB); 162 + OXR_VERIFY_PASSTHROUGH_LAYER_STYLE(&log, style); 163 + 164 + pl->style = *style; 165 + XrPassthroughStyleFB *next = (XrPassthroughStyleFB *)style->next; 166 + while (next) { 167 + switch (next->type) { 168 + case XR_TYPE_PASSTHROUGH_BRIGHTNESS_CONTRAST_SATURATION_FB: 169 + pl->brightnessContrastSaturation = *(XrPassthroughBrightnessContrastSaturationFB *)next; 170 + break; 171 + case XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_MONO_FB: 172 + pl->monoToMono = *(XrPassthroughColorMapMonoToMonoFB *)next; 173 + break; 174 + case XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_RGBA_FB: 175 + pl->monoToRgba = *(XrPassthroughColorMapMonoToRgbaFB *)next; 176 + break; 177 + } 178 + 179 + next = (XrPassthroughStyleFB *)next->next; 180 + } 181 + 182 + return XR_SUCCESS; 183 + } 184 + 185 + XrResult 186 + oxr_xrPassthroughPauseFB(XrPassthroughFB passthrough) 187 + { 188 + OXR_TRACE_MARKER(); 189 + struct oxr_passthrough *pt; 190 + struct oxr_logger log; 191 + OXR_VERIFY_PASSTHROUGH_AND_INIT_LOG(&log, passthrough, pt, "oxr_xrPassthroughPauseFB"); 192 + pt->paused = true; 193 + return XR_SUCCESS; 194 + } 195 + 196 + XrResult 197 + oxr_xrPassthroughStartFB(XrPassthroughFB passthrough) 198 + { 199 + OXR_TRACE_MARKER(); 200 + struct oxr_passthrough *pt; 201 + struct oxr_logger log; 202 + OXR_VERIFY_PASSTHROUGH_AND_INIT_LOG(&log, passthrough, pt, "oxr_xrPassthroughStartFB"); 203 + pt->paused = false; 204 + return XR_SUCCESS; 205 + }
+35
src/xrt/state_trackers/oxr/oxr_api_verify.h
··· 67 67 OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_hand_tracker, HTRACKER, name, new_thing->sess->sys->inst) 68 68 #define OXR_VERIFY_FORCE_FEEDBACK_AND_INIT_LOG(log, thing, new_thing, name) \ 69 69 OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_force_feedback, FFB, name, new_thing->sess->sys->inst) 70 + #define OXR_VERIFY_PASSTHROUGH_AND_INIT_LOG(log, thing, new_thing, name) \ 71 + OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_passthrough, PASSTHROUGH, name, new_thing->sess->sys->inst) 72 + #define OXR_VERIFY_PASSTHROUGH_LAYER_AND_INIT_LOG(log, thing, new_thing, name) \ 73 + OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_passthrough_layer, PASSTHROUGH_LAYER, name, new_thing->sess->sys->inst) 70 74 // clang-format on 71 75 72 76 #define OXR_VERIFY_INSTANCE_NOT_NULL(log, arg, new_arg) OXR_VERIFY_SET(log, arg, new_arg, oxr_instance, INSTANCE); ··· 229 233 } \ 230 234 } while (false) 231 235 236 + #define OXR_VERIFY_PASSTHROUGH_FLAGS(log, flags) \ 237 + if (flags == 0 || \ 238 + (flags & (XR_PASSTHROUGH_IS_RUNNING_AT_CREATION_BIT_FB | XR_PASSTHROUGH_LAYER_DEPTH_BIT_FB)) == 0) \ 239 + return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, \ 240 + "flags is not a valid combination of XrPassthroughFlagBitsFB values"); 241 + 242 + #define OXR_VERIFY_PASSTHROUGH_LAYER_PURPOSE(log, purpose) \ 243 + if ((purpose != XR_PASSTHROUGH_LAYER_PURPOSE_RECONSTRUCTION_FB && \ 244 + purpose != XR_PASSTHROUGH_LAYER_PURPOSE_PROJECTED_FB && \ 245 + purpose != XR_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_HANDS_FB && \ 246 + purpose != XR_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_MASKED_HANDS_FB)) \ 247 + return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, \ 248 + "purpose is not a valid XrPassthroughLayerPurposeFB value"); 249 + 250 + #define OXR_VERIFY_PASSTHROUGH_LAYER_STYLE(log, style) \ 251 + do { \ 252 + uint32_t duplicate_check = 0; \ 253 + const XrPassthroughStyleFB *next = style->next; \ 254 + while (next) { \ 255 + if (next->type != XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_RGBA_FB && \ 256 + next->type != XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_MONO_FB && \ 257 + next->type != XR_TYPE_PASSTHROUGH_BRIGHTNESS_CONTRAST_SATURATION_FB) \ 258 + return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, \ 259 + "style next structure chain contains invalid pointers"); \ 260 + if ((next->type & duplicate_check) != 0) \ 261 + return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, \ 262 + "style next structure chain contains duplicate items"); \ 263 + duplicate_check |= next->type; \ 264 + next = (const XrPassthroughStyleFB *)next->next; \ 265 + } \ 266 + } while (false) 232 267 233 268 /* 234 269 *
+2
src/xrt/state_trackers/oxr/oxr_defines.h
··· 25 25 #define OXR_XR_DEBUG_SOURCESET (*(uint64_t *)"oxrsrcs\0") 26 26 #define OXR_XR_DEBUG_SOURCE (*(uint64_t *)"oxrsrc_\0") 27 27 #define OXR_XR_DEBUG_HTRACKER (*(uint64_t *)"oxrhtra\0") 28 + #define OXR_XR_DEBUG_PASSTHROUGH (*(uint64_t *)"oxrpass\0") 29 + #define OXR_XR_DEBUG_PASSTHROUGH_LAYER (*(uint64_t *)"oxrptla\0") 28 30 // clang-format on 29 31 30 32 /*!
+22
src/xrt/state_trackers/oxr/oxr_event.c
··· 296 296 } 297 297 #endif // OXR_HAVE_EXT_performance_settings 298 298 299 + #ifdef OXR_HAVE_FB_passthrough 300 + XrResult 301 + oxr_event_push_XrEventDataPassthroughStateChangedFB(struct oxr_logger *log, 302 + struct oxr_session *sess, 303 + XrPassthroughStateChangedFlagsFB flags) 304 + { 305 + struct oxr_instance *inst = sess->sys->inst; 306 + XrEventDataPassthroughStateChangedFB *changed; 307 + struct oxr_event *event = NULL; 308 + 309 + ALLOC(log, inst, &event, &changed); 310 + changed->type = XR_TYPE_EVENT_DATA_PASSTHROUGH_STATE_CHANGED_FB; 311 + changed->flags = flags; 312 + event->result = XR_SUCCESS; 313 + lock(inst); 314 + push(inst, event); 315 + unlock(inst); 316 + 317 + return XR_SUCCESS; 318 + } 319 + #endif // OXR_HAVE_FB_passthrough 320 + 299 321 XrResult 300 322 oxr_event_remove_session_events(struct oxr_logger *log, struct oxr_session *sess) 301 323 {
+10
src/xrt/state_trackers/oxr/oxr_extension_support.h
··· 439 439 #define OXR_EXTENSION_SUPPORT_FB_display_refresh_rate(_) 440 440 #endif 441 441 442 + /* 443 + * XR_FB_passthrough 444 + */ 445 + #if defined(XR_FB_passthrough) && defined(XRT_FEATURE_OPENXR_LAYER_PASSTHROUGH) 446 + #define OXR_HAVE_FB_passthrough 447 + #define OXR_EXTENSION_SUPPORT_FB_passthrough(_) _(FB_passthrough, FB_PASSTHROUGH) 448 + #else 449 + #define OXR_EXTENSION_SUPPORT_FB_passthrough(_) 450 + #endif 442 451 443 452 /* 444 453 * XR_ML_ml2_controller_interaction ··· 648 657 OXR_EXTENSION_SUPPORT_FB_composition_layer_settings(_) \ 649 658 OXR_EXTENSION_SUPPORT_FB_composition_layer_depth_test(_) \ 650 659 OXR_EXTENSION_SUPPORT_FB_display_refresh_rate(_) \ 660 + OXR_EXTENSION_SUPPORT_FB_passthrough(_) \ 651 661 OXR_EXTENSION_SUPPORT_ML_ml2_controller_interaction(_) \ 652 662 OXR_EXTENSION_SUPPORT_MND_headless(_) \ 653 663 OXR_EXTENSION_SUPPORT_MND_swapchain_usage_input_attachment_bit(_) \
+64
src/xrt/state_trackers/oxr/oxr_objects.h
··· 2477 2477 XrHandJointSetEXT hand_joint_set; 2478 2478 }; 2479 2479 2480 + #ifdef OXR_HAVE_FB_passthrough 2481 + 2482 + struct oxr_passthrough 2483 + { 2484 + struct oxr_handle_base handle; 2485 + 2486 + struct oxr_session *sess; 2487 + 2488 + XrPassthroughFlagsFB flags; 2489 + 2490 + bool paused; 2491 + }; 2492 + 2493 + struct oxr_passthrough_layer 2494 + { 2495 + struct oxr_handle_base handle; 2496 + 2497 + struct oxr_session *sess; 2498 + 2499 + XrPassthroughFB passthrough; 2500 + 2501 + XrPassthroughFlagsFB flags; 2502 + 2503 + XrPassthroughLayerPurposeFB purpose; 2504 + 2505 + bool paused; 2506 + 2507 + XrPassthroughStyleFB style; 2508 + XrPassthroughColorMapMonoToRgbaFB monoToRgba; 2509 + XrPassthroughColorMapMonoToMonoFB monoToMono; 2510 + XrPassthroughBrightnessContrastSaturationFB brightnessContrastSaturation; 2511 + }; 2512 + 2513 + XrResult 2514 + oxr_passthrough_create(struct oxr_logger *log, 2515 + struct oxr_session *sess, 2516 + const XrPassthroughCreateInfoFB *createInfo, 2517 + struct oxr_passthrough **out_passthrough); 2518 + 2519 + XrResult 2520 + oxr_passthrough_layer_create(struct oxr_logger *log, 2521 + struct oxr_session *sess, 2522 + const XrPassthroughLayerCreateInfoFB *createInfo, 2523 + struct oxr_passthrough_layer **out_layer); 2524 + 2525 + static inline XrPassthroughFB 2526 + oxr_passthrough_to_openxr(struct oxr_passthrough *passthrough) 2527 + { 2528 + return XRT_CAST_PTR_TO_OXR_HANDLE(XrPassthroughFB, passthrough); 2529 + } 2530 + 2531 + static inline XrPassthroughLayerFB 2532 + oxr_passthrough_layer_to_openxr(struct oxr_passthrough_layer *passthroughLayer) 2533 + { 2534 + return XRT_CAST_PTR_TO_OXR_HANDLE(XrPassthroughLayerFB, passthroughLayer); 2535 + } 2536 + 2537 + XrResult 2538 + oxr_event_push_XrEventDataPassthroughStateChangedFB(struct oxr_logger *log, 2539 + struct oxr_session *sess, 2540 + XrPassthroughStateChangedFlagsFB flags); 2541 + 2542 + #endif // OXR_HAVE_FB_passthrough 2543 + 2480 2544 /*! 2481 2545 * @} 2482 2546 */
+144
src/xrt/state_trackers/oxr/oxr_passthrough.c
··· 1 + // Copyright 2023-2024, Qualcomm Innovation Center, Inc. 2 + // SPDX-License-Identifier: BSL-1.0 3 + /*! 4 + * @file 5 + * @brief passthrough related API entrypoint functions. 6 + * @author Knox Liu <quic_dengkail@qti.qualcomm.com> 7 + * @ingroup oxr_main 8 + */ 9 + 10 + #include <stdio.h> 11 + #include <stdlib.h> 12 + #include <string.h> 13 + 14 + #include "math/m_api.h" 15 + #include "math/m_space.h" 16 + #include "util/u_debug.h" 17 + #include "util/u_misc.h" 18 + 19 + #include "oxr_objects.h" 20 + #include "oxr_logger.h" 21 + #include "oxr_handle.h" 22 + #include "oxr_input_transform.h" 23 + #include "oxr_chain.h" 24 + #include "oxr_pretty_print.h" 25 + 26 + /* 27 + * 28 + * XR_FB_passthrough 29 + * 30 + */ 31 + 32 + static enum xrt_passthrough_create_flags 33 + convert_create_flags(XrPassthroughFlagsFB xr_flags) 34 + { 35 + enum xrt_passthrough_create_flags flags = 0; 36 + 37 + if ((xr_flags & XR_PASSTHROUGH_IS_RUNNING_AT_CREATION_BIT_FB) != 0) { 38 + flags |= XRT_PASSTHROUGH_IS_RUNNING_AT_CREATION; 39 + } 40 + if ((xr_flags & XR_PASSTHROUGH_LAYER_DEPTH_BIT_FB) != 0) { 41 + flags |= XRT_PASSTHROUGH_LAYER_DEPTH; 42 + } 43 + 44 + return flags; 45 + } 46 + 47 + static enum xrt_passthrough_purpose_flags 48 + convert_purpose_flags(XrPassthroughLayerPurposeFB xr_flags) 49 + { 50 + enum xrt_passthrough_purpose_flags flags = 0; 51 + 52 + if ((xr_flags & XR_PASSTHROUGH_LAYER_PURPOSE_RECONSTRUCTION_FB) != 0) { 53 + flags |= XRT_PASSTHROUGH_LAYER_PURPOSE_RECONSTRUCTION; 54 + } 55 + if ((xr_flags & XR_PASSTHROUGH_LAYER_PURPOSE_PROJECTED_FB) != 0) { 56 + flags |= XRT_PASSTHROUGH_LAYER_PURPOSE_PROJECTED; 57 + } 58 + if ((xr_flags & XR_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_HANDS_FB) != 0) { 59 + flags |= XRT_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_HANDS; 60 + } 61 + if ((xr_flags & XR_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_MASKED_HANDS_FB) != 0) { 62 + flags |= XRT_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_MASKED_HANDS; 63 + } 64 + 65 + return flags; 66 + } 67 + 68 + static XrResult 69 + oxr_passthrough_destroy(struct oxr_logger *log, struct oxr_handle_base *hb) 70 + { 71 + struct oxr_passthrough *passthrough = (struct oxr_passthrough *)hb; 72 + free(passthrough); 73 + return XR_SUCCESS; 74 + } 75 + 76 + static XrResult 77 + oxr_passthrough_layer_destroy(struct oxr_logger *log, struct oxr_handle_base *hb) 78 + { 79 + struct oxr_passthrough_layer *passthroughLayer = (struct oxr_passthrough_layer *)hb; 80 + free(passthroughLayer); 81 + return XR_SUCCESS; 82 + } 83 + 84 + XrResult 85 + oxr_passthrough_create(struct oxr_logger *log, 86 + struct oxr_session *sess, 87 + const XrPassthroughCreateInfoFB *createInfo, 88 + struct oxr_passthrough **out_passthrough) 89 + { 90 + struct oxr_instance *inst = sess->sys->inst; 91 + 92 + struct oxr_passthrough *passthrough = NULL; 93 + OXR_ALLOCATE_HANDLE_OR_RETURN(log, passthrough, OXR_XR_DEBUG_PASSTHROUGH, oxr_passthrough_destroy, 94 + &sess->handle); 95 + 96 + passthrough->sess = sess; 97 + passthrough->flags = createInfo->flags; 98 + 99 + xrt_result_t xret = XRT_SUCCESS; 100 + 101 + struct xrt_passthrough_create_info info; 102 + info.create = convert_create_flags(createInfo->flags); 103 + xret = xrt_comp_create_passthrough(sess->compositor, &info); 104 + if (xret != XRT_SUCCESS) { 105 + return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, "Failed to create passthrough"); 106 + } 107 + 108 + *out_passthrough = passthrough; 109 + 110 + return XR_SUCCESS; 111 + } 112 + 113 + XrResult 114 + oxr_passthrough_layer_create(struct oxr_logger *log, 115 + struct oxr_session *sess, 116 + const XrPassthroughLayerCreateInfoFB *createInfo, 117 + struct oxr_passthrough_layer **out_layer) 118 + { 119 + struct oxr_instance *inst = sess->sys->inst; 120 + 121 + struct oxr_passthrough_layer *passthroughLayer = NULL; 122 + OXR_ALLOCATE_HANDLE_OR_RETURN(log, passthroughLayer, OXR_XR_DEBUG_PASSTHROUGH_LAYER, 123 + oxr_passthrough_layer_destroy, &sess->handle); 124 + 125 + passthroughLayer->sess = sess; 126 + passthroughLayer->passthrough = createInfo->passthrough; 127 + passthroughLayer->flags = createInfo->flags; 128 + passthroughLayer->purpose = createInfo->purpose; 129 + 130 + xrt_result_t xret = XRT_SUCCESS; 131 + 132 + struct xrt_passthrough_layer_create_info info; 133 + info.create = convert_create_flags(createInfo->flags); 134 + info.purpose = convert_purpose_flags(createInfo->purpose); 135 + 136 + xret = xrt_comp_create_passthrough_layer(sess->compositor, &info); 137 + if (xret != XRT_SUCCESS) { 138 + return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, "Failed to create passthrough layer"); 139 + } 140 + 141 + *out_layer = passthroughLayer; 142 + 143 + return XR_SUCCESS; 144 + }
+27
src/xrt/state_trackers/oxr/oxr_session.c
··· 314 314 return oxr_session_success_result(sess); 315 315 } 316 316 317 + #ifdef OXR_HAVE_FB_passthrough 318 + static inline XrPassthroughStateChangedFlagsFB 319 + xrt_to_passthrough_state_flags(enum xrt_passthrough_state state) 320 + { 321 + XrPassthroughStateChangedFlagsFB res = 0; 322 + if (state & XRT_PASSTHROUGH_STATE_CHANGED_REINIT_REQUIRED_BIT) { 323 + res |= XR_PASSTHROUGH_STATE_CHANGED_REINIT_REQUIRED_BIT_FB; 324 + } 325 + if (state & XRT_PASSTHROUGH_STATE_CHANGED_NON_RECOVERABLE_ERROR_BIT) { 326 + res |= XR_PASSTHROUGH_STATE_CHANGED_NON_RECOVERABLE_ERROR_BIT_FB; 327 + } 328 + if (state & XRT_PASSTHROUGH_STATE_CHANGED_RECOVERABLE_ERROR_BIT) { 329 + res |= XR_PASSTHROUGH_STATE_CHANGED_RECOVERABLE_ERROR_BIT_FB; 330 + } 331 + if (state & XRT_PASSTHROUGH_STATE_CHANGED_RESTORED_ERROR_BIT) { 332 + res |= XR_PASSTHROUGH_STATE_CHANGED_RESTORED_ERROR_BIT_FB; 333 + } 334 + return res; 335 + } 336 + #endif 337 + 317 338 XrResult 318 339 oxr_session_poll(struct oxr_logger *log, struct oxr_session *sess) 319 340 { ··· 369 390 log, sess, xse.performance.domain, xse.performance.sub_domain, xse.performance.from_level, 370 391 xse.performance.to_level); 371 392 #endif // OXR_HAVE_EXT_performance_settings 393 + break; 394 + case XRT_SESSION_EVENT_PASSTHRU_STATE_CHANGE: 395 + #ifdef OXR_HAVE_FB_passthrough 396 + oxr_event_push_XrEventDataPassthroughStateChangedFB( 397 + log, sess, xrt_to_passthrough_state_flags(xse.passthru.state)); 398 + #endif // OXR_HAVE_FB_passthrough 372 399 break; 373 400 default: U_LOG_W("unhandled event type! %d", xse.type); break; 374 401 }
+93
src/xrt/state_trackers/oxr/oxr_session_frame_end.c
··· 313 313 #endif // OXR_HAVE_FB_composition_layer_depth_test 314 314 } 315 315 316 + static void 317 + fill_in_passthrough(struct oxr_session *sess, const XrCompositionLayerBaseHeader *layer, struct xrt_layer_data *data) 318 + { 319 + #ifdef OXR_HAVE_FB_passthrough 320 + // Is the extension enabled? 321 + if (!sess->sys->inst->extensions.FB_passthrough) { 322 + return; 323 + } 324 + const XrCompositionLayerPassthroughFB *passthrough = OXR_GET_INPUT_FROM_CHAIN( 325 + layer, (XrStructureType)XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_FB, XrCompositionLayerPassthroughFB); 326 + struct oxr_passthrough_layer *layer_handle = 327 + XRT_CAST_OXR_HANDLE_TO_PTR(struct oxr_passthrough_layer *, passthrough->layerHandle); 328 + data->passthrough.xrt_pl.paused = layer_handle->paused; 329 + struct oxr_passthrough *passthrough_handle = 330 + XRT_CAST_OXR_HANDLE_TO_PTR(struct oxr_passthrough *, layer_handle->passthrough); 331 + data->passthrough.xrt_pt.paused = passthrough_handle->paused; 332 + #endif 333 + } 334 + 316 335 /* 317 336 * 318 337 * Verify functions. ··· 1066 1085 #endif // OXR_HAVE_KHR_composition_layer_equirect2 1067 1086 } 1068 1087 1088 + static XrResult 1089 + verify_passthrough_layer(struct xrt_compositor *xc, 1090 + struct oxr_logger *log, 1091 + uint32_t layer_index, 1092 + const XrCompositionLayerPassthroughFB *passthrough, 1093 + struct xrt_device *head, 1094 + uint64_t timestamp) 1095 + { 1096 + #ifndef OXR_HAVE_FB_passthrough 1097 + return oxr_error(log, XR_ERROR_LAYER_INVALID, 1098 + "(frameEndInfo->layers[%u]->type) layer type XrCompositionLayerPassthroughFB not supported", 1099 + layer_index); 1100 + #else 1101 + if (passthrough->flags == 0 || (passthrough->flags & (XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT | 1102 + XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT | 1103 + XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT)) == 0) { 1104 + return oxr_error(log, XR_ERROR_LAYER_INVALID, 1105 + "(frameEndInfo->layers[%u]->flags) layer flags is not a valid combination of " 1106 + "XrCompositionLayerFlagBits values", 1107 + layer_index); 1108 + } 1109 + 1110 + if (passthrough->space) { 1111 + XrResult ret = verify_space(log, layer_index, passthrough->space); 1112 + if (ret != XR_SUCCESS) { 1113 + return ret; 1114 + } 1115 + } 1116 + 1117 + struct oxr_passthrough_layer *pl = 1118 + XRT_CAST_OXR_HANDLE_TO_PTR(struct oxr_passthrough_layer *, passthrough->layerHandle); 1119 + if (pl == NULL) { 1120 + return oxr_error(log, XR_ERROR_LAYER_INVALID, 1121 + "(frameEndInfo->layers[%u]->layerHandle) layerHandle is NULL!", layer_index); 1122 + } 1123 + 1124 + return XR_SUCCESS; 1125 + #endif 1126 + } 1069 1127 1070 1128 /* 1071 1129 * ··· 1526 1584 return XR_SUCCESS; 1527 1585 } 1528 1586 1587 + static XrResult 1588 + submit_passthrough_layer(struct oxr_session *sess, 1589 + struct xrt_compositor *xc, 1590 + struct oxr_logger *log, 1591 + const XrCompositionLayerPassthroughFB *passthrough, 1592 + struct xrt_device *head, 1593 + struct xrt_pose *inv_offset, 1594 + uint64_t oxr_timestamp, 1595 + uint64_t xrt_timestamp) 1596 + { 1597 + enum xrt_layer_composition_flags flags = convert_layer_flags(passthrough->flags); 1598 + 1599 + struct xrt_layer_data data; 1600 + U_ZERO(&data); 1601 + data.type = XRT_LAYER_PASSTHROUGH; 1602 + data.name = XRT_INPUT_GENERIC_HEAD_POSE; 1603 + data.timestamp = xrt_timestamp; 1604 + data.flags = flags; 1605 + fill_in_passthrough(sess, (XrCompositionLayerBaseHeader *)passthrough, &data); 1606 + fill_in_blend_factors(sess, (XrCompositionLayerBaseHeader *)passthrough, &data); 1607 + 1608 + xrt_result_t xret = xrt_comp_layer_passthrough(xc, head, &data); 1609 + OXR_CHECK_XRET(log, sess, xret, xrt_comp_layer_passthrough); 1610 + 1611 + return XR_SUCCESS; 1612 + } 1613 + 1529 1614 XrResult 1530 1615 oxr_session_frame_end(struct oxr_logger *log, struct oxr_session *sess, const XrFrameEndInfo *frameEndInfo) 1531 1616 { ··· 1655 1740 res = verify_equirect2_layer(sess, xc, log, i, (XrCompositionLayerEquirect2KHR *)layer, xdev, 1656 1741 frameEndInfo->displayTime); 1657 1742 break; 1743 + case XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_FB: 1744 + res = verify_passthrough_layer(xc, log, i, (XrCompositionLayerPassthroughFB *)layer, xdev, 1745 + frameEndInfo->displayTime); 1746 + break; 1658 1747 default: 1659 1748 return oxr_error(log, XR_ERROR_LAYER_INVALID, 1660 1749 "(frameEndInfo->layers[%u]->type) layer type not supported (%u)", i, ··· 1715 1804 case XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR: 1716 1805 submit_equirect2_layer(sess, xc, log, (XrCompositionLayerEquirect2KHR *)layer, xdev, 1717 1806 &inv_offset, frameEndInfo->displayTime, xrt_display_time_ns); 1807 + break; 1808 + case XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_FB: 1809 + submit_passthrough_layer(sess, xc, log, (XrCompositionLayerPassthroughFB *)layer, xdev, 1810 + &inv_offset, frameEndInfo->displayTime, xrt_display_time_ns); 1718 1811 break; 1719 1812 default: assert(false && "invalid layer type"); 1720 1813 }
+18
src/xrt/state_trackers/oxr/oxr_system.c
··· 329 329 } 330 330 #endif 331 331 332 + #ifdef OXR_HAVE_FB_passthrough 333 + XrSystemPassthroughPropertiesFB *passthrough_props = NULL; 334 + XrSystemPassthroughProperties2FB *passthrough_props2 = NULL; 335 + if (sys->inst->extensions.FB_passthrough) { 336 + passthrough_props = OXR_GET_OUTPUT_FROM_CHAIN(properties, XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES_FB, 337 + XrSystemPassthroughPropertiesFB); 338 + if (passthrough_props) { 339 + passthrough_props->supportsPassthrough = true; 340 + } 341 + 342 + passthrough_props2 = OXR_GET_OUTPUT_FROM_CHAIN(properties, XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES2_FB, 343 + XrSystemPassthroughProperties2FB); 344 + if (passthrough_props2) { 345 + passthrough_props2->capabilities = XR_PASSTHROUGH_CAPABILITY_BIT_FB; 346 + } 347 + } 348 + #endif 349 + 332 350 return XR_SUCCESS; 333 351 } 334 352