diff --git a/src/xrt/state_trackers/oxr/CMakeLists.txt b/src/xrt/state_trackers/oxr/CMakeLists.txt index 57c5885d4..db769550e 100644 --- a/src/xrt/state_trackers/oxr/CMakeLists.txt +++ b/src/xrt/state_trackers/oxr/CMakeLists.txt @@ -106,6 +106,10 @@ if(XRT_FEATURE_OPENXR_BODY_TRACKING_FB) target_sources(st_oxr PRIVATE oxr_api_body_tracking.c oxr_body_tracking.c) endif() +if(XRT_FEATURE_OPENXR_FACE_TRACKING_ANDROID) + target_sources(st_oxr PRIVATE oxr_api_face_tracking_android.c oxr_face_tracking_android.c) +endif() + if(XRT_FEATURE_OPENXR_FACIAL_TRACKING_HTC) target_sources(st_oxr PRIVATE oxr_api_face_tracking_htc.c oxr_face_tracking_htc.c) endif() diff --git a/src/xrt/state_trackers/oxr/oxr_api_face_tracking_android.c b/src/xrt/state_trackers/oxr/oxr_api_face_tracking_android.c new file mode 100644 index 000000000..256917e77 --- /dev/null +++ b/src/xrt/state_trackers/oxr/oxr_api_face_tracking_android.c @@ -0,0 +1,82 @@ +// Copyright 2025, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Android face tracking related API entrypoint functions. + * @author Korcan Hussein + * @ingroup oxr_api + */ + +#include +#include +#include + +#include "util/u_trace_marker.h" + +#include "oxr_objects.h" +#include "oxr_logger.h" + +#include "oxr_api_funcs.h" +#include "oxr_api_verify.h" +#include "oxr_handle.h" + +XRAPI_ATTR XrResult XRAPI_CALL +oxr_xrCreateFaceTrackerANDROID(XrSession session, + const XrFaceTrackerCreateInfoANDROID *createInfo, + XrFaceTrackerANDROID *faceTracker) +{ + OXR_TRACE_MARKER(); + struct oxr_logger log; + struct oxr_session *sess = NULL; + OXR_VERIFY_SESSION_AND_INIT_LOG(&log, session, sess, "xrCreateFaceTrackerANDROID"); + OXR_VERIFY_SESSION_NOT_LOST(&log, sess); + OXR_VERIFY_EXTENSION(&log, sess->sys->inst, ANDROID_face_tracking); + OXR_VERIFY_ARG_TYPE_AND_NOT_NULL(&log, createInfo, XR_TYPE_FACE_TRACKER_CREATE_INFO_ANDROID); + return oxr_face_tracker_android_create(&log, sess, createInfo, faceTracker); +} + +XRAPI_ATTR XrResult XRAPI_CALL +oxr_xrDestroyFaceTrackerANDROID(XrFaceTrackerANDROID facialTracker) +{ + OXR_TRACE_MARKER(); + struct oxr_logger log; + struct oxr_face_tracker_android *face_tracker_android = NULL; + OXR_VERIFY_FACE_TRACKER_ANDROID_AND_INIT_LOG(&log, facialTracker, face_tracker_android, + "xrDestroyFaceTrackerANDROID"); + return oxr_handle_destroy(&log, &face_tracker_android->handle); +} + +XRAPI_ATTR XrResult XRAPI_CALL +oxr_xrGetFaceStateANDROID(XrFaceTrackerANDROID faceTracker, + const XrFaceStateGetInfoANDROID *getInfo, + XrFaceStateANDROID *faceStateOutput) +{ + OXR_TRACE_MARKER(); + struct oxr_logger log; + struct oxr_face_tracker_android *face_tracker_android = NULL; + OXR_VERIFY_FACE_TRACKER_ANDROID_AND_INIT_LOG(&log, faceTracker, face_tracker_android, "xrGetFaceStateANDROID"); + OXR_VERIFY_SESSION_NOT_LOST(&log, face_tracker_android->sess); + OXR_VERIFY_ARG_NOT_NULL(&log, face_tracker_android->xdev); + OXR_VERIFY_ARG_TYPE_AND_NOT_NULL(&log, getInfo, XR_TYPE_FACE_STATE_GET_INFO_ANDROID); + OXR_VERIFY_ARG_TYPE_AND_NOT_NULL(&log, faceStateOutput, XR_TYPE_FACE_STATE_ANDROID); + OXR_VERIFY_ARG_TIME_NOT_ZERO(&log, getInfo->time); + OXR_VERIFY_TWO_CALL_ARRAY(&log, faceStateOutput->parametersCapacityInput, + (&faceStateOutput->parametersCountOutput), faceStateOutput->parameters); + OXR_VERIFY_TWO_CALL_ARRAY(&log, faceStateOutput->regionConfidencesCapacityInput, + (&faceStateOutput->regionConfidencesCountOutput), faceStateOutput->regionConfidences); + return oxr_get_face_state_android(&log, face_tracker_android, getInfo, faceStateOutput); +} + +XRAPI_ATTR XrResult XRAPI_CALL +oxr_xrGetFaceCalibrationStateANDROID(XrFaceTrackerANDROID faceTracker, XrBool32 *faceIsCalibratedOutput) +{ + OXR_TRACE_MARKER(); + struct oxr_logger log; + struct oxr_face_tracker_android *face_tracker_android = NULL; + OXR_VERIFY_FACE_TRACKER_ANDROID_AND_INIT_LOG(&log, faceTracker, face_tracker_android, + "xrGetFaceCalibrationStateANDROID"); + OXR_VERIFY_SESSION_NOT_LOST(&log, face_tracker_android->sess); + OXR_VERIFY_ARG_NOT_NULL(&log, face_tracker_android->xdev); + OXR_VERIFY_ARG_NOT_NULL(&log, faceIsCalibratedOutput); + return oxr_get_face_calibration_state_android(&log, face_tracker_android, faceIsCalibratedOutput); +} diff --git a/src/xrt/state_trackers/oxr/oxr_api_funcs.h b/src/xrt/state_trackers/oxr/oxr_api_funcs.h index 59520992e..b9e8b30ea 100644 --- a/src/xrt/state_trackers/oxr/oxr_api_funcs.h +++ b/src/xrt/state_trackers/oxr/oxr_api_funcs.h @@ -779,6 +779,30 @@ XRAPI_ATTR XrResult XRAPI_CALL oxr_xrCancelFutureEXT(XrInstance instance, const XrFutureCancelInfoEXT *cancelInfo); #endif +/* + * + * oxr_api_face_tracking_android.c + * + */ + +#ifdef OXR_HAVE_ANDROID_face_tracking +XRAPI_ATTR XrResult XRAPI_CALL +oxr_xrCreateFaceTrackerANDROID(XrSession session, + const XrFaceTrackerCreateInfoANDROID *createInfo, + XrFaceTrackerANDROID *faceTracker); + +XRAPI_ATTR XrResult XRAPI_CALL +oxr_xrDestroyFaceTrackerANDROID(XrFaceTrackerANDROID facialTracker); + +XRAPI_ATTR XrResult XRAPI_CALL +oxr_xrGetFaceStateANDROID(XrFaceTrackerANDROID faceTracker, + const XrFaceStateGetInfoANDROID *getInfo, + XrFaceStateANDROID *faceStateOutput); + +XRAPI_ATTR XrResult XRAPI_CALL +oxr_xrGetFaceCalibrationStateANDROID(XrFaceTrackerANDROID faceTracker, XrBool32 *faceIsCalibratedOutput); +#endif + /*! * @} */ diff --git a/src/xrt/state_trackers/oxr/oxr_api_negotiate.c b/src/xrt/state_trackers/oxr/oxr_api_negotiate.c index bf0da596a..559ccc326 100644 --- a/src/xrt/state_trackers/oxr/oxr_api_negotiate.c +++ b/src/xrt/state_trackers/oxr/oxr_api_negotiate.c @@ -419,6 +419,13 @@ handle_non_null(struct oxr_instance *inst, struct oxr_logger *log, const char *n ENTRY_IF_EXT(xrCancelFutureEXT, EXT_future); #endif // OXR_HAVE_EXT_future +#ifdef OXR_HAVE_ANDROID_face_tracking + ENTRY_IF_EXT(xrCreateFaceTrackerANDROID, ANDROID_face_tracking); + ENTRY_IF_EXT(xrDestroyFaceTrackerANDROID, ANDROID_face_tracking); + ENTRY_IF_EXT(xrGetFaceCalibrationStateANDROID, ANDROID_face_tracking); + ENTRY_IF_EXT(xrGetFaceStateANDROID, ANDROID_face_tracking); +#endif + #ifdef OXR_HAVE_KHR_extended_struct_name_lengths ENTRY_IF_EXT(xrStructureTypeToString2KHR, KHR_extended_struct_name_lengths); #endif // OXR_HAVE_KHR_extended_struct_name_lengths diff --git a/src/xrt/state_trackers/oxr/oxr_api_verify.h b/src/xrt/state_trackers/oxr/oxr_api_verify.h index 7fea1916d..407a75af0 100644 --- a/src/xrt/state_trackers/oxr/oxr_api_verify.h +++ b/src/xrt/state_trackers/oxr/oxr_api_verify.h @@ -97,6 +97,8 @@ struct oxr_subaction_paths; #define OXR_VERIFY_FUTURE_AND_INIT_LOG(log, thing, new_thing, name) \ OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_future_ext, FUTURE, name, new_thing->inst); \ OXR_VERIFY_FUTURE_VALID(log, new_thing) +#define OXR_VERIFY_FACE_TRACKER_ANDROID_AND_INIT_LOG(log, thing, new_thing, name) \ + OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_face_tracker_android, FTRACKER, name, new_thing->sess->sys->inst) // clang-format on #define OXR_VERIFY_INSTANCE_NOT_NULL(log, arg, new_arg) OXR_VERIFY_SET(log, arg, new_arg, oxr_instance, INSTANCE); diff --git a/src/xrt/state_trackers/oxr/oxr_face_tracking_android.c b/src/xrt/state_trackers/oxr/oxr_face_tracking_android.c new file mode 100644 index 000000000..e79b7036d --- /dev/null +++ b/src/xrt/state_trackers/oxr/oxr_face_tracking_android.c @@ -0,0 +1,51 @@ +// Copyright 2025, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Android face tracking related API entrypoint functions. + * @author Korcan Hussein + * @ingroup oxr_main + */ + +#include +#include +#include + +#include "oxr_objects.h" +#include "oxr_logger.h" +#include "oxr_handle.h" + +static XrResult +oxr_face_tracker_android_destroy_cb(struct oxr_logger *log, struct oxr_handle_base *hb) +{ + struct oxr_face_tracker_android *face_tracker_android = (struct oxr_face_tracker_android *)hb; + free(face_tracker_android); + return XR_SUCCESS; +} + +XrResult +oxr_face_tracker_android_create(struct oxr_logger *log, + struct oxr_session *sess, + const XrFaceTrackerCreateInfoANDROID *createInfo, + XrFaceTrackerANDROID *faceTracker) +{ + return oxr_session_success_result(sess); +} + +XrResult +oxr_get_face_state_android(struct oxr_logger *log, + struct oxr_face_tracker_android *facial_tracker_android, + const XrFaceStateGetInfoANDROID *getInfo, + XrFaceStateANDROID *faceStateOutput) +{ + + return oxr_session_success_result(facial_tracker_android->sess); +} + +XrResult +oxr_get_face_calibration_state_android(struct oxr_logger *log, + struct oxr_face_tracker_android *facial_tracker_android, + XrBool32 *faceIsCalibratedOutput) +{ + return oxr_session_success_result(facial_tracker_android->sess); +} diff --git a/src/xrt/state_trackers/oxr/oxr_objects.h b/src/xrt/state_trackers/oxr/oxr_objects.h index 4e1e31b17..be43691a4 100644 --- a/src/xrt/state_trackers/oxr/oxr_objects.h +++ b/src/xrt/state_trackers/oxr/oxr_objects.h @@ -127,6 +127,7 @@ struct oxr_interaction_profile; struct oxr_action_set_ref; struct oxr_action_ref; struct oxr_hand_tracker; +struct oxr_face_tracker_android; struct oxr_facial_tracker_htc; struct oxr_face_tracker2_fb; struct oxr_body_tracker_fb; @@ -467,6 +468,20 @@ oxr_face_tracker2_fb_to_openxr(struct oxr_face_tracker2_fb *face_tracker2_fb) return XRT_CAST_PTR_TO_OXR_HANDLE(XrFaceTracker2FB, face_tracker2_fb); } #endif + +#ifdef OXR_HAVE_ANDROID_face_tracking +/*! + * To go back to a OpenXR object. + * + * @relates oxr_facial_tracker_htc + */ +static inline XrFaceTrackerANDROID +oxr_face_tracker_android_to_openxr(struct oxr_face_tracker_android *face_tracker_android) +{ + return XRT_CAST_PTR_TO_OXR_HANDLE(XrFaceTrackerANDROID, face_tracker_android); +} +#endif + /*! * * @name oxr_input.c @@ -3094,6 +3109,46 @@ XrResult oxr_event_push_XrEventDataUserPresenceChangedEXT(struct oxr_logger *log, struct oxr_session *sess, bool isUserPresent); #endif // OXR_HAVE_EXT_user_presence +#ifdef OXR_HAVE_ANDROID_face_tracking +/*! + * Android specific Facial tracker. + * + * Parent type/handle is @ref oxr_instance + * + * + * @obj{XrFaceTrackerANDROID} + * @extends oxr_handle_base + */ +struct oxr_face_tracker_android +{ + //! Common structure for things referred to by OpenXR handles. + struct oxr_handle_base handle; + + //! Owner of this face tracker. + struct oxr_session *sess; + + //! xrt_device backing this face tracker + struct xrt_device *xdev; +}; + +XrResult +oxr_face_tracker_android_create(struct oxr_logger *log, + struct oxr_session *sess, + const XrFaceTrackerCreateInfoANDROID *createInfo, + XrFaceTrackerANDROID *faceTracker); + +XrResult +oxr_get_face_state_android(struct oxr_logger *log, + struct oxr_face_tracker_android *facial_tracker_android, + const XrFaceStateGetInfoANDROID *getInfo, + XrFaceStateANDROID *faceStateOutput); + +XrResult +oxr_get_face_calibration_state_android(struct oxr_logger *log, + struct oxr_face_tracker_android *facial_tracker_android, + XrBool32 *faceIsCalibratedOutput); +#endif // OXR_HAVE_ANDROID_face_tracking + /*! * @} */