/******************************************************************************
 * File: OlderRuntimeCompatibility.h
 *
 * Copyright (c) Qualcomm Technologies, Inc.
 * All Rights Reserved
 * Confidential and Proprietary - Qualcomm Technologies, Inc.
 *
 ******************************************************************************/

#ifndef QCOM_OLDER_RUNTIME_COMPATIBILITY_H
#define QCOM_OLDER_RUNTIME_COMPATIBILITY_H

#include <openxr/openxr.h>

#ifdef __ANDROID__
#include <jni.h>
#endif

#if defined(__GNUC__) && __GNUC__ >= 4
#define ORC_EXPORT __attribute__((visibility("default")))
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
#define ORC_EXPORT __attribute__((visibility("default")))
#elif defined(_WIN32)
#define ORC_EXPORT __declspec(dllexport)
#else
#define ORC_EXPORT
#endif

typedef enum ORCResult {
    ORC_SUCCESS = 0,
    ORC_ERROR_RUNTIME_FAILURE = -1,
    ORC_ERROR_VALIDATION_FAILURE = -2,
    ORC_ERROR_UNINITIALIZED_SYSTEM = -3,
    ORC_ERROR_RUNTIME_TOO_OLD_FOR_APPLICATION = -4,
    ORC_ERROR_APPLICATION_TOO_OLD_FOR_RUNTIME = -5,
    ORC_RESULT_MAX_ENUM = 0x7FFFFFFF,
} ORCResult;

typedef struct ORCAppCompatibilityInfoOverrides {
    XrVersion minApiLevel;
    XrVersion targetApiLevel;
} ORCAppCompatibilityInfoOverrides;

#define ORC_OVERRIDE_API_LEVELS (1 << 0)
#define ORC_OVERRIDE_OAC_LIBRARY_PATH (1 << 1)

typedef struct ORCRuntimeCompatibilityInfoOverrides {
    int32_t validMembers;    // bitfield indicating which struct members are valid.
    XrVersion minApiLevel;
    XrVersion maxApiLevel;
    const char* olderAppCompabitilityLibraryPath;
} ORCRuntimeCompatibilityInfoOverrides;

typedef struct ORCInitInfo {
    void* applicationVM;
    void* applicationContext;
    const ORCAppCompatibilityInfoOverrides* appCompatibilityInfoOverrides;
    const ORCRuntimeCompatibilityInfoOverrides* runtimeCompatibilityInfoOverrides;
} ORCInitInfo;

typedef struct ORCHookInfo {
    PFN_xrGetInstanceProcAddr loaderGetInstanceProcAddr;
} ORCHookInfo;

#define ORC_INITIALIZE_COMPATIBILITY_SYSTEM_FN "orcInitializeCompatibilitySystem"
#define ORC_HOOK_COMPATIBILITY_SYSTEM_FN "orcHookCompatibilitySystem"
#define ORC_SHUTDOWN_COMPATIBILITY_SYSTEM_FN "orcShutdownCompatibilitySystem"

typedef ORCResult(XRAPI_PTR* PFN_orcInitializeCompatibilitySystem)(const ORCInitInfo* initInfo);
typedef ORCResult(XRAPI_PTR* PFN_orcHookCompatibilitySystem)(const ORCHookInfo* hookInfo, PFN_xrGetInstanceProcAddr* hookGetInstanceProcAddr);
typedef ORCResult(XRAPI_PTR* PFN_orcShutdownCompatibilitySystem)();

#ifdef __cplusplus
extern "C" {
#endif

ORC_EXPORT XRAPI_ATTR ORCResult XRAPI_CALL orcInitializeCompatibilitySystem(const ORCInitInfo* initInfo);
ORC_EXPORT XRAPI_ATTR ORCResult XRAPI_CALL orcHookCompatibilitySystem(const ORCHookInfo* hookInfo, PFN_xrGetInstanceProcAddr* hookGetInstanceProcAddr);
ORC_EXPORT XRAPI_ATTR ORCResult XRAPI_CALL orcShutdownCompatibilitySystem();

#ifdef __ANDROID__
JNIEXPORT jobject JNICALL Java_com_qualcomm_qti_openxr_compatibility_olderruntimecompatibility_OlderRuntimeCompatibility_orcInitializeCompatibilitySystem(JNIEnv* env_, jclass class_, jobject context_);
JNIEXPORT jobject JNICALL Java_com_qualcomm_qti_openxr_compatibility_olderruntimecompatibility_OlderRuntimeCompatibility_orcShutdownCompatibilitySystem(JNIEnv* env_, jclass class_);
#endif

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif    // QCOM_OLDER_RUNTIME_COMPATIBILITY_H
