oxr_system.c 10.1 KB
Newer Older
1
// Copyright 2018-2020, Collabora, Ltd.
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
2
3
4
5
6
7
8
9
10
11
12
// SPDX-License-Identifier: BSL-1.0
/*!
 * @file
 * @brief  Holds system related entrypoints.
 * @author Jakob Bornecrantz <jakob@collabora.com>
 * @ingroup oxr_main
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Ryan Pavlik's avatar
Ryan Pavlik committed
13
#include <inttypes.h>
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
14
15
16
#include <assert.h>

#include "xrt/xrt_device.h"
17
#include "util/u_debug.h"
18
#include "util/u_verify.h"
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
19
20
21
22

#include "oxr_objects.h"
#include "oxr_logger.h"
#include "oxr_two_call.h"
23
#include "oxr_chain.h"
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
24

25

26
DEBUG_GET_ONCE_NUM_OPTION(scale_percentage, "OXR_VIEWPORT_SCALE_PERCENTAGE", 100)
27

28

Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
29
static bool
30
oxr_system_matches(struct oxr_logger *log, struct oxr_system *sys, XrFormFactor form_factor)
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
31
32
33
34
35
36
37
38
39
40
41
{
	return form_factor == sys->form_factor;
}

XrResult
oxr_system_select(struct oxr_logger *log,
                  struct oxr_system **systems,
                  uint32_t num_systems,
                  XrFormFactor form_factor,
                  struct oxr_system **out_selected)
{
42
	if (num_systems == 0) {
43
44
		return oxr_error(log, XR_ERROR_FORM_FACTOR_UNSUPPORTED,
		                 "(getInfo->formFactor) no system available (given: %i)", form_factor);
45
46
	}

Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
47
48
49
50
51
52
53
54
55
56
	struct oxr_system *selected = NULL;
	for (uint32_t i = 0; i < num_systems; i++) {
		if (oxr_system_matches(log, systems[i], form_factor)) {
			selected = systems[i];
			break;
		}
	}

	if (selected == NULL) {
		return oxr_error(log, XR_ERROR_FORM_FACTOR_UNSUPPORTED,
57
58
59
		                 "(getInfo->formFactor) no matching system "
		                 "(given: %i, first: %i)",
		                 form_factor, systems[0]->form_factor);
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
60
61
62
63
64
65
66
	}

	*out_selected = selected;

	return XR_SUCCESS;
}

67
XrResult
68
oxr_system_verify_id(struct oxr_logger *log, const struct oxr_instance *inst, XrSystemId systemId)
69
70
{
	if (systemId != 1) {
71
		return oxr_error(log, XR_ERROR_SYSTEM_INVALID, "Invalid system %" PRIu64, systemId);
72
73
74
75
76
	}
	return XR_SUCCESS;
}

XrResult
77
oxr_system_get_by_id(struct oxr_logger *log, struct oxr_instance *inst, XrSystemId systemId, struct oxr_system **system)
78
79
80
81
82
83
84
85
86
87
88
89
{
	XrResult result = oxr_system_verify_id(log, inst, systemId);
	if (result != XR_SUCCESS) {
		return result;
	}

	/* right now only have one system. */
	*system = &inst->system;

	return XR_SUCCESS;
}

