2020-06-01 20:32:43 +00:00
|
|
|
// Copyright 2018-2020, Collabora, Ltd.
|
2019-03-18 05:52:32 +00:00
|
|
|
// SPDX-License-Identifier: BSL-1.0
|
|
|
|
/*!
|
|
|
|
* @file
|
2020-03-31 16:24:58 +00:00
|
|
|
* @brief File for verifying app input into api functions.
|
2019-03-18 05:52:32 +00:00
|
|
|
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
|
|
|
|
* @author Jakob Bornecrantz <jakob@collabora.com>
|
|
|
|
* @ingroup oxr_main
|
|
|
|
* @ingroup oxr_api
|
|
|
|
*/
|
|
|
|
|
2019-10-08 14:40:40 +00:00
|
|
|
#include <assert.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2019-03-18 05:52:32 +00:00
|
|
|
|
|
|
|
#include "xrt/xrt_compiler.h"
|
|
|
|
#include "util/u_debug.h"
|
|
|
|
|
|
|
|
#include "oxr_objects.h"
|
|
|
|
#include "oxr_logger.h"
|
|
|
|
#include "oxr_api_verify.h"
|
2019-06-03 19:13:05 +00:00
|
|
|
#include "oxr_chain.h"
|
2020-07-20 19:53:52 +00:00
|
|
|
#include "oxr_subaction.h"
|
2019-03-18 05:52:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Path verification.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2019-04-05 09:37:57 +00:00
|
|
|
static bool
|
|
|
|
valid_path_char(const char c)
|
|
|
|
{
|
|
|
|
if ('a' <= c && c <= 'z') {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ('0' <= c && c <= '9') {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c == '-' || c == '_' || c == '.' || c == '/') {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-03-25 01:18:17 +00:00
|
|
|
static bool
|
2019-09-29 10:43:45 +00:00
|
|
|
contains_zero(const char *path, uint32_t size)
|
2019-03-18 05:52:32 +00:00
|
|
|
{
|
|
|
|
for (uint32_t i = 0; i < size; i++) {
|
|
|
|
if (path[i] == '\0') {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-10-08 14:40:40 +00:00
|
|
|
XrResult
|
2021-01-14 14:13:48 +00:00
|
|
|
oxr_verify_fixed_size_single_level_path(struct oxr_logger *log, const char *path, uint32_t array_size, const char *name)
|
2019-03-18 05:52:32 +00:00
|
|
|
{
|
2019-04-05 09:37:57 +00:00
|
|
|
if (array_size == 0) {
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, "(%s) internal runtime error", name);
|
2019-03-18 05:52:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (path[0] == '\0') {
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_NAME_INVALID, "(%s) can not be empty", name);
|
2019-03-18 05:52:32 +00:00
|
|
|
}
|
|
|
|
|
2019-04-05 09:37:57 +00:00
|
|
|
if (!contains_zero(path, array_size)) {
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_PATH_FORMAT_INVALID, "(%s) must include zero termination '\\0'.", name);
|
2019-03-18 05:52:32 +00:00
|
|
|
}
|
|
|
|
|
2019-04-05 09:37:57 +00:00
|
|
|
size_t length = strlen(path);
|
|
|
|
for (size_t i = 0; i < length; i++) {
|
|
|
|
const char c = path[i];
|
|
|
|
|
|
|
|
// Slashes are not valid in single level paths.
|
|
|
|
if (valid_path_char(c) && c != '/') {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_PATH_FORMAT_INVALID,
|
|
|
|
"(%s) 0x%02x is not a valid character at position %u", name, c, (uint32_t)i);
|
2019-04-05 09:37:57 +00:00
|
|
|
}
|
2019-03-18 05:52:32 +00:00
|
|
|
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2019-10-08 14:40:40 +00:00
|
|
|
XrResult
|
2021-01-14 14:13:48 +00:00
|
|
|
oxr_verify_localized_name(struct oxr_logger *log, const char *string, uint32_t array_size, const char *name)
|
2019-04-13 15:11:47 +00:00
|
|
|
{
|
|
|
|
if (array_size == 0) {
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, "(%s) internal runtime error", name);
|
2019-04-13 15:11:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (string[0] == '\0') {
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_LOCALIZED_NAME_INVALID, "(%s) can not be empty", name);
|
2019-04-13 15:11:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!contains_zero(string, array_size)) {
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_LOCALIZED_NAME_INVALID, "(%s) must include zero termination '\\0'.",
|
2019-04-13 15:11:47 +00:00
|
|
|
name);
|
|
|
|
}
|
|
|
|
|
2022-05-17 20:27:50 +00:00
|
|
|
/// @todo validate well-formed UTF-8?
|
2019-04-13 15:11:47 +00:00
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2019-10-08 14:40:40 +00:00
|
|
|
enum verify_state
|
2019-04-05 11:54:37 +00:00
|
|
|
{
|
2019-10-08 14:40:40 +00:00
|
|
|
VERIFY_START,
|
|
|
|
VERIFY_MIDDLE,
|
|
|
|
VERIFY_SLASH,
|
|
|
|
VERIFY_SLASHDOTS,
|
2019-04-05 11:54:37 +00:00
|
|
|
};
|
|
|
|
|
2019-10-08 14:40:40 +00:00
|
|
|
XrResult
|
2021-01-14 14:13:48 +00:00
|
|
|
oxr_verify_full_path_c(struct oxr_logger *log, const char *path, const char *name)
|
2019-04-05 11:54:37 +00:00
|
|
|
{
|
2019-04-16 00:10:37 +00:00
|
|
|
// XR_MAX_PATH_LENGTH is max including null terminator,
|
|
|
|
// length will not include null terminator
|
|
|
|
size_t length = XR_MAX_PATH_LENGTH;
|
|
|
|
for (size_t i = 0; i < XR_MAX_PATH_LENGTH; i++) {
|
|
|
|
if (path[i] == '\0') {
|
|
|
|
length = i;
|
|
|
|
break;
|
|
|
|
}
|
2019-04-05 11:54:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return oxr_verify_full_path(log, path, (uint32_t)length, name);
|
|
|
|
}
|
|
|
|
|
2019-10-08 14:40:40 +00:00
|
|
|
XrResult
|
2021-01-14 14:13:48 +00:00
|
|
|
oxr_verify_full_path(struct oxr_logger *log, const char *path, size_t length, const char *name)
|
2019-04-05 11:54:37 +00:00
|
|
|
{
|
2019-10-08 14:40:40 +00:00
|
|
|
enum verify_state state = VERIFY_START;
|
2019-04-05 11:54:37 +00:00
|
|
|
bool valid = true;
|
|
|
|
|
2019-04-16 00:10:37 +00:00
|
|
|
if (length >= XR_MAX_PATH_LENGTH) {
|
|
|
|
char formatted_path[XR_MAX_PATH_LENGTH + 6];
|
2021-01-14 14:13:48 +00:00
|
|
|
snprintf(formatted_path, XR_MAX_PATH_LENGTH + 6, "%s[...]", path);
|
2019-04-16 00:10:37 +00:00
|
|
|
return oxr_error(log, XR_ERROR_PATH_FORMAT_INVALID,
|
|
|
|
"(%s) is too long for a path, must be shorter "
|
|
|
|
"than %u characters",
|
|
|
|
name, XR_MAX_PATH_LENGTH);
|
2019-04-05 11:54:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < length; i++) {
|
|
|
|
const char c = path[i];
|
|
|
|
switch (state) {
|
2019-10-08 14:40:40 +00:00
|
|
|
case VERIFY_START:
|
2019-04-05 11:54:37 +00:00
|
|
|
if (c != '/') {
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_PATH_FORMAT_INVALID,
|
2019-04-05 11:54:37 +00:00
|
|
|
"(%s) does not start with a "
|
|
|
|
"fowrward slash",
|
|
|
|
name);
|
|
|
|
}
|
2019-10-08 14:40:40 +00:00
|
|
|
state = VERIFY_SLASH;
|
2019-04-05 11:54:37 +00:00
|
|
|
break;
|
2019-10-08 14:40:40 +00:00
|
|
|
case VERIFY_SLASH:
|
2019-04-05 11:54:37 +00:00
|
|
|
switch (c) {
|
|
|
|
case '.':
|
|
|
|
// Is valid and starts the SlashDot(s) state.
|
2019-10-08 14:40:40 +00:00
|
|
|
state = VERIFY_SLASHDOTS;
|
2019-04-05 11:54:37 +00:00
|
|
|
break;
|
|
|
|
case '/':
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_PATH_FORMAT_INVALID,
|
|
|
|
"(%s) '//' is not a valid in a path", name);
|
|
|
|
default: valid = valid_path_char(c); state = VERIFY_MIDDLE;
|
2019-04-05 11:54:37 +00:00
|
|
|
}
|
|
|
|
break;
|
2019-10-08 14:40:40 +00:00
|
|
|
case VERIFY_MIDDLE:
|
2019-04-05 11:54:37 +00:00
|
|
|
switch (c) {
|
2019-10-08 14:40:40 +00:00
|
|
|
case '/': state = VERIFY_SLASH; break;
|
2021-01-14 14:13:48 +00:00
|
|
|
default: valid = valid_path_char(c); state = VERIFY_MIDDLE;
|
2019-04-05 11:54:37 +00:00
|
|
|
}
|
|
|
|
break;
|
2019-10-08 14:40:40 +00:00
|
|
|
case VERIFY_SLASHDOTS:
|
2019-04-05 11:54:37 +00:00
|
|
|
switch (c) {
|
|
|
|
case '/':
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_PATH_FORMAT_INVALID,
|
|
|
|
"(%s) '/.[.]*/' is not a valid in a path", name);
|
2019-04-05 11:54:37 +00:00
|
|
|
case '.':
|
|
|
|
// It's valid, more ShashDot(s).
|
|
|
|
break;
|
2021-01-14 14:13:48 +00:00
|
|
|
default: valid = valid_path_char(c); state = VERIFY_MIDDLE;
|
2019-04-05 11:54:37 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-09-24 15:19:52 +00:00
|
|
|
if (valid) {
|
|
|
|
// Can't end with slash
|
|
|
|
valid = (path[length - 1] != '/');
|
|
|
|
}
|
2019-04-05 11:54:37 +00:00
|
|
|
if (!valid) {
|
|
|
|
return oxr_error(log, XR_ERROR_PATH_FORMAT_INVALID,
|
|
|
|
"(%s) 0x%02x is not a valid character "
|
|
|
|
"at position %u",
|
|
|
|
name, c, (uint32_t)length);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (state) {
|
2019-10-08 14:40:40 +00:00
|
|
|
case VERIFY_START:
|
2019-04-05 11:54:37 +00:00
|
|
|
// Empty string
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_PATH_FORMAT_INVALID, "(%s) a empty string is not a valid path", name);
|
2019-10-08 14:40:40 +00:00
|
|
|
case VERIFY_SLASH:
|
2022-05-17 20:27:50 +00:00
|
|
|
// Is this '/path_component/' or '/'
|
2019-04-05 11:54:37 +00:00
|
|
|
if (length > 1) {
|
2022-05-17 20:27:50 +00:00
|
|
|
// It was '/path_component/'
|
2019-04-05 11:54:37 +00:00
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
// It was '/'
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_PATH_FORMAT_INVALID, "(%s) the string '%s' is not a valid path", name,
|
|
|
|
path);
|
2019-10-08 14:40:40 +00:00
|
|
|
case VERIFY_SLASHDOTS:
|
2019-04-05 11:54:37 +00:00
|
|
|
// Does the path ends with '/..'
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_PATH_FORMAT_INVALID, "(%s) strings ending with '/.[.]*' is not a valid",
|
|
|
|
name);
|
2019-04-05 11:54:37 +00:00
|
|
|
|
2019-10-08 14:40:40 +00:00
|
|
|
case VERIFY_MIDDLE:
|
2022-05-17 20:27:50 +00:00
|
|
|
// '/path_component/trailing_path_component' okay!
|
2019-04-05 11:54:37 +00:00
|
|
|
return XR_SUCCESS;
|
|
|
|
default:
|
|
|
|
// We should not end up here.
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, "(%s) internal runtime error validating path (%s)",
|
|
|
|
name, path);
|
2019-04-05 11:54:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-18 05:52:32 +00:00
|
|
|
|
2019-05-07 12:47:18 +00:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Subaction path functions.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static XrResult
|
2019-09-29 10:43:45 +00:00
|
|
|
subaction_path_no_dups(struct oxr_logger *log,
|
|
|
|
struct oxr_instance *inst,
|
2020-10-23 12:39:59 +00:00
|
|
|
struct oxr_subaction_paths *subaction_paths,
|
2019-05-07 12:47:18 +00:00
|
|
|
XrPath path,
|
2019-09-29 10:43:45 +00:00
|
|
|
const char *variable,
|
2019-05-07 12:47:18 +00:00
|
|
|
uint32_t index)
|
|
|
|
{
|
2020-10-23 12:39:59 +00:00
|
|
|
assert(subaction_paths);
|
2019-05-07 12:47:18 +00:00
|
|
|
bool duplicate = false;
|
|
|
|
|
|
|
|
if (path == XR_NULL_PATH) {
|
|
|
|
return oxr_error(log, XR_ERROR_PATH_INVALID,
|
|
|
|
"(%s[%u] == XR_NULL_PATH) not a "
|
|
|
|
"valid subaction path.",
|
|
|
|
variable, index);
|
2019-08-16 22:02:18 +00:00
|
|
|
}
|
|
|
|
|
2021-01-14 14:13:48 +00:00
|
|
|
#define HANDLE_SUBACTION_PATH(X) \
|
|
|
|
if (path == inst->path_cache.X) { \
|
2020-10-23 12:39:59 +00:00
|
|
|
if (subaction_paths->X) { \
|
2021-01-14 14:13:48 +00:00
|
|
|
duplicate = true; \
|
|
|
|
} else { \
|
2020-10-23 12:39:59 +00:00
|
|
|
subaction_paths->X = true; \
|
2021-01-14 14:13:48 +00:00
|
|
|
} \
|
2020-07-20 19:53:52 +00:00
|
|
|
} else
|
|
|
|
|
|
|
|
OXR_FOR_EACH_VALID_SUBACTION_PATH(HANDLE_SUBACTION_PATH)
|
|
|
|
{
|
|
|
|
// else clasue
|
2019-09-29 10:43:45 +00:00
|
|
|
const char *str = NULL;
|
2019-05-07 12:47:18 +00:00
|
|
|
size_t length = 0;
|
|
|
|
|
|
|
|
oxr_path_get_string(log, inst, path, &str, &length);
|
2020-05-30 22:32:06 +00:00
|
|
|
return oxr_error(log, XR_ERROR_PATH_UNSUPPORTED,
|
2019-05-07 12:47:18 +00:00
|
|
|
"(%s[%u] == '%s') path is not a "
|
|
|
|
"valid subaction path.",
|
|
|
|
variable, index, str);
|
|
|
|
}
|
2020-07-20 19:53:52 +00:00
|
|
|
#undef HANDLE_SUBACTION_PATH
|
2019-05-07 12:47:18 +00:00
|
|
|
|
|
|
|
if (duplicate) {
|
2019-09-29 10:43:45 +00:00
|
|
|
const char *str = NULL;
|
2019-05-07 12:47:18 +00:00
|
|
|
size_t length = 0;
|
|
|
|
|
|
|
|
oxr_path_get_string(log, inst, path, &str, &length);
|
|
|
|
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_PATH_UNSUPPORTED, "(%s[%u] == '%s') duplicate paths", variable, index,
|
|
|
|
str);
|
2019-05-07 12:47:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-10-08 14:40:40 +00:00
|
|
|
XrResult
|
2019-09-29 10:43:45 +00:00
|
|
|
oxr_verify_subaction_paths_create(struct oxr_logger *log,
|
|
|
|
struct oxr_instance *inst,
|
2019-05-07 12:47:18 +00:00
|
|
|
uint32_t countSubactionPaths,
|
2019-09-29 10:43:45 +00:00
|
|
|
const XrPath *subactionPaths,
|
|
|
|
const char *variable)
|
2019-05-07 12:47:18 +00:00
|
|
|
{
|
2020-10-23 12:39:59 +00:00
|
|
|
struct oxr_subaction_paths subaction_paths = {0};
|
2019-05-07 12:47:18 +00:00
|
|
|
|
|
|
|
for (uint32_t i = 0; i < countSubactionPaths; i++) {
|
|
|
|
XrPath path = subactionPaths[i];
|
|
|
|
|
2020-10-23 12:39:59 +00:00
|
|
|
XrResult ret = subaction_path_no_dups(log, inst, &subaction_paths, path, variable, i);
|
2019-05-07 12:47:18 +00:00
|
|
|
if (ret != XR_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2019-10-08 14:40:40 +00:00
|
|
|
XrResult
|
2021-01-14 14:13:48 +00:00
|
|
|
oxr_verify_subaction_path_sync(struct oxr_logger *log, struct oxr_instance *inst, XrPath path, uint32_t index)
|
2019-05-07 12:47:18 +00:00
|
|
|
{
|
2021-01-14 14:13:48 +00:00
|
|
|
#define VERIFY_PATH(X) \
|
|
|
|
else if (path == inst->path_cache.X) \
|
|
|
|
{ \
|
|
|
|
return XR_SUCCESS; \
|
2020-07-20 19:53:52 +00:00
|
|
|
}
|
|
|
|
if (path == XR_NULL_PATH) {
|
2019-05-07 12:47:18 +00:00
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
2020-07-20 19:53:52 +00:00
|
|
|
OXR_FOR_EACH_SUBACTION_PATH(VERIFY_PATH)
|
|
|
|
|
|
|
|
#undef VERIFY_PATH
|
|
|
|
|
2019-09-29 10:43:45 +00:00
|
|
|
const char *str = NULL;
|
2019-08-16 22:02:18 +00:00
|
|
|
size_t length = 0;
|
|
|
|
|
|
|
|
oxr_path_get_string(log, inst, path, &str, &length);
|
|
|
|
return oxr_error(log, XR_ERROR_PATH_INVALID,
|
|
|
|
"(actionSets[%i].subactionPath == '%s') path "
|
|
|
|
"is not a valid subaction path.",
|
|
|
|
index, str);
|
2019-05-07 12:47:18 +00:00
|
|
|
}
|
|
|
|
|
2019-10-08 14:40:40 +00:00
|
|
|
XrResult
|
2019-09-29 10:43:45 +00:00
|
|
|
oxr_verify_subaction_path_get(struct oxr_logger *log,
|
|
|
|
struct oxr_instance *inst,
|
2019-05-07 12:47:18 +00:00
|
|
|
XrPath path,
|
2020-10-23 12:39:59 +00:00
|
|
|
const struct oxr_subaction_paths *act_subaction_paths,
|
|
|
|
struct oxr_subaction_paths *out_subaction_paths,
|
2019-09-29 10:43:45 +00:00
|
|
|
const char *variable)
|
2019-05-07 12:47:18 +00:00
|
|
|
{
|
2020-10-23 12:39:59 +00:00
|
|
|
struct oxr_subaction_paths subaction_paths = {0};
|
2019-05-07 12:47:18 +00:00
|
|
|
|
2021-01-14 14:13:48 +00:00
|
|
|
#define GET_PATH(X) \
|
|
|
|
else if (path == inst->path_cache.X) \
|
|
|
|
{ \
|
2020-10-23 12:39:59 +00:00
|
|
|
subaction_paths.X = true; \
|
2020-07-20 19:53:52 +00:00
|
|
|
}
|
|
|
|
|
2019-05-07 12:47:18 +00:00
|
|
|
if (path == XR_NULL_PATH) {
|
2020-10-23 12:39:59 +00:00
|
|
|
subaction_paths.any = true;
|
2020-07-20 19:53:52 +00:00
|
|
|
}
|
|
|
|
OXR_FOR_EACH_SUBACTION_PATH(GET_PATH) else
|
|
|
|
{
|
2019-09-29 10:43:45 +00:00
|
|
|
const char *str = NULL;
|
2019-05-07 12:47:18 +00:00
|
|
|
size_t length = 0;
|
|
|
|
|
|
|
|
oxr_path_get_string(log, inst, path, &str, &length);
|
|
|
|
return oxr_error(log, XR_ERROR_PATH_INVALID,
|
|
|
|
"(%s == '%s') path is not "
|
|
|
|
"a valid subaction path.",
|
|
|
|
variable, str);
|
|
|
|
}
|
2020-07-20 19:53:52 +00:00
|
|
|
#undef GET_PATH
|
|
|
|
|
|
|
|
bool fail = false;
|
2021-01-14 14:13:48 +00:00
|
|
|
#define CHECK_CREATION_TIME(X) \
|
2020-10-23 12:39:59 +00:00
|
|
|
if (subaction_paths.X && !act_subaction_paths->X) { \
|
2021-01-14 14:13:48 +00:00
|
|
|
fail = true; \
|
2020-07-20 19:53:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
OXR_FOR_EACH_SUBACTION_PATH(CHECK_CREATION_TIME);
|
|
|
|
#undef CHECK_CREATION_TIME
|
2019-05-07 12:47:18 +00:00
|
|
|
|
2020-07-20 19:53:52 +00:00
|
|
|
if (fail) {
|
2019-09-29 10:43:45 +00:00
|
|
|
const char *str = NULL;
|
2019-05-07 12:47:18 +00:00
|
|
|
size_t length = 0;
|
|
|
|
|
|
|
|
oxr_path_get_string(log, inst, path, &str, &length);
|
|
|
|
|
2020-05-30 19:08:52 +00:00
|
|
|
return oxr_error(log, XR_ERROR_PATH_UNSUPPORTED,
|
2019-05-07 12:47:18 +00:00
|
|
|
"(%s == '%s') the subaction path was "
|
|
|
|
"not specified at action creation",
|
|
|
|
variable, str);
|
|
|
|
}
|
|
|
|
|
2020-10-23 12:39:59 +00:00
|
|
|
*out_subaction_paths = subaction_paths;
|
2019-05-07 12:47:18 +00:00
|
|
|
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-03-18 05:52:32 +00:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Other verification.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2022-01-04 18:51:57 +00:00
|
|
|
XrResult
|
|
|
|
oxr_verify_extensions(struct oxr_logger *log, const struct oxr_extension_status *extensions)
|
|
|
|
{
|
2022-03-30 14:20:26 +00:00
|
|
|
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
2022-01-04 18:51:57 +00:00
|
|
|
if ((extensions->KHR_swapchain_usage_input_attachment_bit ||
|
|
|
|
extensions->MND_swapchain_usage_input_attachment_bit) &&
|
|
|
|
!extensions->KHR_vulkan_enable2 && !extensions->KHR_vulkan_enable) {
|
|
|
|
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE,
|
|
|
|
"Using [KHR|MND]_swapchain_usage_input_attachment_bit doesn't make sense without "
|
|
|
|
"KHR_vulkan_enable[2].");
|
|
|
|
}
|
2022-03-30 14:20:26 +00:00
|
|
|
#endif
|
2022-01-04 18:51:57 +00:00
|
|
|
|
2022-01-04 22:47:44 +00:00
|
|
|
if (extensions->EXT_dpad_binding && !extensions->KHR_binding_modification) {
|
|
|
|
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE,
|
|
|
|
"XR_EXT_dpad_binding requires XR_KHR_binding_modification");
|
|
|
|
}
|
|
|
|
|
2022-01-04 18:51:57 +00:00
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-06-04 14:01:57 +00:00
|
|
|
XrResult
|
|
|
|
oxr_verify_view_config_type(struct oxr_logger *log,
|
|
|
|
struct oxr_instance *inst,
|
|
|
|
XrViewConfigurationType view_conf,
|
|
|
|
const char *view_conf_name)
|
|
|
|
{
|
|
|
|
// These are always valid.
|
|
|
|
if (view_conf == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO ||
|
|
|
|
view_conf == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO) {
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "(%s == 0x%08x) invalid view configuration type",
|
2020-06-04 14:01:57 +00:00
|
|
|
view_conf_name, view_conf);
|
|
|
|
}
|
|
|
|
|
2019-10-08 14:40:40 +00:00
|
|
|
XrResult
|
2019-09-29 10:43:45 +00:00
|
|
|
oxr_verify_XrSessionCreateInfo(struct oxr_logger *log,
|
|
|
|
const struct oxr_instance *inst,
|
|
|
|
const XrSessionCreateInfo *createInfo)
|
2019-03-18 05:52:32 +00:00
|
|
|
{
|
|
|
|
if (createInfo->type != XR_TYPE_SESSION_CREATE_INFO) {
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "(createInfo->type)");
|
2019-03-18 05:52:32 +00:00
|
|
|
}
|
|
|
|
|
2019-08-14 22:14:59 +00:00
|
|
|
if (createInfo->createFlags != 0) {
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "Non-zero session create flags");
|
2019-08-14 22:14:59 +00:00
|
|
|
}
|
|
|
|
|
2019-06-05 19:21:25 +00:00
|
|
|
XrResult result = oxr_system_verify_id(log, inst, createInfo->systemId);
|
|
|
|
if (result != XR_SUCCESS) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2019-08-19 17:37:50 +00:00
|
|
|
#if defined(OXR_HAVE_KHR_opengl_enable) && defined(XR_USE_PLATFORM_XLIB)
|
2021-01-14 14:13:48 +00:00
|
|
|
XrGraphicsBindingOpenGLXlibKHR const *opengl_xlib = OXR_GET_INPUT_FROM_CHAIN(
|
|
|
|
createInfo, XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR, XrGraphicsBindingOpenGLXlibKHR);
|
2019-06-03 19:13:05 +00:00
|
|
|
if (opengl_xlib != NULL) {
|
2019-08-19 17:37:50 +00:00
|
|
|
OXR_VERIFY_EXTENSION(log, inst, KHR_opengl_enable);
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_verify_XrGraphicsBindingOpenGLXlibKHR(log, opengl_xlib);
|
2019-06-03 19:13:05 +00:00
|
|
|
}
|
2019-08-19 17:37:50 +00:00
|
|
|
#endif // defined(OXR_HAVE_KHR_opengl_enable) && defined(XR_USE_PLATFORM_XLIB)
|
2019-06-03 19:13:05 +00:00
|
|
|
|
2021-01-04 15:44:50 +00:00
|
|
|
#if defined(OXR_HAVE_KHR_vulkan_enable) || defined(OXR_HAVE_KHR_vulkan_enable2)
|
|
|
|
/* XR_TYPE_GRAPHICS_BINDING_VULKAN2_KHR aliased to
|
|
|
|
* XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR */
|
2021-01-14 14:13:48 +00:00
|
|
|
XrGraphicsBindingVulkanKHR const *vulkan =
|
|
|
|
OXR_GET_INPUT_FROM_CHAIN(createInfo, XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR, XrGraphicsBindingVulkanKHR);
|
2019-06-03 19:13:05 +00:00
|
|
|
if (vulkan != NULL) {
|
2021-01-14 14:13:48 +00:00
|
|
|
OXR_VERIFY_EXTENSIONS_OR(log, inst, KHR_vulkan_enable, KHR_vulkan_enable2);
|
2019-06-03 19:13:05 +00:00
|
|
|
return oxr_verify_XrGraphicsBindingVulkanKHR(log, vulkan);
|
|
|
|
}
|
2021-01-04 15:44:50 +00:00
|
|
|
#endif // defined(OXR_HAVE_KHR_vulkan_enable) ||
|
|
|
|
// defined(OXR_HAVE_KHR_vulkan_enable2)
|
2019-06-03 19:13:05 +00:00
|
|
|
|
2020-05-21 10:20:32 +00:00
|
|
|
#if defined(OXR_HAVE_MNDX_egl_enable) && defined(XR_USE_PLATFORM_EGL)
|
2021-01-14 14:13:48 +00:00
|
|
|
XrGraphicsBindingEGLMNDX const *egl =
|
|
|
|
OXR_GET_INPUT_FROM_CHAIN(createInfo, XR_TYPE_GRAPHICS_BINDING_EGL_MNDX, XrGraphicsBindingEGLMNDX);
|
2019-10-29 16:11:48 +00:00
|
|
|
if (egl != NULL) {
|
2020-05-21 10:20:32 +00:00
|
|
|
OXR_VERIFY_EXTENSION(log, inst, MNDX_egl_enable);
|
2020-05-20 15:55:07 +00:00
|
|
|
return oxr_verify_XrGraphicsBindingEGLMNDX(log, egl);
|
2019-10-29 16:11:48 +00:00
|
|
|
}
|
2020-05-21 10:20:32 +00:00
|
|
|
#endif // defined(OXR_HAVE_MNDX_egl_enable) && defined(XR_USE_PLATFORM_EGL_KHR)
|
2019-10-29 16:11:48 +00:00
|
|
|
|
2020-10-08 13:48:53 +00:00
|
|
|
#if defined(XR_USE_PLATFORM_ANDROID) && defined(XR_USE_GRAPHICS_API_OPENGL_ES)
|
2021-01-14 14:13:48 +00:00
|
|
|
XrGraphicsBindingOpenGLESAndroidKHR const *opengles_android = OXR_GET_INPUT_FROM_CHAIN(
|
|
|
|
createInfo, XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR, XrGraphicsBindingOpenGLESAndroidKHR);
|
2020-10-08 13:48:53 +00:00
|
|
|
if (opengles_android != NULL) {
|
|
|
|
OXR_VERIFY_EXTENSION(log, inst, KHR_opengl_es_enable);
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_verify_XrGraphicsBindingOpenGLESAndroidKHR(log, opengles_android);
|
2020-10-08 13:48:53 +00:00
|
|
|
}
|
2021-10-21 18:45:39 +00:00
|
|
|
#endif // defined(XR_USE_PLATFORM_ANDROID) && defined(XR_USE_GRAPHICS_API_OPENGL_ES)
|
2020-10-08 13:48:53 +00:00
|
|
|
|
2022-05-16 15:44:47 +00:00
|
|
|
#if defined(XR_USE_GRAPHICS_API_D3D11)
|
|
|
|
XrGraphicsBindingD3D11KHR const *d3d11 =
|
|
|
|
OXR_GET_INPUT_FROM_CHAIN(createInfo, XR_TYPE_GRAPHICS_BINDING_D3D11_KHR, XrGraphicsBindingD3D11KHR);
|
|
|
|
if (d3d11 != NULL) {
|
|
|
|
OXR_VERIFY_EXTENSION(log, inst, KHR_D3D11_enable);
|
|
|
|
return oxr_verify_XrGraphicsBindingD3D11KHR(log, d3d11);
|
|
|
|
}
|
|
|
|
#endif // XR_USE_GRAPHICS_API_D3D11
|
|
|
|
|
2019-06-03 19:13:05 +00:00
|
|
|
/*
|
|
|
|
* Add any new graphics binding structs here - before the headless
|
|
|
|
* check. (order for non-headless checks not specified in standard.)
|
|
|
|
* Add a new verify function below.
|
|
|
|
* Any new addition will also need to be added to
|
|
|
|
* oxr_session_create_impl.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* We didn't recognize any graphics binding structs in the chain - our
|
|
|
|
* last hope is headless. */
|
|
|
|
|
2019-08-19 17:37:50 +00:00
|
|
|
if (inst->extensions.MND_headless) {
|
2019-06-03 19:13:05 +00:00
|
|
|
return XR_SUCCESS;
|
2019-03-18 05:52:32 +00:00
|
|
|
}
|
|
|
|
|
2019-06-03 22:42:03 +00:00
|
|
|
return oxr_error(log, XR_ERROR_GRAPHICS_DEVICE_INVALID,
|
|
|
|
"(createInfo->next) Argument chain does not contain "
|
|
|
|
"any known graphics bindings");
|
2019-03-18 05:52:32 +00:00
|
|
|
}
|
|
|
|
|
2019-03-25 01:18:17 +00:00
|
|
|
|
2019-12-03 19:08:10 +00:00
|
|
|
#if defined(XR_USE_PLATFORM_XLIB) && defined(XR_USE_GRAPHICS_API_OPENGL)
|
2019-03-25 01:18:17 +00:00
|
|
|
|
2019-10-08 14:40:40 +00:00
|
|
|
XrResult
|
2021-01-14 14:13:48 +00:00
|
|
|
oxr_verify_XrGraphicsBindingOpenGLXlibKHR(struct oxr_logger *log, const XrGraphicsBindingOpenGLXlibKHR *next)
|
2019-03-18 05:52:32 +00:00
|
|
|
{
|
|
|
|
if (next->type != XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR) {
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "Graphics binding has invalid type");
|
2019-11-08 15:07:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (next->xDisplay == NULL) {
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "xDisplay is NULL");
|
2019-03-18 05:52:32 +00:00
|
|
|
}
|
|
|
|
|
2019-11-08 15:07:10 +00:00
|
|
|
if (next->glxContext == NULL) {
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "glxContext is NULL");
|
2019-11-08 15:07:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (next->glxDrawable == NULL) {
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "glxDrawable is NULL");
|
2019-11-08 15:07:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-03-18 05:52:32 +00:00
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
2019-03-25 01:18:17 +00:00
|
|
|
|
2019-12-03 19:08:10 +00:00
|
|
|
#endif // defined(XR_USE_PLATFORM_XLIB) && defined(XR_USE_GRAPHICS_API_OPENGL)
|
2019-03-18 05:52:32 +00:00
|
|
|
|
2019-03-25 01:18:17 +00:00
|
|
|
|
2019-03-18 05:52:32 +00:00
|
|
|
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
2019-03-25 01:18:17 +00:00
|
|
|
|
2019-10-08 14:40:40 +00:00
|
|
|
XrResult
|
2021-01-14 14:13:48 +00:00
|
|
|
oxr_verify_XrGraphicsBindingVulkanKHR(struct oxr_logger *log, const XrGraphicsBindingVulkanKHR *next)
|
2019-03-18 05:52:32 +00:00
|
|
|
{
|
2021-01-04 15:44:50 +00:00
|
|
|
/* XR_TYPE_GRAPHICS_BINDING_VULKAN2_KHR aliased to
|
|
|
|
* XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR */
|
2019-03-18 05:52:32 +00:00
|
|
|
if (next->type != XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR) {
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "Graphics binding has invalid type");
|
2019-03-18 05:52:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
2019-03-25 01:18:17 +00:00
|
|
|
|
2021-01-04 15:44:50 +00:00
|
|
|
#endif // XR_USE_GRAPHICS_API_VULKAN
|
2019-10-29 16:11:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
#ifdef XR_USE_PLATFORM_EGL
|
|
|
|
|
|
|
|
XrResult
|
2021-01-14 14:13:48 +00:00
|
|
|
oxr_verify_XrGraphicsBindingEGLMNDX(struct oxr_logger *log, const XrGraphicsBindingEGLMNDX *next)
|
2019-10-29 16:11:48 +00:00
|
|
|
{
|
2020-10-25 01:35:22 +00:00
|
|
|
// Here for internal error checking
|
2020-05-20 15:55:07 +00:00
|
|
|
if (next->type != XR_TYPE_GRAPHICS_BINDING_EGL_MNDX) {
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, "XrGraphicsBindingEGLMNDX::type is invalid '%i'",
|
|
|
|
next->type);
|
2020-10-25 01:35:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (next->getProcAddress == NULL) {
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE,
|
|
|
|
"XrGraphicsBindingEGLMNDX::getProcAddress cannot be NULL");
|
2020-10-25 01:35:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (next->display == NULL) {
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "XrGraphicsBindingEGLMNDX::display cannot be NULL");
|
2020-10-25 01:35:22 +00:00
|
|
|
}
|
|
|
|
|
2021-03-03 17:27:42 +00:00
|
|
|
// The next->config field can be NULL if EGL_KHR_no_config_context is supported by the display.
|
2020-10-25 01:35:22 +00:00
|
|
|
|
|
|
|
if (next->context == NULL) {
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "XrGraphicsBindingEGLMNDX::context cannot be NULL");
|
2019-10-29 16:11:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
2020-10-08 13:48:53 +00:00
|
|
|
|
|
|
|
#if defined(XR_USE_PLATFORM_ANDROID) && defined(XR_USE_GRAPHICS_API_OPENGL_ES)
|
|
|
|
XrResult
|
2021-01-14 14:13:48 +00:00
|
|
|
oxr_verify_XrGraphicsBindingOpenGLESAndroidKHR(struct oxr_logger *log, const XrGraphicsBindingOpenGLESAndroidKHR *next)
|
2020-10-08 13:48:53 +00:00
|
|
|
{
|
|
|
|
if (next->type != XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR) {
|
2021-01-14 14:13:48 +00:00
|
|
|
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "Graphics binding has invalid type");
|
2020-10-08 13:48:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
#endif // defined(XR_USE_PLATFORM_ANDROID) &&
|
|
|
|
// defined(XR_USE_GRAPHICS_API_OPENGL_ES)
|
2022-05-16 15:44:47 +00:00
|
|
|
|
|
|
|
#if defined(XR_USE_GRAPHICS_API_D3D11)
|
|
|
|
XrResult
|
|
|
|
oxr_verify_XrGraphicsBindingD3D11KHR(struct oxr_logger *log, const XrGraphicsBindingD3D11KHR *next)
|
|
|
|
{
|
|
|
|
if (next->type != XR_TYPE_GRAPHICS_BINDING_D3D11_KHR) {
|
|
|
|
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "Graphics binding has invalid type");
|
|
|
|
}
|
|
|
|
if (next->device == NULL) {
|
2022-05-25 14:49:20 +00:00
|
|
|
return oxr_error(log, XR_ERROR_GRAPHICS_DEVICE_INVALID,
|
|
|
|
"XrGraphicsBindingD3D11KHR::device cannot be NULL");
|
2022-05-16 15:44:47 +00:00
|
|
|
}
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
#endif // defined(XR_USE_GRAPHICS_API_D3D11)
|