The open source OpenXR runtime
1// Copyright 2020-2024, Collabora, Ltd.
2// Copyright 2025, NVIDIA CORPORATION.
3// SPDX-License-Identifier: BSL-1.0
4/*!
5 * @file
6 * @brief Shared default implementation of the instance with compositor.
7 * @author Jakob Bornecrantz <jakob@collabora.com>
8 * @author Rylie Pavlik <rylie.pavlik@collabora.com>
9 */
10
11#include "xrt/xrt_space.h"
12#include "xrt/xrt_system.h"
13#include "xrt/xrt_config_build.h"
14#include "xrt/xrt_config_os.h"
15
16
17#include "os/os_time.h"
18
19#include "util/u_debug.h"
20#include "util/u_system.h"
21#include "util/u_trace_marker.h"
22#include "util/u_system_helpers.h"
23
24#ifdef XRT_MODULE_COMPOSITOR_MAIN
25#include "main/comp_main_interface.h"
26#endif
27
28#include "target_instance_parts.h"
29
30#include <assert.h>
31
32#ifdef XRT_OS_ANDROID
33#include "android/android_instance_base.h"
34#endif
35
36#ifdef XRT_MODULE_COMPOSITOR_MAIN
37#define USE_NULL_DEFAULT (false)
38#else
39#define USE_NULL_DEFAULT (true)
40#endif
41
42DEBUG_GET_ONCE_BOOL_OPTION(use_null, "XRT_COMPOSITOR_NULL", USE_NULL_DEFAULT)
43
44xrt_result_t
45null_compositor_create_system(struct xrt_device *xdev, struct xrt_system_compositor **out_xsysc);
46
47
48
49/*
50 *
51 * Internal functions.
52 *
53 */
54
55static xrt_result_t
56t_instance_is_system_available(struct xrt_instance *xinst, bool *out_available)
57{
58 XRT_TRACE_MARKER();
59
60 assert(out_available != NULL);
61
62 *out_available = true;
63
64 return XRT_SUCCESS;
65}
66
67static xrt_result_t
68t_instance_create_system(struct xrt_instance *xinst,
69 struct xrt_system **out_xsys,
70 struct xrt_system_devices **out_xsysd,
71 struct xrt_space_overseer **out_xso,
72 struct xrt_system_compositor **out_xsysc)
73{
74 XRT_TRACE_MARKER();
75
76 assert(out_xsys != NULL);
77 assert(*out_xsys == NULL);
78 assert(out_xsysd != NULL);
79 assert(*out_xsysd == NULL);
80 assert(out_xso != NULL);
81 assert(*out_xso == NULL);
82 assert(out_xsysc == NULL || *out_xsysc == NULL);
83
84 struct u_system *usys = NULL;
85 struct xrt_system_compositor *xsysc = NULL;
86 struct xrt_space_overseer *xso = NULL;
87 struct xrt_system_devices *xsysd = NULL;
88 xrt_result_t xret = XRT_SUCCESS;
89
90 usys = u_system_create();
91 assert(usys != NULL); // Should never fail.
92
93 xret = u_system_devices_create_from_prober( //
94 xinst, // xinst
95 &usys->broadcast, // broadcast
96 &xsysd, // out_xsysd
97 &xso); // out_xso
98 if (xret != XRT_SUCCESS) {
99 return xret;
100 }
101
102 // Early out if we only want devices.
103 if (out_xsysc == NULL) {
104 goto out;
105 }
106
107 struct xrt_device *head = xsysd->static_roles.head;
108 u_system_fill_properties(usys, head->str);
109
110 bool use_null = debug_get_bool_option_use_null();
111
112#ifdef XRT_MODULE_COMPOSITOR_NULL
113 if (use_null) {
114 xret = null_compositor_create_system(head, &xsysc);
115 }
116#else
117 if (use_null) {
118 U_LOG_E("The null compositor is not compiled in!");
119 xret = XRT_ERROR_VULKAN;
120 }
121#endif
122
123#ifdef XRT_MODULE_COMPOSITOR_MAIN
124 if (xret == XRT_SUCCESS && xsysc == NULL) {
125 xret = comp_main_create_system_compositor(head, NULL, NULL, &xsysc);
126 }
127#else
128 if (!use_null) {
129 U_LOG_E("Explicitly didn't request the null compositor, but the main compositor hasn't been built!");
130 xret = XRT_ERROR_VULKAN;
131 }
132#endif
133
134 if (xret != XRT_SUCCESS) {
135 goto err_destroy;
136 }
137
138out:
139 *out_xsys = &usys->base;
140 *out_xsysd = xsysd;
141 *out_xso = xso;
142
143 if (xsysc != NULL) {
144 // Tell the system about the system compositor.
145 u_system_set_system_compositor(usys, xsysc);
146
147 assert(out_xsysc != NULL);
148 *out_xsysc = xsysc;
149 }
150
151 return xret;
152
153
154err_destroy:
155 xrt_space_overseer_destroy(&xso);
156 xrt_system_devices_destroy(&xsysd);
157 u_system_destroy(&usys);
158
159 return xret;
160}
161
162
163/*
164 *
165 * Exported function(s).
166 *
167 */
168
169xrt_result_t
170xrt_instance_create(struct xrt_instance_info *ii, struct xrt_instance **out_xinst)
171{
172 struct xrt_prober *xp = NULL;
173
174 u_trace_marker_init();
175
176 XRT_TRACE_MARKER();
177
178 int ret = xrt_prober_create_with_lists(&xp, &target_lists);
179 if (ret < 0) {
180 return XRT_ERROR_PROBER_CREATION_FAILED;
181 }
182
183 struct t_instance *tinst = U_TYPED_CALLOC(struct t_instance);
184 tinst->base.is_system_available = t_instance_is_system_available;
185 tinst->base.create_system = t_instance_create_system;
186 tinst->base.get_prober = t_instance_get_prober;
187 tinst->base.destroy = t_instance_destroy;
188 tinst->xp = xp;
189
190 tinst->base.startup_timestamp = os_monotonic_get_ns();
191
192#ifdef XRT_OS_ANDROID
193 if (ii != NULL) {
194 ret = android_instance_base_init(&tinst->android, &tinst->base, ii);
195 if (ret < 0) {
196 xrt_prober_destroy(&xp);
197 free(tinst);
198 return ret;
199 }
200 }
201#endif // XRT_OS_ANDROID
202
203 *out_xinst = &tinst->base;
204
205 return XRT_SUCCESS;
206}