90
91


Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
92
XrResult
93
oxr_system_fill_in(struct oxr_logger *log, struct oxr_instance *inst, XrSystemId systemId, struct oxr_system *sys)
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
94
{
95
96
	//! @todo handle other subaction paths?

97
98
99
	sys->inst = inst;
	sys->systemId = systemId;
	sys->form_factor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
100
101
	sys->view_config_type = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;

102
#ifdef XR_USE_GRAPHICS_API_VULKAN
103
	sys->vulkan_enable2_instance = VK_NULL_HANDLE;
104
	sys->suggested_vulkan_physical_device = VK_NULL_HANDLE;
105
#endif
106

107
	// Headless.
108
	if (sys->xsysc == NULL) {
109
110
111
112
113
		sys->blend_modes[0] = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
		sys->num_blend_modes = 1;
		return XR_SUCCESS;
	}

114
	double scale = debug_get_num_option_scale_percentage() / 100.0;
115
116
117
118
	if (scale > 2.0) {
		scale = 2.0;
		oxr_log(log, "Clamped scale to 200%%\n");
	}
119

120
	struct xrt_system_compositor_info *info = &sys->xsysc->info;
121
122
123
124
125
126
127
128
129
130
131
132

	uint32_t w0 = (uint32_t)(info->views[0].recommended.width_pixels * scale);
	uint32_t h0 = (uint32_t)(info->views[0].recommended.height_pixels * scale);
	uint32_t w1 = (uint32_t)(info->views[1].recommended.width_pixels * scale);
	uint32_t h1 = (uint32_t)(info->views[1].recommended.height_pixels * scale);

	uint32_t w0_2 = info->views[0].max.width_pixels;
	uint32_t h0_2 = info->views[0].max.height_pixels;
	uint32_t w1_2 = info->views[1].max.width_pixels;
	uint32_t h1_2 = info->views[1].max.height_pixels;

#define imin(a, b) (a < b ? a : b)
133

134
135
136
137
	w0 = imin(w0, w0_2);
	h0 = imin(h0, h0_2);
	w1 = imin(w1, w1_2);
	h1 = imin(h1, h1_2);
138

139
#undef imin
140

141
	// clang-format off
142
	sys->views[0].recommendedImageRectWidth       = w0;
143
	sys->views[0].maxImageRectWidth               = w0_2;
144
	sys->views[0].recommendedImageRectHeight      = h0;
145
	sys->views[0].maxImageRectHeight              = h0_2;
146
147
	sys->views[0].recommendedSwapchainSampleCount = info->views[0].recommended.sample_count;
	sys->views[0].maxSwapchainSampleCount         = info->views[0].max.sample_count;
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
148

149
	sys->views[1].recommendedImageRectWidth       = w1;
150
	sys->views[1].maxImageRectWidth               = w1_2;
151
	sys->views[1].recommendedImageRectHeight      = h1;
152
	sys->views[1].maxImageRectHeight              = h1_2;
153
154
	sys->views[1].recommendedSwapchainSampleCount = info->views[1].recommended.sample_count;
	sys->views[1].maxSwapchainSampleCount         = info->views[1].max.sample_count;
155
	// clang-format on
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
156

157
158
	struct xrt_device *head = GET_XDEV_BY_ROLE(sys, head);

159
160
	assert(head->hmd->num_blend_modes <= XRT_MAX_DEVICE_BLEND_MODES);
	assert(head->hmd->num_blend_modes != 0);
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
161

162
163
164
165
166
	for (size_t i = 0; i < head->hmd->num_blend_modes; i++) {
		assert(u_verify_blend_mode_valid(head->hmd->blend_modes[i]));
		sys->blend_modes[i] = (XrEnvironmentBlendMode)head->hmd->blend_modes[i];
	}
	sys->num_blend_modes = (uint32_t)head->hmd->num_blend_modes;
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
167

168
	assert(sys->num_blend_modes <= ARRAY_SIZE(sys->blend_modes));
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
169
170
171
172

	return XR_SUCCESS;
}

173
bool
174
oxr_system_get_hand_tracking_support(struct oxr_logger *log, struct oxr_instance *inst)
175
176
177
178
179
180
181
182
183
184
{
	struct oxr_system *sys = &inst->system;
	struct xrt_device *left = GET_XDEV_BY_ROLE(sys, left);
	struct xrt_device *right = GET_XDEV_BY_ROLE(sys, right);

	bool left_supported = left && left->hand_tracking_supported;
	bool right_supported = right && right->hand_tracking_supported;
	return left_supported || right_supported;
}

Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
185
XrResult
186
oxr_system_get_properties(struct oxr_logger *log, struct oxr_system *sys, XrSystemProperties *properties)
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
187
188
189
{
	properties->vendorId = 42;
	properties->systemId = sys->systemId;
190

191
192
	struct xrt_device *xdev = GET_XDEV_BY_ROLE(sys, head);

193
	// The magical 247 number, is to silence warnings.
194
	snprintf(properties->systemName, XR_MAX_SYSTEM_NAME_SIZE, "Monado: %.*s", 247, xdev->str);
195

196
	// Get from compositor.
197
	struct xrt_system_compositor_info *info = sys->xsysc ? &sys->xsysc->info : NULL;
198

199
200
201
202
203
204
	if (info) {
		properties->graphicsProperties.maxLayerCount = info->max_layers;
	} else {
		// probably using the headless extension, but the extension does not modify the 16 layer minimum.
		properties->graphicsProperties.maxLayerCount = 16;
	}
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
205
206
	properties->graphicsProperties.maxSwapchainImageWidth = 1024 * 16;
	properties->graphicsProperties.maxSwapchainImageHeight = 1024 * 16;
207
208
	properties->trackingProperties.orientationTracking = xdev->orientation_tracking_supported;
	properties->trackingProperties.positionTracking = xdev->position_tracking_supported;
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
209

210
211
212
213
214
215
	XrSystemHandTrackingPropertiesEXT *hand_tracking_props = NULL;
	// We should only be looking for extension structs if the extension has been enabled.
	if (sys->inst->extensions.EXT_hand_tracking) {
		hand_tracking_props = OXR_GET_OUTPUT_FROM_CHAIN(properties, XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT,
		                                                XrSystemHandTrackingPropertiesEXT);
	}
216
217

	if (hand_tracking_props) {
218
		hand_tracking_props->supportsHandTracking = oxr_system_get_hand_tracking_support(log, sys->inst);
219
220
	}

Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
221
222
223
224
225
226
227
228
229
230
	return XR_SUCCESS;
}

XrResult
oxr_system_enumerate_view_confs(struct oxr_logger *log,
                                struct oxr_system *sys,
                                uint32_t viewConfigurationTypeCapacityInput,
                                uint32_t *viewConfigurationTypeCountOutput,
                                XrViewConfigurationType *viewConfigurationTypes)
{
231
232
	OXR_TWO_CALL_HELPER(log, viewConfigurationTypeCapacityInput, viewConfigurationTypeCountOutput,
	                    viewConfigurationTypes, 1, &sys->view_config_type, XR_SUCCESS);
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
233
234
235
236
237
}

XrResult
oxr_system_enumerate_blend_modes(struct oxr_logger *log,
                                 struct oxr_system *sys,
238
                                 XrViewConfigurationType viewConfigurationType,
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
239
240
241
242
                                 uint32_t environmentBlendModeCapacityInput,
                                 uint32_t *environmentBlendModeCountOutput,
                                 XrEnvironmentBlendMode *environmentBlendModes)
{
243
	//! @todo Take into account viewConfigurationType
244
245
	OXR_TWO_CALL_HELPER(log, environmentBlendModeCapacityInput, environmentBlendModeCountOutput,
	                    environmentBlendModes, sys->num_blend_modes, sys->blend_modes, XR_SUCCESS);
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
246
247
248
}

XrResult
249
250
251
252
oxr_system_get_view_conf_properties(struct oxr_logger *log,
                                    struct oxr_system *sys,
                                    XrViewConfigurationType viewConfigurationType,
                                    XrViewConfigurationProperties *configurationProperties)
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
253
254
{
	if (viewConfigurationType != sys->view_config_type) {
255
		return oxr_error(log, XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED, "Invalid view configuration type");
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
256
257
258
	}

	configurationProperties->viewConfigurationType = sys->view_config_type;
Ryan Pavlik's avatar
Ryan Pavlik committed
259
	configurationProperties->fovMutable = XR_FALSE;
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
260
261
262
263

	return XR_SUCCESS;
}

264
static void
265
view_configuration_view_fill_in(XrViewConfigurationView *target_view, XrViewConfigurationView *source_view)
266
267
268
269
270
271
272
273
274
275
276
{
	// clang-format off
	target_view->recommendedImageRectWidth       = source_view->recommendedImageRectWidth;
	target_view->maxImageRectWidth               = source_view->maxImageRectWidth;
	target_view->recommendedImageRectHeight      = source_view->recommendedImageRectHeight;
	target_view->maxImageRectHeight              = source_view->maxImageRectHeight;
	target_view->recommendedSwapchainSampleCount = source_view->recommendedSwapchainSampleCount;
	target_view->maxSwapchainSampleCount         = source_view->maxSwapchainSampleCount;
	// clang-format on
}

Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
277
XrResult
278
279
280
281
282
283
oxr_system_enumerate_view_conf_views(struct oxr_logger *log,
                                     struct oxr_system *sys,
                                     XrViewConfigurationType viewConfigurationType,
                                     uint32_t viewCapacityInput,
                                     uint32_t *viewCountOutput,
                                     XrViewConfigurationView *views)
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
284
285
{
	if (viewConfigurationType != sys->view_config_type) {
286
		return oxr_error(log, XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED, "Invalid view configuration type");
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
287
288
	}

289
	OXR_TWO_CALL_FILL_IN_HELPER(log, viewCapacityInput, viewCountOutput, views, 2, view_configuration_view_fill_in,
290
	                            sys->views, XR_SUCCESS);
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
291
}