The open source OpenXR runtime
1// Copyright 2023, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Helper to implement @ref xrt_session.
6 * @author Jakob Bornecrantz <jakob@collabora.com>
7 * @ingroup aux_util
8 */
9
10#include "util/u_system.h"
11#include "util/u_session.h"
12
13
14/*
15 *
16 * Helpers.
17 *
18 */
19
20static inline struct u_session *
21u_session(struct xrt_session *xs)
22{
23 return (struct u_session *)xs;
24}
25
26
27/*
28 *
29 * Member functions.
30 *
31 */
32
33static xrt_result_t
34push_event(struct xrt_session_event_sink *xses, const union xrt_session_event *xse)
35{
36 struct u_session *us = container_of(xses, struct u_session, sink);
37
38 u_session_event_push(us, xse);
39
40 return XRT_SUCCESS;
41}
42
43static xrt_result_t
44poll_events(struct xrt_session *xs, union xrt_session_event *out_xse)
45{
46 struct u_session *us = u_session(xs);
47
48 u_session_event_pop(us, out_xse);
49
50 return XRT_SUCCESS;
51}
52
53static void
54destroy(struct xrt_session *xs)
55{
56 struct u_session *us = u_session(xs);
57
58 struct u_session_event *event = us->events.ptr;
59 while (event) {
60 struct u_session_event *tmp = event->next;
61 free(event);
62 event = tmp;
63 }
64
65 us->events.ptr = NULL;
66
67 if (us->usys != NULL) {
68 u_system_remove_session(us->usys, &us->base, &us->sink);
69 }
70
71 free(xs);
72}
73
74
75/*
76 *
77 * 'Exported' functions.
78 *
79 */
80
81struct u_session *
82u_session_create(struct u_system *usys)
83{
84 struct u_session *us = U_TYPED_CALLOC(struct u_session);
85
86 // xrt_session fields.
87 us->base.poll_events = poll_events;
88 us->base.destroy = destroy;
89
90 // xrt_session_event_sink fields.
91 us->sink.push_event = push_event;
92
93 // u_session fields.
94 XRT_MAYBE_UNUSED int ret = os_mutex_init(&us->events.mutex);
95 assert(ret == 0);
96 us->usys = usys;
97
98 // If we got a u_system.
99 if (usys != NULL) {
100 u_system_add_session(usys, &us->base, &us->sink);
101 }
102
103 return us;
104}
105
106void
107u_session_event_push(struct u_session *us, const union xrt_session_event *xse)
108{
109 struct u_session_event *use = U_TYPED_CALLOC(struct u_session_event);
110 use->xse = *xse;
111
112 os_mutex_lock(&us->events.mutex);
113
114 // Find the last slot.
115 struct u_session_event **slot = &us->events.ptr;
116 while (*slot != NULL) {
117 slot = &(*slot)->next;
118 }
119
120 *slot = use;
121
122 os_mutex_unlock(&us->events.mutex);
123}
124
125void
126u_session_event_pop(struct u_session *us, union xrt_session_event *out_xse)
127{
128 U_ZERO(out_xse);
129 out_xse->type = XRT_SESSION_EVENT_NONE;
130
131 os_mutex_lock(&us->events.mutex);
132
133 if (us->events.ptr != NULL) {
134 struct u_session_event *use = us->events.ptr;
135
136 *out_xse = use->xse;
137 us->events.ptr = use->next;
138 free(use);
139 }
140
141 os_mutex_unlock(&us->events.mutex);
142}