The open source OpenXR runtime
1// Copyright 2020-2023, Collabora, Ltd.
2// Copyright 2025, NVIDIA CORPORATION.
3// SPDX-License-Identifier: BSL-1.0
4/*!
5 * @file
6 * @brief Client side wrapper of @ref xrt_system.
7 * @author Jakob Bornecrantz <jakob@collabora.com>
8 * @ingroup ipc_client
9 */
10
11#include "xrt/xrt_defines.h"
12#include "xrt/xrt_system.h"
13#include "xrt/xrt_session.h"
14
15#include "ipc_client_generated.h"
16
17#include <assert.h>
18
19/*!
20 * IPC client implementation of @ref xrt_system.
21 *
22 * @implements xrt_system
23 * @ingroup ipc_client
24 */
25struct ipc_client_system
26{
27 struct xrt_system base;
28
29 struct ipc_connection *ipc_c;
30
31 struct xrt_system_compositor *xsysc;
32};
33
34
35/*
36 *
37 * Helpers
38 *
39 */
40
41static inline struct ipc_client_system *
42ipc_system(struct xrt_system *xsys)
43{
44 return (struct ipc_client_system *)xsys;
45}
46
47static inline xrt_result_t
48create_headless(struct ipc_client_system *icsys, const struct xrt_session_info *xsi, struct xrt_session **out_xs)
49{
50 xrt_result_t xret = XRT_SUCCESS;
51
52 // We create the session ourselves.
53 xret = ipc_call_session_create( //
54 icsys->ipc_c, // ipc_c
55 xsi, // xsi
56 false); // create_native_compositor
57 IPC_CHK_AND_RET(icsys->ipc_c, xret, "ipc_call_session_create");
58
59 struct xrt_session *xs = ipc_client_session_create(icsys->ipc_c);
60 assert(xs != NULL);
61
62 *out_xs = xs;
63
64 return XRT_SUCCESS;
65}
66
67static inline xrt_result_t
68create_with_comp(struct ipc_client_system *icsys,
69 const struct xrt_session_info *xsi,
70 struct xrt_session **out_xs,
71 struct xrt_compositor_native **out_xcn)
72{
73 xrt_result_t xret = XRT_SUCCESS;
74
75 assert(icsys->xsysc != NULL);
76
77 // The native compositor creates the session.
78 xret = ipc_client_create_native_compositor( //
79 icsys->xsysc, //
80 xsi, //
81 out_xcn); //
82 IPC_CHK_AND_RET(icsys->ipc_c, xret, "ipc_client_create_native_compositor");
83
84 struct xrt_session *xs = ipc_client_session_create(icsys->ipc_c);
85 assert(xs != NULL);
86
87 *out_xs = xs;
88
89 return XRT_SUCCESS;
90}
91
92
93/*
94 *
95 * Member functions.
96 *
97 */
98
99static xrt_result_t
100ipc_client_system_create_session(struct xrt_system *xsys,
101 const struct xrt_session_info *xsi,
102 struct xrt_session **out_xs,
103 struct xrt_compositor_native **out_xcn)
104{
105 struct ipc_client_system *icsys = ipc_system(xsys);
106
107 if (out_xcn != NULL && icsys->xsysc == NULL) {
108 U_LOG_E("No system compositor in system, can't create native compositor.");
109 return XRT_ERROR_COMPOSITOR_NOT_SUPPORTED;
110 }
111
112 // Skip making a native compositor if not asked for.
113 if (out_xcn == NULL) {
114 return create_headless(icsys, xsi, out_xs);
115 } else {
116 return create_with_comp(icsys, xsi, out_xs, out_xcn);
117 }
118}
119
120static void
121ipc_client_system_destroy(struct xrt_system *xsys)
122{
123 struct ipc_client_system *icsys = ipc_system(xsys);
124
125 free(icsys);
126}
127
128
129/*
130 *
131 * 'Exported' functions.
132 *
133 */
134
135struct xrt_system *
136ipc_client_system_create(struct ipc_connection *ipc_c, struct xrt_system_compositor *xsysc)
137{
138 struct ipc_client_system *icsys = U_TYPED_CALLOC(struct ipc_client_system);
139
140 xrt_result_t xret = ipc_call_system_get_properties(ipc_c, &icsys->base.properties);
141 IPC_CHK_ONLY_PRINT(ipc_c, xret, "ipc_call_system_get_properties");
142 if (xret != XRT_SUCCESS) {
143 free(icsys);
144 return NULL;
145 }
146
147 icsys->base.create_session = ipc_client_system_create_session;
148 icsys->base.destroy = ipc_client_system_destroy;
149 icsys->ipc_c = ipc_c;
150 icsys->xsysc = xsysc;
151
152 return &icsys->base;
153}