mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2024-12-28 02:26:16 +00:00
st/oxr: Add extension XR_FB_passthrough
This commit is contained in:
parent
6876de1da6
commit
c57976c2af
|
@ -422,6 +422,9 @@ endif()
|
||||||
if(NOT DEFINED XRT_FEATURE_OPENXR_LAYER_FB_DEPTH_TEST)
|
if(NOT DEFINED XRT_FEATURE_OPENXR_LAYER_FB_DEPTH_TEST)
|
||||||
set(XRT_FEATURE_OPENXR_LAYER_FB_DEPTH_TEST OFF)
|
set(XRT_FEATURE_OPENXR_LAYER_FB_DEPTH_TEST OFF)
|
||||||
endif()
|
endif()
|
||||||
|
if(NOT DEFINED XRT_FEATURE_OPENXR_LAYER_PASSTHROUGH)
|
||||||
|
set(XRT_FEATURE_OPENXR_LAYER_PASSTHROUGH OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Defaults for OpenXR spaces
|
# Defaults for OpenXR spaces
|
||||||
if(NOT DEFINED XRT_FEATURE_OPENXR_SPACE_LOCAL_FLOOR)
|
if(NOT DEFINED XRT_FEATURE_OPENXR_SPACE_LOCAL_FLOOR)
|
||||||
|
@ -632,6 +635,7 @@ message(STATUS "# FEATURE_OPENXR_LAYER_DEPTH: ${XRT_FEATURE
|
||||||
message(STATUS "# FEATURE_OPENXR_LAYER_EQUIRECT1: ${XRT_FEATURE_OPENXR_LAYER_EQUIRECT1}")
|
message(STATUS "# FEATURE_OPENXR_LAYER_EQUIRECT1: ${XRT_FEATURE_OPENXR_LAYER_EQUIRECT1}")
|
||||||
message(STATUS "# FEATURE_OPENXR_LAYER_EQUIRECT2: ${XRT_FEATURE_OPENXR_LAYER_EQUIRECT2}")
|
message(STATUS "# FEATURE_OPENXR_LAYER_EQUIRECT2: ${XRT_FEATURE_OPENXR_LAYER_EQUIRECT2}")
|
||||||
message(STATUS "# FEATURE_OPENXR_LAYER_FB_ALPHA_BLEND: ${XRT_FEATURE_OPENXR_LAYER_FB_ALPHA_BLEND}")
|
message(STATUS "# FEATURE_OPENXR_LAYER_FB_ALPHA_BLEND: ${XRT_FEATURE_OPENXR_LAYER_FB_ALPHA_BLEND}")
|
||||||
|
message(STATUS "# FEATURE_OPENXR_LAYER_PASSTHROUGH: ${XRT_FEATURE_OPENXR_LAYER_PASSTHROUGH}")
|
||||||
message(STATUS "# FEATURE_OPENXR_LAYER_FB_IMAGE_LAYOUT ${XRT_FEATURE_OPENXR_LAYER_FB_IMAGE_LAYOUT}")
|
message(STATUS "# FEATURE_OPENXR_LAYER_FB_IMAGE_LAYOUT ${XRT_FEATURE_OPENXR_LAYER_FB_IMAGE_LAYOUT}")
|
||||||
message(STATUS "# FEATURE_OPENXR_LAYER_FB_SETTINGS: ${XRT_FEATURE_OPENXR_LAYER_FB_SETTINGS}")
|
message(STATUS "# FEATURE_OPENXR_LAYER_FB_SETTINGS: ${XRT_FEATURE_OPENXR_LAYER_FB_SETTINGS}")
|
||||||
message(STATUS "# FEATURE_OPENXR_LAYER_FB_DEPTH_TEST: ${XRT_FEATURE_OPENXR_LAYER_FB_DEPTH_TEST}")
|
message(STATUS "# FEATURE_OPENXR_LAYER_FB_DEPTH_TEST: ${XRT_FEATURE_OPENXR_LAYER_FB_DEPTH_TEST}")
|
||||||
|
|
|
@ -70,6 +70,7 @@ EXTENSIONS = (
|
||||||
['XR_FB_composition_layer_settings', 'XRT_FEATURE_OPENXR_LAYER_FB_SETTINGS'],
|
['XR_FB_composition_layer_settings', 'XRT_FEATURE_OPENXR_LAYER_FB_SETTINGS'],
|
||||||
['XR_FB_composition_layer_depth_test', 'XRT_FEATURE_OPENXR_LAYER_FB_DEPTH_TEST'],
|
['XR_FB_composition_layer_depth_test', 'XRT_FEATURE_OPENXR_LAYER_FB_DEPTH_TEST'],
|
||||||
['XR_FB_display_refresh_rate', 'XRT_FEATURE_OPENXR_DISPLAY_REFRESH_RATE'],
|
['XR_FB_display_refresh_rate', 'XRT_FEATURE_OPENXR_DISPLAY_REFRESH_RATE'],
|
||||||
|
['XR_FB_passthrough', 'XRT_FEATURE_OPENXR_LAYER_PASSTHROUGH'],
|
||||||
['XR_ML_ml2_controller_interaction', 'XRT_FEATURE_OPENXR_INTERACTION_ML2'],
|
['XR_ML_ml2_controller_interaction', 'XRT_FEATURE_OPENXR_INTERACTION_ML2'],
|
||||||
['XR_MND_headless', 'XRT_FEATURE_OPENXR_HEADLESS'],
|
['XR_MND_headless', 'XRT_FEATURE_OPENXR_HEADLESS'],
|
||||||
['XR_MND_swapchain_usage_input_attachment_bit'],
|
['XR_MND_swapchain_usage_input_attachment_bit'],
|
||||||
|
|
|
@ -82,6 +82,7 @@ enum xrt_layer_type
|
||||||
XRT_LAYER_CYLINDER,
|
XRT_LAYER_CYLINDER,
|
||||||
XRT_LAYER_EQUIRECT1,
|
XRT_LAYER_EQUIRECT1,
|
||||||
XRT_LAYER_EQUIRECT2,
|
XRT_LAYER_EQUIRECT2,
|
||||||
|
XRT_LAYER_PASSTHROUGH
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -355,6 +356,34 @@ struct xrt_layer_equirect2_data
|
||||||
float lower_vertical_angle;
|
float lower_vertical_angle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @interface xrt_passthrough
|
||||||
|
*/
|
||||||
|
struct xrt_passthrough
|
||||||
|
{
|
||||||
|
bool paused;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @interface xrt_passthrough_layer
|
||||||
|
*/
|
||||||
|
struct xrt_passthrough_layer
|
||||||
|
{
|
||||||
|
bool paused;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* All the pure data values associated with a passthrough layer.
|
||||||
|
*
|
||||||
|
* The @ref xrt_swapchain references and @ref xrt_device are provided outside of
|
||||||
|
* this struct.
|
||||||
|
*/
|
||||||
|
struct xrt_layer_passthrough_data
|
||||||
|
{
|
||||||
|
struct xrt_passthrough xrt_pt;
|
||||||
|
struct xrt_passthrough_layer xrt_pl;
|
||||||
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* All the pure data values associated with a composition layer.
|
* All the pure data values associated with a composition layer.
|
||||||
*
|
*
|
||||||
|
@ -436,6 +465,7 @@ struct xrt_layer_data
|
||||||
struct xrt_layer_cylinder_data cylinder;
|
struct xrt_layer_cylinder_data cylinder;
|
||||||
struct xrt_layer_equirect1_data equirect1;
|
struct xrt_layer_equirect1_data equirect1;
|
||||||
struct xrt_layer_equirect2_data equirect2;
|
struct xrt_layer_equirect2_data equirect2;
|
||||||
|
struct xrt_layer_passthrough_data passthrough;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -861,6 +891,23 @@ struct xrt_swapchain_create_info
|
||||||
uint32_t formats[XRT_MAX_SWAPCHAIN_CREATE_INFO_FORMAT_LIST_COUNT];
|
uint32_t formats[XRT_MAX_SWAPCHAIN_CREATE_INFO_FORMAT_LIST_COUNT];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Passthrough creation info.
|
||||||
|
*/
|
||||||
|
struct xrt_passthrough_create_info
|
||||||
|
{
|
||||||
|
enum xrt_passthrough_create_flags create;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Passthrough layer creation info.
|
||||||
|
*/
|
||||||
|
struct xrt_passthrough_layer_create_info
|
||||||
|
{
|
||||||
|
enum xrt_passthrough_create_flags create;
|
||||||
|
enum xrt_passthrough_purpose_flags purpose;
|
||||||
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Struct used to negotiate properties of a swapchain that is created outside
|
* Struct used to negotiate properties of a swapchain that is created outside
|
||||||
* of the compositor. Often used by a client compositor or IPC layer to allocate
|
* of the compositor. Often used by a client compositor or IPC layer to allocate
|
||||||
|
@ -991,6 +1038,22 @@ struct xrt_compositor
|
||||||
struct xrt_compositor_semaphore **out_xcsem);
|
struct xrt_compositor_semaphore **out_xcsem);
|
||||||
/*! @} */
|
/*! @} */
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Create a passthrough.
|
||||||
|
*/
|
||||||
|
xrt_result_t (*create_passthrough)(struct xrt_compositor *xc, const struct xrt_passthrough_create_info *info);
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Create a passthrough layer.
|
||||||
|
*/
|
||||||
|
xrt_result_t (*create_passthrough_layer)(struct xrt_compositor *xc,
|
||||||
|
const struct xrt_passthrough_layer_create_info *info);
|
||||||
|
/*!
|
||||||
|
* Destroy a passthrough.
|
||||||
|
*/
|
||||||
|
xrt_result_t (*destroy_passthrough)(struct xrt_compositor *xc);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @name Function pointers for session functions
|
* @name Function pointers for session functions
|
||||||
* @{
|
* @{
|
||||||
|
@ -1256,6 +1319,19 @@ struct xrt_compositor
|
||||||
struct xrt_swapchain *xsc,
|
struct xrt_swapchain *xsc,
|
||||||
const struct xrt_layer_data *data);
|
const struct xrt_layer_data *data);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Adds a passthrough layer for submission.
|
||||||
|
*
|
||||||
|
* @param xc Self pointer
|
||||||
|
* @param xdev The device the layer is relative to.
|
||||||
|
* @param data All of the pure data bits (not pointers/handles),
|
||||||
|
* including what part of the supplied swapchain
|
||||||
|
* object to use.
|
||||||
|
*/
|
||||||
|
xrt_result_t (*layer_passthrough)(struct xrt_compositor *xc,
|
||||||
|
struct xrt_device *xdev,
|
||||||
|
const struct xrt_layer_data *data);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Commits all of the submitted layers.
|
* @brief Commits all of the submitted layers.
|
||||||
*
|
*
|
||||||
|
@ -1419,6 +1495,44 @@ xrt_comp_create_semaphore(struct xrt_compositor *xc,
|
||||||
|
|
||||||
/*! @} */
|
/*! @} */
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @copydoc xrt_compositor::create_passthrough
|
||||||
|
*
|
||||||
|
* Helper for calling through the function pointer.
|
||||||
|
*
|
||||||
|
* @public @memberof xrt_compositor
|
||||||
|
*/
|
||||||
|
static inline xrt_result_t
|
||||||
|
xrt_comp_create_passthrough(struct xrt_compositor *xc, const struct xrt_passthrough_create_info *info)
|
||||||
|
{
|
||||||
|
return xc->create_passthrough(xc, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @copydoc xrt_compositor::create_passthrough_layer
|
||||||
|
*
|
||||||
|
* Helper for calling through the function pointer.
|
||||||
|
*
|
||||||
|
* @public @memberof xrt_compositor
|
||||||
|
*/
|
||||||
|
static inline xrt_result_t
|
||||||
|
xrt_comp_create_passthrough_layer(struct xrt_compositor *xc, const struct xrt_passthrough_layer_create_info *info)
|
||||||
|
{
|
||||||
|
return xc->create_passthrough_layer(xc, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @copydoc xrt_compositor::destroy_passthrough
|
||||||
|
*
|
||||||
|
* Helper for calling through the function pointer.
|
||||||
|
*
|
||||||
|
* @public @memberof xrt_compositor
|
||||||
|
*/
|
||||||
|
static inline xrt_result_t
|
||||||
|
xrt_comp_destroy_passthrough(struct xrt_compositor *xc)
|
||||||
|
{
|
||||||
|
return xc->destroy_passthrough(xc);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @name Session methods
|
* @name Session methods
|
||||||
|
@ -1681,6 +1795,19 @@ xrt_comp_layer_equirect2(struct xrt_compositor *xc,
|
||||||
return xc->layer_equirect2(xc, xdev, xsc, data);
|
return xc->layer_equirect2(xc, xdev, xsc, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @copydoc xrt_compositor::layer_passthrough
|
||||||
|
*
|
||||||
|
* Helper for calling through the function pointer.
|
||||||
|
*
|
||||||
|
* @public @memberof xrt_compositor
|
||||||
|
*/
|
||||||
|
static inline xrt_result_t
|
||||||
|
xrt_comp_layer_passthrough(struct xrt_compositor *xc, struct xrt_device *xdev, const struct xrt_layer_data *data)
|
||||||
|
{
|
||||||
|
return xc->layer_passthrough(xc, xdev, data);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @copydoc xrt_compositor::layer_commit
|
* @copydoc xrt_compositor::layer_commit
|
||||||
*
|
*
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#cmakedefine XRT_FEATURE_OPENXR_LAYER_EQUIRECT1
|
#cmakedefine XRT_FEATURE_OPENXR_LAYER_EQUIRECT1
|
||||||
#cmakedefine XRT_FEATURE_OPENXR_LAYER_EQUIRECT2
|
#cmakedefine XRT_FEATURE_OPENXR_LAYER_EQUIRECT2
|
||||||
#cmakedefine XRT_FEATURE_OPENXR_LAYER_FB_ALPHA_BLEND
|
#cmakedefine XRT_FEATURE_OPENXR_LAYER_FB_ALPHA_BLEND
|
||||||
|
#cmakedefine XRT_FEATURE_OPENXR_LAYER_PASSTHROUGH
|
||||||
#cmakedefine XRT_FEATURE_OPENXR_LAYER_FB_IMAGE_LAYOUT
|
#cmakedefine XRT_FEATURE_OPENXR_LAYER_FB_IMAGE_LAYOUT
|
||||||
#cmakedefine XRT_FEATURE_OPENXR_LAYER_FB_SETTINGS
|
#cmakedefine XRT_FEATURE_OPENXR_LAYER_FB_SETTINGS
|
||||||
#cmakedefine XRT_FEATURE_OPENXR_LAYER_FB_DEPTH_TEST
|
#cmakedefine XRT_FEATURE_OPENXR_LAYER_FB_DEPTH_TEST
|
||||||
|
|
|
@ -115,6 +115,47 @@ enum xrt_blend_mode
|
||||||
|
|
||||||
#define XRT_MAX_DEVICE_BLEND_MODES 3
|
#define XRT_MAX_DEVICE_BLEND_MODES 3
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Special flags for creating passthrough.
|
||||||
|
*/
|
||||||
|
enum xrt_passthrough_create_flags
|
||||||
|
{
|
||||||
|
//! Start the passthrough on creation
|
||||||
|
XRT_PASSTHROUGH_IS_RUNNING_AT_CREATION = (1 << 0),
|
||||||
|
//! Our compositor just ignores this bit.
|
||||||
|
XRT_PASSTHROUGH_LAYER_DEPTH = (1 << 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Specify additional state change behavior.
|
||||||
|
*/
|
||||||
|
enum xrt_passthrough_state
|
||||||
|
{
|
||||||
|
//! Passthrough system requires reinitialization.
|
||||||
|
XRT_PASSTHROUGH_STATE_CHANGED_REINIT_REQUIRED_BIT = (1 << 0),
|
||||||
|
//! Non-recoverable error has occurred.
|
||||||
|
XRT_PASSTHROUGH_STATE_CHANGED_NON_RECOVERABLE_ERROR_BIT = (1 << 1),
|
||||||
|
//! A recoverable error has occurred.
|
||||||
|
XRT_PASSTHROUGH_STATE_CHANGED_RECOVERABLE_ERROR_BIT = (1 << 2),
|
||||||
|
//! The runtime has recovered from a previous error and is functioning normally.
|
||||||
|
XRT_PASSTHROUGH_STATE_CHANGED_RESTORED_ERROR_BIT = (1 << 3),
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Specify the kind of passthrough behavior the layer provides.
|
||||||
|
*/
|
||||||
|
enum xrt_passthrough_purpose_flags
|
||||||
|
{
|
||||||
|
//! Fullscreen layer
|
||||||
|
XRT_PASSTHROUGH_LAYER_PURPOSE_RECONSTRUCTION = (1 << 0),
|
||||||
|
//! Projected layer.
|
||||||
|
XRT_PASSTHROUGH_LAYER_PURPOSE_PROJECTED = (1 << 1),
|
||||||
|
//! Provided by XR_FB_passthrough_keyboard_hands
|
||||||
|
XRT_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_HANDS = 1000203001,
|
||||||
|
//! Provided by XR_FB_passthrough_keyboard_hands
|
||||||
|
XRT_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_MASKED_HANDS = 1000203002,
|
||||||
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Which distortion model does the device expose,
|
* Which distortion model does the device expose,
|
||||||
* used both as a bitfield and value.
|
* used both as a bitfield and value.
|
||||||
|
|
|
@ -58,6 +58,9 @@ enum xrt_session_event_type
|
||||||
|
|
||||||
//! The performance of the session has changed
|
//! The performance of the session has changed
|
||||||
XRT_SESSION_EVENT_PERFORMANCE_CHANGE = 7,
|
XRT_SESSION_EVENT_PERFORMANCE_CHANGE = 7,
|
||||||
|
|
||||||
|
//! The passthrough state of the session has changed
|
||||||
|
XRT_SESSION_EVENT_PASSTHRU_STATE_CHANGE = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -152,6 +155,15 @@ struct xrt_session_event_perf_change
|
||||||
enum xrt_perf_notify_level to_level;
|
enum xrt_perf_notify_level to_level;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Passthrough state change event.
|
||||||
|
*/
|
||||||
|
struct xrt_session_event_passthrough_state_change
|
||||||
|
{
|
||||||
|
enum xrt_session_event_type type;
|
||||||
|
enum xrt_passthrough_state state;
|
||||||
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Union of all session events, used to return multiple events through one call.
|
* Union of all session events, used to return multiple events through one call.
|
||||||
* Each event struct must start with a @ref xrt_session_event_type field.
|
* Each event struct must start with a @ref xrt_session_event_type field.
|
||||||
|
@ -168,6 +180,7 @@ union xrt_session_event {
|
||||||
struct xrt_session_event_display_refresh_rate_change display;
|
struct xrt_session_event_display_refresh_rate_change display;
|
||||||
struct xrt_session_event_reference_space_change_pending ref_change;
|
struct xrt_session_event_reference_space_change_pending ref_change;
|
||||||
struct xrt_session_event_perf_change performance;
|
struct xrt_session_event_perf_change performance;
|
||||||
|
struct xrt_session_event_passthrough_state_change passthru;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -104,6 +104,10 @@ if(WIN32)
|
||||||
target_compile_definitions(st_oxr PRIVATE XR_USE_PLATFORM_WIN32)
|
target_compile_definitions(st_oxr PRIVATE XR_USE_PLATFORM_WIN32)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(XRT_FEATURE_OPENXR_LAYER_PASSTHROUGH)
|
||||||
|
target_sources(st_oxr PRIVATE oxr_api_passthrough.c oxr_passthrough.c)
|
||||||
|
endif()
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
st_oxr
|
st_oxr
|
||||||
PRIVATE
|
PRIVATE
|
||||||
|
|
|
@ -570,6 +570,44 @@ oxr_xrGetDisplayRefreshRateFB(XrSession session, float *displayRefreshRate);
|
||||||
XRAPI_ATTR XrResult XRAPI_CALL
|
XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
oxr_xrRequestDisplayRefreshRateFB(XrSession session, float displayRefreshRate);
|
oxr_xrRequestDisplayRefreshRateFB(XrSession session, float displayRefreshRate);
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* oxr_api_passthrough.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifdef OXR_HAVE_FB_passthrough
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
oxr_xrCreateGeometryInstanceFB(XrSession session,
|
||||||
|
const XrGeometryInstanceCreateInfoFB *createInfo,
|
||||||
|
XrGeometryInstanceFB *outGeometryInstance);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
oxr_xrCreatePassthroughFB(XrSession session,
|
||||||
|
const XrPassthroughCreateInfoFB *createInfo,
|
||||||
|
XrPassthroughFB *outPassthrough);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
oxr_xrCreatePassthroughLayerFB(XrSession session,
|
||||||
|
const XrPassthroughLayerCreateInfoFB *createInfo,
|
||||||
|
XrPassthroughLayerFB *outLayer);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
oxr_xrDestroyGeometryInstanceFB(XrGeometryInstanceFB instance);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
oxr_xrDestroyPassthroughFB(XrPassthroughFB passthrough);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
oxr_xrDestroyPassthroughLayerFB(XrPassthroughLayerFB layer);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
oxr_xrGeometryInstanceSetTransformFB(XrGeometryInstanceFB instance,
|
||||||
|
const XrGeometryInstanceTransformFB *transformation);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
oxr_xrPassthroughLayerPauseFB(XrPassthroughLayerFB layer);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
oxr_xrPassthroughLayerResumeFB(XrPassthroughLayerFB layer);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
oxr_xrPassthroughLayerSetStyleFB(XrPassthroughLayerFB layer, const XrPassthroughStyleFB *style);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
oxr_xrPassthroughPauseFB(XrPassthroughFB passthrough);
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
oxr_xrPassthroughStartFB(XrPassthroughFB passthrough);
|
||||||
|
#endif
|
||||||
/*!
|
/*!
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -246,6 +246,21 @@ handle_non_null(struct oxr_instance *inst, struct oxr_logger *log, const char *n
|
||||||
ENTRY_IF_EXT(xrRequestDisplayRefreshRateFB, FB_display_refresh_rate);
|
ENTRY_IF_EXT(xrRequestDisplayRefreshRateFB, FB_display_refresh_rate);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef OXR_HAVE_FB_passthrough
|
||||||
|
ENTRY_IF_EXT(xrCreateGeometryInstanceFB, FB_passthrough);
|
||||||
|
ENTRY_IF_EXT(xrCreatePassthroughFB, FB_passthrough);
|
||||||
|
ENTRY_IF_EXT(xrCreatePassthroughLayerFB, FB_passthrough);
|
||||||
|
ENTRY_IF_EXT(xrDestroyGeometryInstanceFB, FB_passthrough);
|
||||||
|
ENTRY_IF_EXT(xrDestroyPassthroughFB, FB_passthrough);
|
||||||
|
ENTRY_IF_EXT(xrDestroyPassthroughLayerFB, FB_passthrough);
|
||||||
|
ENTRY_IF_EXT(xrGeometryInstanceSetTransformFB, FB_passthrough);
|
||||||
|
ENTRY_IF_EXT(xrPassthroughLayerPauseFB, FB_passthrough);
|
||||||
|
ENTRY_IF_EXT(xrPassthroughLayerResumeFB, FB_passthrough);
|
||||||
|
ENTRY_IF_EXT(xrPassthroughLayerSetStyleFB, FB_passthrough);
|
||||||
|
ENTRY_IF_EXT(xrPassthroughPauseFB, FB_passthrough);
|
||||||
|
ENTRY_IF_EXT(xrPassthroughStartFB, FB_passthrough);
|
||||||
|
#endif // OXR_HAVE_FB_passthrough
|
||||||
|
|
||||||
#ifdef OXR_HAVE_EXT_debug_utils
|
#ifdef OXR_HAVE_EXT_debug_utils
|
||||||
ENTRY_IF_EXT(xrSetDebugUtilsObjectNameEXT, EXT_debug_utils);
|
ENTRY_IF_EXT(xrSetDebugUtilsObjectNameEXT, EXT_debug_utils);
|
||||||
ENTRY_IF_EXT(xrCreateDebugUtilsMessengerEXT, EXT_debug_utils);
|
ENTRY_IF_EXT(xrCreateDebugUtilsMessengerEXT, EXT_debug_utils);
|
||||||
|
|
205
src/xrt/state_trackers/oxr/oxr_api_passthrough.c
Normal file
205
src/xrt/state_trackers/oxr/oxr_api_passthrough.c
Normal file
|
@ -0,0 +1,205 @@
|
||||||
|
// Copyright 2023-2024, Qualcomm Innovation Center, Inc.
|
||||||
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
* @brief passthrough related API entrypoint functions.
|
||||||
|
* @author Knox Liu <quic_dengkail@qti.qualcomm.com>
|
||||||
|
* @ingroup oxr_api
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "oxr_objects.h"
|
||||||
|
#include "oxr_logger.h"
|
||||||
|
#include "oxr_handle.h"
|
||||||
|
|
||||||
|
#include "util/u_debug.h"
|
||||||
|
#include "util/u_trace_marker.h"
|
||||||
|
|
||||||
|
#include "oxr_api_funcs.h"
|
||||||
|
#include "oxr_api_verify.h"
|
||||||
|
#include "oxr_chain.h"
|
||||||
|
#include "oxr_subaction.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
XrResult
|
||||||
|
oxr_xrCreateGeometryInstanceFB(XrSession session,
|
||||||
|
const XrGeometryInstanceCreateInfoFB *createInfo,
|
||||||
|
XrGeometryInstanceFB *outGeometryInstance)
|
||||||
|
{
|
||||||
|
OXR_TRACE_MARKER();
|
||||||
|
struct oxr_logger log;
|
||||||
|
oxr_log_init(&log, "oxr_xrCreateGeometryInstanceFB");
|
||||||
|
return oxr_error(&log, XR_ERROR_RUNTIME_FAILURE, " not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult
|
||||||
|
oxr_xrCreatePassthroughFB(XrSession session,
|
||||||
|
const XrPassthroughCreateInfoFB *createInfo,
|
||||||
|
XrPassthroughFB *outPassthrough)
|
||||||
|
{
|
||||||
|
OXR_TRACE_MARKER();
|
||||||
|
|
||||||
|
struct oxr_session *sess;
|
||||||
|
struct oxr_logger log;
|
||||||
|
OXR_VERIFY_SESSION_AND_INIT_LOG(&log, session, sess, "oxr_xrCreatePassthroughFB");
|
||||||
|
OXR_VERIFY_SESSION_NOT_LOST(&log, sess);
|
||||||
|
OXR_VERIFY_ARG_TYPE_AND_NOT_NULL(&log, createInfo, XR_TYPE_PASSTHROUGH_CREATE_INFO_FB);
|
||||||
|
OXR_VERIFY_PASSTHROUGH_FLAGS(&log, createInfo->flags);
|
||||||
|
|
||||||
|
struct oxr_passthrough *passthrough;
|
||||||
|
XrResult ret = oxr_passthrough_create(&log, sess, createInfo, &passthrough);
|
||||||
|
if (ret != XR_SUCCESS) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
*outPassthrough = oxr_passthrough_to_openxr(passthrough);
|
||||||
|
|
||||||
|
return oxr_session_success_result(sess);
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult
|
||||||
|
oxr_xrCreatePassthroughLayerFB(XrSession session,
|
||||||
|
const XrPassthroughLayerCreateInfoFB *createInfo,
|
||||||
|
XrPassthroughLayerFB *outLayer)
|
||||||
|
{
|
||||||
|
OXR_TRACE_MARKER();
|
||||||
|
|
||||||
|
struct oxr_session *sess;
|
||||||
|
struct oxr_logger log;
|
||||||
|
OXR_VERIFY_SESSION_AND_INIT_LOG(&log, session, sess, "oxr_xrCreatePassthroughLayerFB");
|
||||||
|
OXR_VERIFY_SESSION_NOT_LOST(&log, sess);
|
||||||
|
OXR_VERIFY_ARG_TYPE_AND_NOT_NULL(&log, createInfo, XR_TYPE_PASSTHROUGH_LAYER_CREATE_INFO_FB);
|
||||||
|
OXR_VERIFY_ARG_NOT_NULL(&log, createInfo->passthrough);
|
||||||
|
OXR_VERIFY_PASSTHROUGH_FLAGS(&log, createInfo->flags);
|
||||||
|
OXR_VERIFY_PASSTHROUGH_LAYER_PURPOSE(&log, createInfo->purpose);
|
||||||
|
|
||||||
|
struct oxr_passthrough_layer *passthroughLayer;
|
||||||
|
XrResult ret = oxr_passthrough_layer_create(&log, sess, createInfo, &passthroughLayer);
|
||||||
|
if (ret != XR_SUCCESS) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
*outLayer = oxr_passthrough_layer_to_openxr(passthroughLayer);
|
||||||
|
|
||||||
|
return oxr_session_success_result(sess);
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult
|
||||||
|
oxr_xrDestroyGeometryInstanceFB(XrGeometryInstanceFB instance)
|
||||||
|
{
|
||||||
|
OXR_TRACE_MARKER();
|
||||||
|
struct oxr_logger log;
|
||||||
|
oxr_log_init(&log, "oxr_xrDestroyGeometryInstanceFB");
|
||||||
|
return oxr_error(&log, XR_ERROR_RUNTIME_FAILURE, " not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult
|
||||||
|
oxr_xrDestroyPassthroughFB(XrPassthroughFB passthrough)
|
||||||
|
{
|
||||||
|
OXR_TRACE_MARKER();
|
||||||
|
|
||||||
|
struct oxr_passthrough *pt;
|
||||||
|
struct oxr_logger log;
|
||||||
|
OXR_VERIFY_PASSTHROUGH_AND_INIT_LOG(&log, passthrough, pt, "oxr_xrDestroyPassthroughFB");
|
||||||
|
|
||||||
|
xrt_comp_destroy_passthrough(pt->sess->compositor);
|
||||||
|
|
||||||
|
return oxr_handle_destroy(&log, &pt->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult
|
||||||
|
oxr_xrDestroyPassthroughLayerFB(XrPassthroughLayerFB layer)
|
||||||
|
{
|
||||||
|
OXR_TRACE_MARKER();
|
||||||
|
|
||||||
|
struct oxr_passthrough_layer *pl;
|
||||||
|
struct oxr_logger log;
|
||||||
|
OXR_VERIFY_PASSTHROUGH_LAYER_AND_INIT_LOG(&log, layer, pl, "oxr_xrDestroyPassthroughLayerFB");
|
||||||
|
|
||||||
|
return oxr_handle_destroy(&log, &pl->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult
|
||||||
|
oxr_xrGeometryInstanceSetTransformFB(XrGeometryInstanceFB instance, const XrGeometryInstanceTransformFB *transformation)
|
||||||
|
{
|
||||||
|
OXR_TRACE_MARKER();
|
||||||
|
struct oxr_logger log;
|
||||||
|
oxr_log_init(&log, "oxr_xrGeometryInstanceSetTransformFB");
|
||||||
|
return oxr_error(&log, XR_ERROR_RUNTIME_FAILURE, " not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult
|
||||||
|
oxr_xrPassthroughLayerPauseFB(XrPassthroughLayerFB layer)
|
||||||
|
{
|
||||||
|
OXR_TRACE_MARKER();
|
||||||
|
struct oxr_passthrough_layer *pl;
|
||||||
|
struct oxr_logger log;
|
||||||
|
OXR_VERIFY_PASSTHROUGH_LAYER_AND_INIT_LOG(&log, layer, pl, "oxr_xrPassthroughLayerPauseFB");
|
||||||
|
pl->paused = true;
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult
|
||||||
|
oxr_xrPassthroughLayerResumeFB(XrPassthroughLayerFB layer)
|
||||||
|
{
|
||||||
|
OXR_TRACE_MARKER();
|
||||||
|
struct oxr_passthrough_layer *pl;
|
||||||
|
struct oxr_logger log;
|
||||||
|
OXR_VERIFY_PASSTHROUGH_LAYER_AND_INIT_LOG(&log, layer, pl, "oxr_xrPassthroughLayerResumeFB");
|
||||||
|
pl->paused = false;
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult
|
||||||
|
oxr_xrPassthroughLayerSetStyleFB(XrPassthroughLayerFB layer, const XrPassthroughStyleFB *style)
|
||||||
|
{
|
||||||
|
OXR_TRACE_MARKER();
|
||||||
|
struct oxr_passthrough_layer *pl;
|
||||||
|
struct oxr_logger log;
|
||||||
|
OXR_VERIFY_PASSTHROUGH_LAYER_AND_INIT_LOG(&log, layer, pl, "oxr_xrPassthroughLayerResumeFB");
|
||||||
|
OXR_VERIFY_ARG_TYPE_AND_NOT_NULL(&log, style, XR_TYPE_PASSTHROUGH_STYLE_FB);
|
||||||
|
OXR_VERIFY_PASSTHROUGH_LAYER_STYLE(&log, style);
|
||||||
|
|
||||||
|
pl->style = *style;
|
||||||
|
XrPassthroughStyleFB *next = (XrPassthroughStyleFB *)style->next;
|
||||||
|
while (next) {
|
||||||
|
switch (next->type) {
|
||||||
|
case XR_TYPE_PASSTHROUGH_BRIGHTNESS_CONTRAST_SATURATION_FB:
|
||||||
|
pl->brightnessContrastSaturation = *(XrPassthroughBrightnessContrastSaturationFB *)next;
|
||||||
|
break;
|
||||||
|
case XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_MONO_FB:
|
||||||
|
pl->monoToMono = *(XrPassthroughColorMapMonoToMonoFB *)next;
|
||||||
|
break;
|
||||||
|
case XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_RGBA_FB:
|
||||||
|
pl->monoToRgba = *(XrPassthroughColorMapMonoToRgbaFB *)next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
next = (XrPassthroughStyleFB *)next->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult
|
||||||
|
oxr_xrPassthroughPauseFB(XrPassthroughFB passthrough)
|
||||||
|
{
|
||||||
|
OXR_TRACE_MARKER();
|
||||||
|
struct oxr_passthrough *pt;
|
||||||
|
struct oxr_logger log;
|
||||||
|
OXR_VERIFY_PASSTHROUGH_AND_INIT_LOG(&log, passthrough, pt, "oxr_xrPassthroughPauseFB");
|
||||||
|
pt->paused = true;
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult
|
||||||
|
oxr_xrPassthroughStartFB(XrPassthroughFB passthrough)
|
||||||
|
{
|
||||||
|
OXR_TRACE_MARKER();
|
||||||
|
struct oxr_passthrough *pt;
|
||||||
|
struct oxr_logger log;
|
||||||
|
OXR_VERIFY_PASSTHROUGH_AND_INIT_LOG(&log, passthrough, pt, "oxr_xrPassthroughStartFB");
|
||||||
|
pt->paused = false;
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
|
@ -67,6 +67,10 @@ extern "C" {
|
||||||
OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_hand_tracker, HTRACKER, name, new_thing->sess->sys->inst)
|
OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_hand_tracker, HTRACKER, name, new_thing->sess->sys->inst)
|
||||||
#define OXR_VERIFY_FORCE_FEEDBACK_AND_INIT_LOG(log, thing, new_thing, name) \
|
#define OXR_VERIFY_FORCE_FEEDBACK_AND_INIT_LOG(log, thing, new_thing, name) \
|
||||||
OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_force_feedback, FFB, name, new_thing->sess->sys->inst)
|
OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_force_feedback, FFB, name, new_thing->sess->sys->inst)
|
||||||
|
#define OXR_VERIFY_PASSTHROUGH_AND_INIT_LOG(log, thing, new_thing, name) \
|
||||||
|
OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_passthrough, PASSTHROUGH, name, new_thing->sess->sys->inst)
|
||||||
|
#define OXR_VERIFY_PASSTHROUGH_LAYER_AND_INIT_LOG(log, thing, new_thing, name) \
|
||||||
|
OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_passthrough_layer, PASSTHROUGH_LAYER, name, new_thing->sess->sys->inst)
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
#define OXR_VERIFY_INSTANCE_NOT_NULL(log, arg, new_arg) OXR_VERIFY_SET(log, arg, new_arg, oxr_instance, INSTANCE);
|
#define OXR_VERIFY_INSTANCE_NOT_NULL(log, arg, new_arg) OXR_VERIFY_SET(log, arg, new_arg, oxr_instance, INSTANCE);
|
||||||
|
@ -229,6 +233,37 @@ extern "C" {
|
||||||
} \
|
} \
|
||||||
} while (false)
|
} while (false)
|
||||||
|
|
||||||
|
#define OXR_VERIFY_PASSTHROUGH_FLAGS(log, flags) \
|
||||||
|
if (flags == 0 || \
|
||||||
|
(flags & (XR_PASSTHROUGH_IS_RUNNING_AT_CREATION_BIT_FB | XR_PASSTHROUGH_LAYER_DEPTH_BIT_FB)) == 0) \
|
||||||
|
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, \
|
||||||
|
"flags is not a valid combination of XrPassthroughFlagBitsFB values");
|
||||||
|
|
||||||
|
#define OXR_VERIFY_PASSTHROUGH_LAYER_PURPOSE(log, purpose) \
|
||||||
|
if ((purpose != XR_PASSTHROUGH_LAYER_PURPOSE_RECONSTRUCTION_FB && \
|
||||||
|
purpose != XR_PASSTHROUGH_LAYER_PURPOSE_PROJECTED_FB && \
|
||||||
|
purpose != XR_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_HANDS_FB && \
|
||||||
|
purpose != XR_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_MASKED_HANDS_FB)) \
|
||||||
|
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, \
|
||||||
|
"purpose is not a valid XrPassthroughLayerPurposeFB value");
|
||||||
|
|
||||||
|
#define OXR_VERIFY_PASSTHROUGH_LAYER_STYLE(log, style) \
|
||||||
|
do { \
|
||||||
|
uint32_t duplicate_check = 0; \
|
||||||
|
const XrPassthroughStyleFB *next = style->next; \
|
||||||
|
while (next) { \
|
||||||
|
if (next->type != XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_RGBA_FB && \
|
||||||
|
next->type != XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_MONO_FB && \
|
||||||
|
next->type != XR_TYPE_PASSTHROUGH_BRIGHTNESS_CONTRAST_SATURATION_FB) \
|
||||||
|
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, \
|
||||||
|
"style next structure chain contains invalid pointers"); \
|
||||||
|
if ((next->type & duplicate_check) != 0) \
|
||||||
|
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, \
|
||||||
|
"style next structure chain contains duplicate items"); \
|
||||||
|
duplicate_check |= next->type; \
|
||||||
|
next = (const XrPassthroughStyleFB *)next->next; \
|
||||||
|
} \
|
||||||
|
} while (false)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#define OXR_XR_DEBUG_SOURCESET (*(uint64_t *)"oxrsrcs\0")
|
#define OXR_XR_DEBUG_SOURCESET (*(uint64_t *)"oxrsrcs\0")
|
||||||
#define OXR_XR_DEBUG_SOURCE (*(uint64_t *)"oxrsrc_\0")
|
#define OXR_XR_DEBUG_SOURCE (*(uint64_t *)"oxrsrc_\0")
|
||||||
#define OXR_XR_DEBUG_HTRACKER (*(uint64_t *)"oxrhtra\0")
|
#define OXR_XR_DEBUG_HTRACKER (*(uint64_t *)"oxrhtra\0")
|
||||||
|
#define OXR_XR_DEBUG_PASSTHROUGH (*(uint64_t *)"oxrpass\0")
|
||||||
|
#define OXR_XR_DEBUG_PASSTHROUGH_LAYER (*(uint64_t *)"oxrptla\0")
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -296,6 +296,28 @@ oxr_event_push_XrEventDataPerfSettingsEXTX(struct oxr_logger *log,
|
||||||
}
|
}
|
||||||
#endif // OXR_HAVE_EXT_performance_settings
|
#endif // OXR_HAVE_EXT_performance_settings
|
||||||
|
|
||||||
|
#ifdef OXR_HAVE_FB_passthrough
|
||||||
|
XrResult
|
||||||
|
oxr_event_push_XrEventDataPassthroughStateChangedFB(struct oxr_logger *log,
|
||||||
|
struct oxr_session *sess,
|
||||||
|
XrPassthroughStateChangedFlagsFB flags)
|
||||||
|
{
|
||||||
|
struct oxr_instance *inst = sess->sys->inst;
|
||||||
|
XrEventDataPassthroughStateChangedFB *changed;
|
||||||
|
struct oxr_event *event = NULL;
|
||||||
|
|
||||||
|
ALLOC(log, inst, &event, &changed);
|
||||||
|
changed->type = XR_TYPE_EVENT_DATA_PASSTHROUGH_STATE_CHANGED_FB;
|
||||||
|
changed->flags = flags;
|
||||||
|
event->result = XR_SUCCESS;
|
||||||
|
lock(inst);
|
||||||
|
push(inst, event);
|
||||||
|
unlock(inst);
|
||||||
|
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif // OXR_HAVE_FB_passthrough
|
||||||
|
|
||||||
XrResult
|
XrResult
|
||||||
oxr_event_remove_session_events(struct oxr_logger *log, struct oxr_session *sess)
|
oxr_event_remove_session_events(struct oxr_logger *log, struct oxr_session *sess)
|
||||||
{
|
{
|
||||||
|
|
|
@ -439,6 +439,15 @@
|
||||||
#define OXR_EXTENSION_SUPPORT_FB_display_refresh_rate(_)
|
#define OXR_EXTENSION_SUPPORT_FB_display_refresh_rate(_)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XR_FB_passthrough
|
||||||
|
*/
|
||||||
|
#if defined(XR_FB_passthrough) && defined(XRT_FEATURE_OPENXR_LAYER_PASSTHROUGH)
|
||||||
|
#define OXR_HAVE_FB_passthrough
|
||||||
|
#define OXR_EXTENSION_SUPPORT_FB_passthrough(_) _(FB_passthrough, FB_PASSTHROUGH)
|
||||||
|
#else
|
||||||
|
#define OXR_EXTENSION_SUPPORT_FB_passthrough(_)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XR_ML_ml2_controller_interaction
|
* XR_ML_ml2_controller_interaction
|
||||||
|
@ -648,6 +657,7 @@
|
||||||
OXR_EXTENSION_SUPPORT_FB_composition_layer_settings(_) \
|
OXR_EXTENSION_SUPPORT_FB_composition_layer_settings(_) \
|
||||||
OXR_EXTENSION_SUPPORT_FB_composition_layer_depth_test(_) \
|
OXR_EXTENSION_SUPPORT_FB_composition_layer_depth_test(_) \
|
||||||
OXR_EXTENSION_SUPPORT_FB_display_refresh_rate(_) \
|
OXR_EXTENSION_SUPPORT_FB_display_refresh_rate(_) \
|
||||||
|
OXR_EXTENSION_SUPPORT_FB_passthrough(_) \
|
||||||
OXR_EXTENSION_SUPPORT_ML_ml2_controller_interaction(_) \
|
OXR_EXTENSION_SUPPORT_ML_ml2_controller_interaction(_) \
|
||||||
OXR_EXTENSION_SUPPORT_MND_headless(_) \
|
OXR_EXTENSION_SUPPORT_MND_headless(_) \
|
||||||
OXR_EXTENSION_SUPPORT_MND_swapchain_usage_input_attachment_bit(_) \
|
OXR_EXTENSION_SUPPORT_MND_swapchain_usage_input_attachment_bit(_) \
|
||||||
|
|
|
@ -2477,6 +2477,70 @@ struct oxr_hand_tracker
|
||||||
XrHandJointSetEXT hand_joint_set;
|
XrHandJointSetEXT hand_joint_set;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef OXR_HAVE_FB_passthrough
|
||||||
|
|
||||||
|
struct oxr_passthrough
|
||||||
|
{
|
||||||
|
struct oxr_handle_base handle;
|
||||||
|
|
||||||
|
struct oxr_session *sess;
|
||||||
|
|
||||||
|
XrPassthroughFlagsFB flags;
|
||||||
|
|
||||||
|
bool paused;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct oxr_passthrough_layer
|
||||||
|
{
|
||||||
|
struct oxr_handle_base handle;
|
||||||
|
|
||||||
|
struct oxr_session *sess;
|
||||||
|
|
||||||
|
XrPassthroughFB passthrough;
|
||||||
|
|
||||||
|
XrPassthroughFlagsFB flags;
|
||||||
|
|
||||||
|
XrPassthroughLayerPurposeFB purpose;
|
||||||
|
|
||||||
|
bool paused;
|
||||||
|
|
||||||
|
XrPassthroughStyleFB style;
|
||||||
|
XrPassthroughColorMapMonoToRgbaFB monoToRgba;
|
||||||
|
XrPassthroughColorMapMonoToMonoFB monoToMono;
|
||||||
|
XrPassthroughBrightnessContrastSaturationFB brightnessContrastSaturation;
|
||||||
|
};
|
||||||
|
|
||||||
|
XrResult
|
||||||
|
oxr_passthrough_create(struct oxr_logger *log,
|
||||||
|
struct oxr_session *sess,
|
||||||
|
const XrPassthroughCreateInfoFB *createInfo,
|
||||||
|
struct oxr_passthrough **out_passthrough);
|
||||||
|
|
||||||
|
XrResult
|
||||||
|
oxr_passthrough_layer_create(struct oxr_logger *log,
|
||||||
|
struct oxr_session *sess,
|
||||||
|
const XrPassthroughLayerCreateInfoFB *createInfo,
|
||||||
|
struct oxr_passthrough_layer **out_layer);
|
||||||
|
|
||||||
|
static inline XrPassthroughFB
|
||||||
|
oxr_passthrough_to_openxr(struct oxr_passthrough *passthrough)
|
||||||
|
{
|
||||||
|
return XRT_CAST_PTR_TO_OXR_HANDLE(XrPassthroughFB, passthrough);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline XrPassthroughLayerFB
|
||||||
|
oxr_passthrough_layer_to_openxr(struct oxr_passthrough_layer *passthroughLayer)
|
||||||
|
{
|
||||||
|
return XRT_CAST_PTR_TO_OXR_HANDLE(XrPassthroughLayerFB, passthroughLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult
|
||||||
|
oxr_event_push_XrEventDataPassthroughStateChangedFB(struct oxr_logger *log,
|
||||||
|
struct oxr_session *sess,
|
||||||
|
XrPassthroughStateChangedFlagsFB flags);
|
||||||
|
|
||||||
|
#endif // OXR_HAVE_FB_passthrough
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
144
src/xrt/state_trackers/oxr/oxr_passthrough.c
Normal file
144
src/xrt/state_trackers/oxr/oxr_passthrough.c
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
// Copyright 2023-2024, Qualcomm Innovation Center, Inc.
|
||||||
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
* @brief passthrough related API entrypoint functions.
|
||||||
|
* @author Knox Liu <quic_dengkail@qti.qualcomm.com>
|
||||||
|
* @ingroup oxr_main
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "math/m_api.h"
|
||||||
|
#include "math/m_space.h"
|
||||||
|
#include "util/u_debug.h"
|
||||||
|
#include "util/u_misc.h"
|
||||||
|
|
||||||
|
#include "oxr_objects.h"
|
||||||
|
#include "oxr_logger.h"
|
||||||
|
#include "oxr_handle.h"
|
||||||
|
#include "oxr_input_transform.h"
|
||||||
|
#include "oxr_chain.h"
|
||||||
|
#include "oxr_pretty_print.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* XR_FB_passthrough
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
static enum xrt_passthrough_create_flags
|
||||||
|
convert_create_flags(XrPassthroughFlagsFB xr_flags)
|
||||||
|
{
|
||||||
|
enum xrt_passthrough_create_flags flags = 0;
|
||||||
|
|
||||||
|
if ((xr_flags & XR_PASSTHROUGH_IS_RUNNING_AT_CREATION_BIT_FB) != 0) {
|
||||||
|
flags |= XRT_PASSTHROUGH_IS_RUNNING_AT_CREATION;
|
||||||
|
}
|
||||||
|
if ((xr_flags & XR_PASSTHROUGH_LAYER_DEPTH_BIT_FB) != 0) {
|
||||||
|
flags |= XRT_PASSTHROUGH_LAYER_DEPTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum xrt_passthrough_purpose_flags
|
||||||
|
convert_purpose_flags(XrPassthroughLayerPurposeFB xr_flags)
|
||||||
|
{
|
||||||
|
enum xrt_passthrough_purpose_flags flags = 0;
|
||||||
|
|
||||||
|
if ((xr_flags & XR_PASSTHROUGH_LAYER_PURPOSE_RECONSTRUCTION_FB) != 0) {
|
||||||
|
flags |= XRT_PASSTHROUGH_LAYER_PURPOSE_RECONSTRUCTION;
|
||||||
|
}
|
||||||
|
if ((xr_flags & XR_PASSTHROUGH_LAYER_PURPOSE_PROJECTED_FB) != 0) {
|
||||||
|
flags |= XRT_PASSTHROUGH_LAYER_PURPOSE_PROJECTED;
|
||||||
|
}
|
||||||
|
if ((xr_flags & XR_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_HANDS_FB) != 0) {
|
||||||
|
flags |= XRT_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_HANDS;
|
||||||
|
}
|
||||||
|
if ((xr_flags & XR_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_MASKED_HANDS_FB) != 0) {
|
||||||
|
flags |= XRT_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_MASKED_HANDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
static XrResult
|
||||||
|
oxr_passthrough_destroy(struct oxr_logger *log, struct oxr_handle_base *hb)
|
||||||
|
{
|
||||||
|
struct oxr_passthrough *passthrough = (struct oxr_passthrough *)hb;
|
||||||
|
free(passthrough);
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static XrResult
|
||||||
|
oxr_passthrough_layer_destroy(struct oxr_logger *log, struct oxr_handle_base *hb)
|
||||||
|
{
|
||||||
|
struct oxr_passthrough_layer *passthroughLayer = (struct oxr_passthrough_layer *)hb;
|
||||||
|
free(passthroughLayer);
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult
|
||||||
|
oxr_passthrough_create(struct oxr_logger *log,
|
||||||
|
struct oxr_session *sess,
|
||||||
|
const XrPassthroughCreateInfoFB *createInfo,
|
||||||
|
struct oxr_passthrough **out_passthrough)
|
||||||
|
{
|
||||||
|
struct oxr_instance *inst = sess->sys->inst;
|
||||||
|
|
||||||
|
struct oxr_passthrough *passthrough = NULL;
|
||||||
|
OXR_ALLOCATE_HANDLE_OR_RETURN(log, passthrough, OXR_XR_DEBUG_PASSTHROUGH, oxr_passthrough_destroy,
|
||||||
|
&sess->handle);
|
||||||
|
|
||||||
|
passthrough->sess = sess;
|
||||||
|
passthrough->flags = createInfo->flags;
|
||||||
|
|
||||||
|
xrt_result_t xret = XRT_SUCCESS;
|
||||||
|
|
||||||
|
struct xrt_passthrough_create_info info;
|
||||||
|
info.create = convert_create_flags(createInfo->flags);
|
||||||
|
xret = xrt_comp_create_passthrough(sess->compositor, &info);
|
||||||
|
if (xret != XRT_SUCCESS) {
|
||||||
|
return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, "Failed to create passthrough");
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_passthrough = passthrough;
|
||||||
|
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult
|
||||||
|
oxr_passthrough_layer_create(struct oxr_logger *log,
|
||||||
|
struct oxr_session *sess,
|
||||||
|
const XrPassthroughLayerCreateInfoFB *createInfo,
|
||||||
|
struct oxr_passthrough_layer **out_layer)
|
||||||
|
{
|
||||||
|
struct oxr_instance *inst = sess->sys->inst;
|
||||||
|
|
||||||
|
struct oxr_passthrough_layer *passthroughLayer = NULL;
|
||||||
|
OXR_ALLOCATE_HANDLE_OR_RETURN(log, passthroughLayer, OXR_XR_DEBUG_PASSTHROUGH_LAYER,
|
||||||
|
oxr_passthrough_layer_destroy, &sess->handle);
|
||||||
|
|
||||||
|
passthroughLayer->sess = sess;
|
||||||
|
passthroughLayer->passthrough = createInfo->passthrough;
|
||||||
|
passthroughLayer->flags = createInfo->flags;
|
||||||
|
passthroughLayer->purpose = createInfo->purpose;
|
||||||
|
|
||||||
|
xrt_result_t xret = XRT_SUCCESS;
|
||||||
|
|
||||||
|
struct xrt_passthrough_layer_create_info info;
|
||||||
|
info.create = convert_create_flags(createInfo->flags);
|
||||||
|
info.purpose = convert_purpose_flags(createInfo->purpose);
|
||||||
|
|
||||||
|
xret = xrt_comp_create_passthrough_layer(sess->compositor, &info);
|
||||||
|
if (xret != XRT_SUCCESS) {
|
||||||
|
return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, "Failed to create passthrough layer");
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_layer = passthroughLayer;
|
||||||
|
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
|
@ -314,6 +314,27 @@ oxr_session_request_exit(struct oxr_logger *log, struct oxr_session *sess)
|
||||||
return oxr_session_success_result(sess);
|
return oxr_session_success_result(sess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef OXR_HAVE_FB_passthrough
|
||||||
|
static inline XrPassthroughStateChangedFlagsFB
|
||||||
|
xrt_to_passthrough_state_flags(enum xrt_passthrough_state state)
|
||||||
|
{
|
||||||
|
XrPassthroughStateChangedFlagsFB res = 0;
|
||||||
|
if (state & XRT_PASSTHROUGH_STATE_CHANGED_REINIT_REQUIRED_BIT) {
|
||||||
|
res |= XR_PASSTHROUGH_STATE_CHANGED_REINIT_REQUIRED_BIT_FB;
|
||||||
|
}
|
||||||
|
if (state & XRT_PASSTHROUGH_STATE_CHANGED_NON_RECOVERABLE_ERROR_BIT) {
|
||||||
|
res |= XR_PASSTHROUGH_STATE_CHANGED_NON_RECOVERABLE_ERROR_BIT_FB;
|
||||||
|
}
|
||||||
|
if (state & XRT_PASSTHROUGH_STATE_CHANGED_RECOVERABLE_ERROR_BIT) {
|
||||||
|
res |= XR_PASSTHROUGH_STATE_CHANGED_RECOVERABLE_ERROR_BIT_FB;
|
||||||
|
}
|
||||||
|
if (state & XRT_PASSTHROUGH_STATE_CHANGED_RESTORED_ERROR_BIT) {
|
||||||
|
res |= XR_PASSTHROUGH_STATE_CHANGED_RESTORED_ERROR_BIT_FB;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
XrResult
|
XrResult
|
||||||
oxr_session_poll(struct oxr_logger *log, struct oxr_session *sess)
|
oxr_session_poll(struct oxr_logger *log, struct oxr_session *sess)
|
||||||
{
|
{
|
||||||
|
@ -370,6 +391,12 @@ oxr_session_poll(struct oxr_logger *log, struct oxr_session *sess)
|
||||||
xse.performance.to_level);
|
xse.performance.to_level);
|
||||||
#endif // OXR_HAVE_EXT_performance_settings
|
#endif // OXR_HAVE_EXT_performance_settings
|
||||||
break;
|
break;
|
||||||
|
case XRT_SESSION_EVENT_PASSTHRU_STATE_CHANGE:
|
||||||
|
#ifdef OXR_HAVE_FB_passthrough
|
||||||
|
oxr_event_push_XrEventDataPassthroughStateChangedFB(
|
||||||
|
log, sess, xrt_to_passthrough_state_flags(xse.passthru.state));
|
||||||
|
#endif // OXR_HAVE_FB_passthrough
|
||||||
|
break;
|
||||||
default: U_LOG_W("unhandled event type! %d", xse.type); break;
|
default: U_LOG_W("unhandled event type! %d", xse.type); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -313,6 +313,25 @@ fill_in_depth_test(struct oxr_session *sess, const XrCompositionLayerBaseHeader
|
||||||
#endif // OXR_HAVE_FB_composition_layer_depth_test
|
#endif // OXR_HAVE_FB_composition_layer_depth_test
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fill_in_passthrough(struct oxr_session *sess, const XrCompositionLayerBaseHeader *layer, struct xrt_layer_data *data)
|
||||||
|
{
|
||||||
|
#ifdef OXR_HAVE_FB_passthrough
|
||||||
|
// Is the extension enabled?
|
||||||
|
if (!sess->sys->inst->extensions.FB_passthrough) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const XrCompositionLayerPassthroughFB *passthrough = OXR_GET_INPUT_FROM_CHAIN(
|
||||||
|
layer, (XrStructureType)XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_FB, XrCompositionLayerPassthroughFB);
|
||||||
|
struct oxr_passthrough_layer *layer_handle =
|
||||||
|
XRT_CAST_OXR_HANDLE_TO_PTR(struct oxr_passthrough_layer *, passthrough->layerHandle);
|
||||||
|
data->passthrough.xrt_pl.paused = layer_handle->paused;
|
||||||
|
struct oxr_passthrough *passthrough_handle =
|
||||||
|
XRT_CAST_OXR_HANDLE_TO_PTR(struct oxr_passthrough *, layer_handle->passthrough);
|
||||||
|
data->passthrough.xrt_pt.paused = passthrough_handle->paused;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Verify functions.
|
* Verify functions.
|
||||||
|
@ -1066,6 +1085,45 @@ verify_equirect2_layer(struct oxr_session *sess,
|
||||||
#endif // OXR_HAVE_KHR_composition_layer_equirect2
|
#endif // OXR_HAVE_KHR_composition_layer_equirect2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static XrResult
|
||||||
|
verify_passthrough_layer(struct xrt_compositor *xc,
|
||||||
|
struct oxr_logger *log,
|
||||||
|
uint32_t layer_index,
|
||||||
|
const XrCompositionLayerPassthroughFB *passthrough,
|
||||||
|
struct xrt_device *head,
|
||||||
|
uint64_t timestamp)
|
||||||
|
{
|
||||||
|
#ifndef OXR_HAVE_FB_passthrough
|
||||||
|
return oxr_error(log, XR_ERROR_LAYER_INVALID,
|
||||||
|
"(frameEndInfo->layers[%u]->type) layer type XrCompositionLayerPassthroughFB not supported",
|
||||||
|
layer_index);
|
||||||
|
#else
|
||||||
|
if (passthrough->flags == 0 || (passthrough->flags & (XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT |
|
||||||
|
XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT |
|
||||||
|
XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT)) == 0) {
|
||||||
|
return oxr_error(log, XR_ERROR_LAYER_INVALID,
|
||||||
|
"(frameEndInfo->layers[%u]->flags) layer flags is not a valid combination of "
|
||||||
|
"XrCompositionLayerFlagBits values",
|
||||||
|
layer_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (passthrough->space) {
|
||||||
|
XrResult ret = verify_space(log, layer_index, passthrough->space);
|
||||||
|
if (ret != XR_SUCCESS) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct oxr_passthrough_layer *pl =
|
||||||
|
XRT_CAST_OXR_HANDLE_TO_PTR(struct oxr_passthrough_layer *, passthrough->layerHandle);
|
||||||
|
if (pl == NULL) {
|
||||||
|
return oxr_error(log, XR_ERROR_LAYER_INVALID,
|
||||||
|
"(frameEndInfo->layers[%u]->layerHandle) layerHandle is NULL!", layer_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return XR_SUCCESS;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
|
@ -1526,6 +1584,33 @@ submit_equirect2_layer(struct oxr_session *sess,
|
||||||
return XR_SUCCESS;
|
return XR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static XrResult
|
||||||
|
submit_passthrough_layer(struct oxr_session *sess,
|
||||||
|
struct xrt_compositor *xc,
|
||||||
|
struct oxr_logger *log,
|
||||||
|
const XrCompositionLayerPassthroughFB *passthrough,
|
||||||
|
struct xrt_device *head,
|
||||||
|
struct xrt_pose *inv_offset,
|
||||||
|
uint64_t oxr_timestamp,
|
||||||
|
uint64_t xrt_timestamp)
|
||||||
|
{
|
||||||
|
enum xrt_layer_composition_flags flags = convert_layer_flags(passthrough->flags);
|
||||||
|
|
||||||
|
struct xrt_layer_data data;
|
||||||
|
U_ZERO(&data);
|
||||||
|
data.type = XRT_LAYER_PASSTHROUGH;
|
||||||
|
data.name = XRT_INPUT_GENERIC_HEAD_POSE;
|
||||||
|
data.timestamp = xrt_timestamp;
|
||||||
|
data.flags = flags;
|
||||||
|
fill_in_passthrough(sess, (XrCompositionLayerBaseHeader *)passthrough, &data);
|
||||||
|
fill_in_blend_factors(sess, (XrCompositionLayerBaseHeader *)passthrough, &data);
|
||||||
|
|
||||||
|
xrt_result_t xret = xrt_comp_layer_passthrough(xc, head, &data);
|
||||||
|
OXR_CHECK_XRET(log, sess, xret, xrt_comp_layer_passthrough);
|
||||||
|
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
XrResult
|
XrResult
|
||||||
oxr_session_frame_end(struct oxr_logger *log, struct oxr_session *sess, const XrFrameEndInfo *frameEndInfo)
|
oxr_session_frame_end(struct oxr_logger *log, struct oxr_session *sess, const XrFrameEndInfo *frameEndInfo)
|
||||||
{
|
{
|
||||||
|
@ -1655,6 +1740,10 @@ oxr_session_frame_end(struct oxr_logger *log, struct oxr_session *sess, const Xr
|
||||||
res = verify_equirect2_layer(sess, xc, log, i, (XrCompositionLayerEquirect2KHR *)layer, xdev,
|
res = verify_equirect2_layer(sess, xc, log, i, (XrCompositionLayerEquirect2KHR *)layer, xdev,
|
||||||
frameEndInfo->displayTime);
|
frameEndInfo->displayTime);
|
||||||
break;
|
break;
|
||||||
|
case XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_FB:
|
||||||
|
res = verify_passthrough_layer(xc, log, i, (XrCompositionLayerPassthroughFB *)layer, xdev,
|
||||||
|
frameEndInfo->displayTime);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return oxr_error(log, XR_ERROR_LAYER_INVALID,
|
return oxr_error(log, XR_ERROR_LAYER_INVALID,
|
||||||
"(frameEndInfo->layers[%u]->type) layer type not supported (%u)", i,
|
"(frameEndInfo->layers[%u]->type) layer type not supported (%u)", i,
|
||||||
|
@ -1716,6 +1805,10 @@ oxr_session_frame_end(struct oxr_logger *log, struct oxr_session *sess, const Xr
|
||||||
submit_equirect2_layer(sess, xc, log, (XrCompositionLayerEquirect2KHR *)layer, xdev,
|
submit_equirect2_layer(sess, xc, log, (XrCompositionLayerEquirect2KHR *)layer, xdev,
|
||||||
&inv_offset, frameEndInfo->displayTime, xrt_display_time_ns);
|
&inv_offset, frameEndInfo->displayTime, xrt_display_time_ns);
|
||||||
break;
|
break;
|
||||||
|
case XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_FB:
|
||||||
|
submit_passthrough_layer(sess, xc, log, (XrCompositionLayerPassthroughFB *)layer, xdev,
|
||||||
|
&inv_offset, frameEndInfo->displayTime, xrt_display_time_ns);
|
||||||
|
break;
|
||||||
default: assert(false && "invalid layer type");
|
default: assert(false && "invalid layer type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -329,6 +329,24 @@ oxr_system_get_properties(struct oxr_logger *log, struct oxr_system *sys, XrSyst
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef OXR_HAVE_FB_passthrough
|
||||||
|
XrSystemPassthroughPropertiesFB *passthrough_props = NULL;
|
||||||
|
XrSystemPassthroughProperties2FB *passthrough_props2 = NULL;
|
||||||
|
if (sys->inst->extensions.FB_passthrough) {
|
||||||
|
passthrough_props = OXR_GET_OUTPUT_FROM_CHAIN(properties, XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES_FB,
|
||||||
|
XrSystemPassthroughPropertiesFB);
|
||||||
|
if (passthrough_props) {
|
||||||
|
passthrough_props->supportsPassthrough = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
passthrough_props2 = OXR_GET_OUTPUT_FROM_CHAIN(properties, XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES2_FB,
|
||||||
|
XrSystemPassthroughProperties2FB);
|
||||||
|
if (passthrough_props2) {
|
||||||
|
passthrough_props2->capabilities = XR_PASSTHROUGH_CAPABILITY_BIT_FB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return XR_SUCCESS;
|
return XR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue