// -*-c++-*- // SPDX-License-Identifier: LGPL-2.1-only // Copyright (C) 2021 James Hogan #ifndef OSGXR_Settings #define OSGXR_Settings 1 #include #include #include #include namespace osgXR { /// Encapsulates osgXR / OpenXR settings data. class OSGXR_EXPORT Settings : public osg::Referenced { public: /* * Instance management. */ Settings(); virtual ~Settings(); /// Get the default/global instance of Settings. static Settings *instance(); /* * OpenXR application information. */ /** * Set the application's name and version to expose to OpenXR. * These will be used to create an OpenXR instance. * @param appName Name of the application. * @param appVersion 32-bit version number of the application. */ void setApp(const std::string &appName, uint32_t appVersion) { _appName = appName; _appVersion = appVersion; } /** * Set the application's name to expose to OpenXR. * This will be used to create an OpenXR instance. * @param appName Name of the application. */ void setAppName(const std::string &appName) { _appName = appName; } /// Get the application's name to expose to OpenXR. const std::string &getAppName() const { return _appName; } /** * Set the application's version to expose to OpenXR. * This will be used to create an OpenXR instance. * @param appVersion 32-bit version number of the application. */ void setAppVersion(uint32_t appVersion) { _appVersion = appVersion; } /// Get the application's 32-bit version number to expose to OpenXR. uint32_t getAppVersion() const { return _appVersion; } /* * osgXR configuration settings. */ /** * Set whether to try enabling OpenXR's validation layer. * This controls whether the OpenXR validation API layer (i.e. * XR_APILAYER_LUNARG_core_validation) will be enabled when creating an * OpenXR instance. * By default this is disabled. * @param validationLayer Whether to try enabling the validation layer. */ void setValidationLayer(bool validationLayer) { _validationLayer = validationLayer; } /// Get whether to try enabling OpenXR's validation layer. bool getValidationLayer() const { return _validationLayer; } /** * Set whether to enable submission of depth information to OpenXR. * This controls whether the OpenXR instance depth information extension * (i.e XR_KHR_composition_layer_depth) will be used to submit depth * information to OpenXR to allow improved reprojection. * This is currently disabled by default. * @param depthInfo Whether to enable submission of depth information. */ void setDepthInfo(bool depthInfo) { _depthInfo = depthInfo; } /// Get whether to enable submission of depth information to OpenXR. bool getDepthInfo() const { return _depthInfo; } /** * Set whether to create visibility masks. * This controls whether the OpenXR instance visibility mask extension * (i.e. XR_KHR_visibility_mask) will be used to create and update * visibility masks for each VR view in order to mask hidden fragments. * This is enabled by default. * @param visibilityMask Whether to create visibility masks. */ void setVisibilityMask(bool visibilityMask) { _visibilityMask = visibilityMask; } /// Get whether to create visibility masks. bool getVisibilityMask() const { return _visibilityMask; } /// OpenXR system orm factors. typedef enum FormFactor { /// A display mounted to the user's head. HEAD_MOUNTED_DISPLAY, /// A display held in the user's hands. HANDHELD_DISPLAY, } FormFactor; /** * Set which OpenXR form factor to use. * This controls which OpenXR form factor to try to use. The default is * HEAD_MOUNTED_DISPLAY. * @param formFactor Form factor to use. */ void setFormFactor(FormFactor formFactor) { _formFactor = formFactor; } /// Get which OpenXR form factor to use. FormFactor getFormFactor() const { return _formFactor; } /// Modes for blending layers onto the user's view of the real world. typedef enum BlendMode { // Matches XrEnvironmentBlendMode /// Display layers with no view of physical world behind. BLEND_MODE_OPAQUE = 1, /// Additively blend layers with view of physical world behind. BLEND_MODE_ADDITIVE = 2, /// Alpha blend layers with view of physical world behind. BLEND_MODE_ALPHA_BLEND = 3, } BlendMode; /** * Specify a preferred environment blend mode. * The chosen environment blend mode is allowed for use, and will be * chosen in preference to any other supported environment blend modes * specified by allowEnvBlendMode() if supported by OpenXR. * @param mode Environment blend mode to prefer. */ void preferEnvBlendMode(BlendMode mode) { uint32_t mask = (1u << (unsigned int)mode); _preferredEnvBlendModeMask |= mask; _allowedEnvBlendModeMask |= mask; } /** * Specify an allowed environment blend mode. * The chosen environment blend mode is allowed for use, and may be * chosen if supported by OpenXR when none of the preferred environment * blend modes specified by preferEnvBlendMode() are supported by * OpenXR. * @param mode Environment blend mode to prefer. */ void allowEnvBlendMode(BlendMode mode) { uint32_t mask = (1u << (unsigned int)mode); _allowedEnvBlendModeMask |= mask; } /// Get the bitmask of preferred environment blend modes. uint32_t getPreferredEnvBlendModeMask() const { return _preferredEnvBlendModeMask; } /// Set the bitmask of preferred environment blend modes. void setPreferredEnvBlendModeMask(uint32_t preferredEnvBlendModeMask) { _preferredEnvBlendModeMask = preferredEnvBlendModeMask; } /// Get the bitmask of allowed environment blend modes. uint32_t getAllowedEnvBlendModeMask() const { return _allowedEnvBlendModeMask; } /// Set the bitmask of allowed environment blend modes. void setAllowedEnvBlendModeMask(uint32_t allowedEnvBlendModeMask) { _allowedEnvBlendModeMask = allowedEnvBlendModeMask; } /// Techniques for rendering multiple views. typedef enum VRMode { /// Choose automatically. VRMODE_AUTOMATIC, /** Create a slave camera for each view. * Either separate swapchains, or single with multiple viewports. */ VRMODE_SLAVE_CAMERAS, /** Use the OSG SceneView stereo functionality. * No extra slave cameras. * Only supports SWAPCHAIN_SINGLE with stereo. */ VRMODE_SCENE_VIEW, } VRMode; /// Set the rendering technique to use. void setVRMode(VRMode mode) { _vrMode = mode; } /// Get the rendering technique to use. VRMode getVRMode() const { return _vrMode; } /// Techniques for managing swapchains. typedef enum SwapchainMode { /// Choose automatically. SWAPCHAIN_AUTOMATIC, /// Create a 2D swapchain per view. SWAPCHAIN_MULTIPLE, /** Create a single 2D swapchain with a viewport per view. * Stack them horizontally. */ SWAPCHAIN_SINGLE, } SwapchainMode; /// Set the swapchain management technique to use. void setSwapchainMode(SwapchainMode mode) { _swapchainMode = mode; } /// Get the swapchain management technique to use. SwapchainMode getSwapchainMode() const { return _swapchainMode; } /// RGB(A) / depth encodings. typedef enum Encoding { /** Discrete linear encoding of RGB(A). * The OpenXR runtime may perform its own conversion from RGB to * sRGB for display on HMD, so the app should ensure it leaves RGB * values linear to avoid an over-bright image. */ ENCODING_LINEAR = 0, /** Floating-point linear encoding of RGB(A). * The OpenXR runtime may perform its own conversion from RGB to * sRGB for display on HMD, so the app should ensure it leaves RGB * values linear to avoid an over-bright image. */ ENCODING_FLOAT = 1, /** Discrete non-linear sRGB encoding with linear (A). * Linear RGB values should be converted to sRGB, for example with * GL_FRAMEBUFFER_SRGB or via fragment shader code, as the OpenXR * runtime will treat them as non-linear. * Not applicable to depth/stencil swapchains. */ ENCODING_SRGB = 2, } Encoding; /** * Specify a preferred RGB(A) encoding. * The chosen RGB(A) encoding is allowed for use, and a format with this * encoding will be chosen in preference to other allowed encodings * specified by allowRGBEncoding() if possible. * @param encoding RGB(A) encoding to prefer. */ void preferRGBEncoding(Encoding encoding) { uint32_t mask = (1u << (unsigned int)encoding); _preferredRGBEncodingMask |= mask; _allowedRGBEncodingMask |= mask; } /** * Specify an allowed RGB(A) encoding. * The chosen RGB(A) encoding is allowed for use, and a format with this * encoding may be chosen when none of the preferred color encodings * specified by preferRGBEncoding() are useable. * @param encoding RGB(A) encoding to permit. */ void allowRGBEncoding(Encoding encoding) { uint32_t mask = (1u << (unsigned int)encoding); _allowedRGBEncodingMask |= mask; } /// Get the bitmask of preferred RGB(A) encodings. uint32_t getPreferredRGBEncodingMask() const { return _preferredRGBEncodingMask; } /// Set the bitmask of preferred RGB(A) encodings. void setPreferredRGBEncodingMask(uint32_t preferredRGBEncodingMask) { _preferredRGBEncodingMask = preferredRGBEncodingMask; } /// Get the bitmask of allowed RGB(A) encodings. uint32_t getAllowedRGBEncodingMask() const { return _allowedRGBEncodingMask; } /// Set the bitmask of allowed RGB(A) encodings. void setAllowedRGBEncodingMask(uint32_t allowedRGBEncodingMask) { _allowedRGBEncodingMask = allowedRGBEncodingMask; } /** * Specify a preferred depth encoding. * The chosen depth encoding is allowed for use, and a format with this * encoding will be chosen in preference to other allowed encodings * specified by allowDepthEncoding() if possible. * @param encoding Depth encoding to prefer. */ void preferDepthEncoding(Encoding encoding) { uint32_t mask = (1u << (unsigned int)encoding); _preferredDepthEncodingMask |= mask; _allowedDepthEncodingMask |= mask; } /** * Specify an allowed depth encoding. * The chosen depth encoding is allowed for use, and a format with this * encoding may be chosen when none of the preferred color encodings * specified by preferDepthEncoding() are useable. * @param encoding Depth encoding to permit. */ void allowDepthEncoding(Encoding encoding) { uint32_t mask = (1u << (unsigned int)encoding); _allowedDepthEncodingMask |= mask; } /// Get the bitmask of preferred depth encodings. uint32_t getPreferredDepthEncodingMask() const { return _preferredDepthEncodingMask; } /// Set the bitmask of preferred depth encodings. void setPreferredDepthEncodingMask(uint32_t preferredDepthEncodingMask) { _preferredDepthEncodingMask = preferredDepthEncodingMask; } /// Get the bitmask of allowed depth encodings. uint32_t getAllowedDepthEncodingMask() const { return _allowedDepthEncodingMask; } /// Set the bitmask of allowed depth encodings. void setAllowedDepthEncodingMask(uint32_t allowedDepthEncodingMask) { _allowedDepthEncodingMask = allowedDepthEncodingMask; } /** * Get number of desired bits for each RGB channel in RGB(A) swapchain. * This only applies to linear RGB formats, not sRGB formats. */ int getRGBBits() const { return _rgbBits; } /** * Set number of desired bits for each RGB channel in RGB(A) swapchain. * This only applies to linear RGB formats, not sRGB formats. */ void setRGBBits(int rgbBits = -1) { _rgbBits = rgbBits; } /// Get number of desired alpha bits in RGB(A) swapchain. int getAlphaBits() const { return _alphaBits; } /// Set the number of desired alpha bits in RGB(A) swapchain. void setAlphaBits(int alphaBits = -1) { _alphaBits = alphaBits; } /// Get number of desired depth bits in depth/stencil swapchain. int getDepthBits() const { return _depthBits; } /// Set the number of desired depth bits in depth/stencil swapchain. void setDepthBits(int depthBits = -1) { _depthBits = depthBits; } /// Get number of desired stencil bits in depth/stencil swapchain. int getStencilBits() const { return _stencilBits; } /// Set the number of desired stenil bits in depth/stencil swapchain. void setStencilBits(int stencilBits = -1) { _stencilBits = stencilBits; } /// Get mirror settings. MirrorSettings &getMirrorSettings() { return _mirrorSettings; } /// Get mirror settings. const MirrorSettings &getMirrorSettings() const { return _mirrorSettings; } /** * Set the number of virtual world units to fit per real world meter. * This controls the size of the user relative to the virtual world, by * scaling down the size of the world. * @param unitsPerMeter The number of units per real world meter. */ void setUnitsPerMeter(float unitsPerMeter) { _unitsPerMeter = unitsPerMeter; } /// Get the number of virtual world units to fit per real world meter. float getUnitsPerMeter() const { return _unitsPerMeter; } // Internal APIs typedef enum { DIFF_NONE = 0, DIFF_APP_INFO = (1u << 0), DIFF_VALIDATION_LAYER = (1u << 1), DIFF_DEPTH_INFO = (1u << 2), DIFF_VISIBILITY_MASK = (1u << 3), DIFF_FORM_FACTOR = (1u << 4), DIFF_BLEND_MODE = (1u << 5), DIFF_VR_MODE = (1u << 6), DIFF_SWAPCHAIN_MODE = (1u << 7), DIFF_RGB_ENCODING = (1u << 8), DIFF_DEPTH_ENCODING = (1u << 9), DIFF_RGB_BITS = (1u << 10), DIFF_ALPHA_BITS = (1u << 11), DIFF_DEPTH_BITS = (1u << 12), DIFF_STENCIL_BITS = (1u << 13), DIFF_MIRROR = (1u << 14), DIFF_SCALE = (1u << 15), } _ChangeMask; unsigned int _diff(const Settings &other) const; private: /* * Internal data. */ // For XrInstance creation std::string _appName; uint32_t _appVersion; bool _validationLayer; bool _depthInfo; bool _visibilityMask; // To get XrSystem FormFactor _formFactor; // For choosing environment blend mode uint32_t _preferredEnvBlendModeMask; uint32_t _allowedEnvBlendModeMask; // VR/swapchain modes to use VRMode _vrMode; SwapchainMode _swapchainMode; // Swapchain requirements uint32_t _preferredRGBEncodingMask; uint32_t _allowedRGBEncodingMask; uint32_t _preferredDepthEncodingMask; uint32_t _allowedDepthEncodingMask; // These default to -1: get bit depths from graphics window traits int _rgbBits; // for linear RGB formats, per channel int _alphaBits; int _depthBits; int _stencilBits; // Mirror settings MirrorSettings _mirrorSettings; // How big the world float _unitsPerMeter; }; } #endif