···11+// Copyright 2019-2023, Collabora, Ltd.
22+// SPDX-License-Identifier: BSL-1.0
33+/*!
44+ * @file
55+ * @brief Header defining xrt space and space overseer.
66+ * @author Jakob Bornecrantz <jakob@collabora.com>
77+ * @ingroup xrt_iface
88+ */
99+1010+#pragma once
1111+1212+#include "xrt/xrt_defines.h"
1313+1414+#ifdef __cplusplus
1515+extern "C" {
1616+#endif
1717+1818+1919+struct xrt_device;
2020+2121+/*!
2222+ * A space very similar to a OpenXR XrSpace but not a full one-to-one mapping,
2323+ * but used to power XrSpace.
2424+ *
2525+ * @see @ref xrt_space_overseer
2626+ * @see @ref design-spaces
2727+ * @ingroup xrt_iface
2828+ */
2929+struct xrt_space
3030+{
3131+ /*!
3232+ * Reference helper.
3333+ */
3434+ struct xrt_reference reference;
3535+3636+ /*!
3737+ * Destroy function.
3838+ */
3939+ void (*destroy)(struct xrt_space *xs);
4040+};
4141+4242+/*!
4343+ * Update the reference counts on space(s).
4444+ *
4545+ * @param[in,out] dst Pointer to a object reference: if the object reference is
4646+ * non-null will decrement its counter. The reference that
4747+ * @p dst points to will be set to @p src.
4848+ * @param[in] src New object for @p dst to refer to (may be null).
4949+ * If non-null, will have its refcount increased.
5050+ * @ingroup xrt_iface
5151+ * @relates xrt_space
5252+ */
5353+static inline void
5454+xrt_space_reference(struct xrt_space **dst, struct xrt_space *src)
5555+{
5656+ struct xrt_space *old_dst = *dst;
5757+5858+ if (old_dst == src) {
5959+ return;
6060+ }
6161+6262+ if (src) {
6363+ xrt_reference_inc(&src->reference);
6464+ }
6565+6666+ *dst = src;
6767+6868+ if (old_dst) {
6969+ if (xrt_reference_dec(&old_dst->reference)) {
7070+ old_dst->destroy(old_dst);
7171+ }
7272+ }
7373+}
7474+7575+/*!
7676+ * Object that oversees and manages spaces, one created for each XR system.
7777+ *
7878+ * The space overseer is used by the state tracker to query the poses of spaces
7979+ * and devices in that space system. While the default implementation
8080+ * @ref u_space_overseer implements the spaces as a graph of relatable spaces,
8181+ * that is a implementation detail (the interface also lends itself to that
8282+ * since bases have parents). As such the graph is not exposed in this interface
8383+ * and spaces are technically free floating.
8484+ *
8585+ * One advantage of the free floating nature is that an overseer implementation
8686+ * has much greater flexibility in configuring the graph to fit the current XR
8787+ * system the best, it also have freedom to reconfigure the graph at runtime
8888+ * should that be needed. Since any potential graph isn't exposed there is no
8989+ * need to synchronise it across the app process and the service process.
9090+ *
9191+ * @see @ref design-spaces
9292+ * @ingroup xrt_iface
9393+ */
9494+struct xrt_space_overseer
9595+{
9696+ struct
9797+ {
9898+ struct xrt_space *root; //!< Root space, always available
9999+ struct xrt_space *view; //!< View space, may be null (in very rare cases).
100100+ struct xrt_space *local; //!< Local space, may be null (in very rare cases).
101101+ struct xrt_space *stage; //!< Stage space, may be null.
102102+ struct xrt_space *unbounded; //!< Unbounded space, only here for slam trackers.
103103+104104+ /*!
105105+ * Semantic spaces to be mapped to OpenXR spaces.
106106+ */
107107+ } semantic;
108108+109109+ /*!
110110+ * Create a space with a fixed offset to the parent space.
111111+ *
112112+ * @param[in] xso Owning space overseer.
113113+ * @param[in] parent The parent space for the new space.
114114+ * @param[in] offset Offset to the space.
115115+ * @param[out] out_space The newly created space.
116116+ */
117117+ xrt_result_t (*create_offset_space)(struct xrt_space_overseer *xso,
118118+ struct xrt_space *parent,
119119+ const struct xrt_pose *offset,
120120+ struct xrt_space **out_space);
121121+122122+ /*!
123123+ * Create a space that wraps a device input pose, implicitly make the
124124+ * device's tracking space the returned space parent.
125125+ *
126126+ * @param[in] xso Owning space overseer.
127127+ * @param[in] xdev Device to get the pose from.
128128+ * @param[in] name Name of the pose input.
129129+ * @param[out] out_space The newly created space.
130130+ */
131131+ xrt_result_t (*create_pose_space)(struct xrt_space_overseer *xso,
132132+ struct xrt_device *xdev,
133133+ enum xrt_input_name name,
134134+ struct xrt_space **out_space);
135135+136136+ /*!
137137+ * Locate a space in the base space.
138138+ *
139139+ * @see xrt_device::get_tracked_pose.
140140+ *
141141+ * @param[in] xso Owning space overseer.
142142+ * @param[in] base_space The space that we want the pose in.
143143+ * @param[in] base_offset Offset if any to the base space.
144144+ * @param[in] at_timestamp_ns At which time.
145145+ * @param[in] space The space to be located.
146146+ * @param[in] offset Offset if any to the located space.
147147+ * @param[out] out_relation Resulting pose.
148148+ */
149149+ xrt_result_t (*locate_space)(struct xrt_space_overseer *xso,
150150+ struct xrt_space *base_space,
151151+ const struct xrt_pose *base_offset,
152152+ uint64_t at_timestamp_ns,
153153+ struct xrt_space *space,
154154+ const struct xrt_pose *offset,
155155+ struct xrt_space_relation *out_relation);
156156+157157+ /*!
158158+ * Locate a the origin of the tracking space of a device, this is not
159159+ * the same as the device position. In other words, what is the position
160160+ * of the space that the device is in, and which it returns its poses
161161+ * in. Needed to use @ref xrt_device::get_view_poses and
162162+ * @ref xrt_device::get_hand_tracking.
163163+ *
164164+ * @see xrt_device::get_tracked_pose.
165165+ *
166166+ * @param[in] xso Owning space overseer.
167167+ * @param[in] base_space The space that we want the pose in.
168168+ * @param[in] base_offset Offset if any to the base space.
169169+ * @param[in] at_timestamp_ns At which time.
170170+ * @param[in] xdev Device to get the pose from.
171171+ * @param[out] out_relation Resulting pose.
172172+ */
173173+ xrt_result_t (*locate_device)(struct xrt_space_overseer *xso,
174174+ struct xrt_space *base_space,
175175+ const struct xrt_pose *base_offset,
176176+ uint64_t at_timestamp_ns,
177177+ struct xrt_device *xdev,
178178+ struct xrt_space_relation *out_relation);
179179+180180+ /*!
181181+ * Destroy function.
182182+ *
183183+ * @param xso The space overseer.
184184+ */
185185+ void (*destroy)(struct xrt_space_overseer *xs);
186186+};
187187+188188+/*!
189189+ * @copydoc xrt_space_overseer::create_offset_space
190190+ *
191191+ * Helper for calling through the function pointer.
192192+ *
193193+ * @public @memberof xrt_space_overseer
194194+ */
195195+static inline xrt_result_t
196196+xrt_space_overseer_create_offset_space(struct xrt_space_overseer *xso,
197197+ struct xrt_space *parent,
198198+ const struct xrt_pose *offset,
199199+ struct xrt_space **out_space)
200200+{
201201+ return xso->create_offset_space(xso, parent, offset, out_space);
202202+}
203203+204204+/*!
205205+ * @copydoc xrt_space_overseer::create_pose_space
206206+ *
207207+ * Helper for calling through the function pointer.
208208+ *
209209+ * @public @memberof xrt_space_overseer
210210+ */
211211+static inline xrt_result_t
212212+xrt_space_overseer_create_pose_space(struct xrt_space_overseer *xso,
213213+ struct xrt_device *xdev,
214214+ enum xrt_input_name name,
215215+ struct xrt_space **out_space)
216216+{
217217+ return xso->create_pose_space(xso, xdev, name, out_space);
218218+}
219219+220220+/*!
221221+ * @copydoc xrt_space_overseer::locate_space
222222+ *
223223+ * Helper for calling through the function pointer.
224224+ *
225225+ * @public @memberof xrt_space_overseer
226226+ */
227227+static inline xrt_result_t
228228+xrt_space_overseer_locate_space(struct xrt_space_overseer *xso,
229229+ struct xrt_space *base_space,
230230+ const struct xrt_pose *base_offset,
231231+ uint64_t at_timestamp_ns,
232232+ struct xrt_space *space,
233233+ const struct xrt_pose *offset,
234234+ struct xrt_space_relation *out_relation)
235235+{
236236+ return xso->locate_space(xso, base_space, base_offset, at_timestamp_ns, space, offset, out_relation);
237237+}
238238+239239+/*!
240240+ * @copydoc xrt_space_overseer::locate_device
241241+ *
242242+ * Helper for calling through the function pointer.
243243+ *
244244+ * @public @memberof xrt_space_overseer
245245+ */
246246+static inline xrt_result_t
247247+xrt_space_overseer_locate_device(struct xrt_space_overseer *xso,
248248+ struct xrt_space *base_space,
249249+ const struct xrt_pose *base_offset,
250250+ uint64_t at_timestamp_ns,
251251+ struct xrt_device *xdev,
252252+ struct xrt_space_relation *out_relation)
253253+{
254254+ return xso->locate_device(xso, base_space, base_offset, at_timestamp_ns, xdev, out_relation);
255255+}
256256+257257+/*!
258258+ * Helper for calling through the function pointer: does a null check and sets
259259+ * xc_ptr to null if freed.
260260+ *
261261+ * @see xrt_space_overseer::destroy
262262+ * @public @memberof xrt_space_overseer
263263+ */
264264+static inline void
265265+xrt_space_overseer_destroy(struct xrt_space_overseer **xso_ptr)
266266+{
267267+ struct xrt_space_overseer *xso = *xso_ptr;
268268+ if (xso == NULL) {
269269+ return;
270270+ }
271271+272272+ xso->destroy(xso);
273273+ *xso_ptr = NULL;
274274+}
275275+276276+277277+#ifdef __cplusplus
278278+}
279279+#endif