nuclear@0: /************************************************************************************ nuclear@0: nuclear@0: Filename : CAPI_HSWDisplay.h nuclear@0: Content : Implements Health and Safety Warning system. nuclear@0: Created : July 3, 2014 nuclear@0: Authors : Paul Pedriana nuclear@0: nuclear@0: Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. nuclear@0: nuclear@0: Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); nuclear@0: you may not use the Oculus VR Rift SDK except in compliance with the License, nuclear@0: which is provided at the time of installation or download, or which nuclear@0: otherwise accompanies this software in either electronic or hard copy form. nuclear@0: nuclear@0: You may obtain a copy of the License at nuclear@0: nuclear@0: http://www.oculusvr.com/licenses/LICENSE-3.2 nuclear@0: nuclear@0: Unless required by applicable law or agreed to in writing, the Oculus VR SDK nuclear@0: distributed under the License is distributed on an "AS IS" BASIS, nuclear@0: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. nuclear@0: See the License for the specific language governing permissions and nuclear@0: limitations under the License. nuclear@0: nuclear@0: ************************************************************************************/ nuclear@0: nuclear@0: #ifndef OVR_CAPI_HSWDisplay_h nuclear@0: #define OVR_CAPI_HSWDisplay_h nuclear@0: nuclear@0: #include "../OVR_CAPI.h" nuclear@0: #include "CAPI_HMDRenderState.h" nuclear@0: #include nuclear@0: nuclear@0: nuclear@0: nuclear@0: //------------------------------------------------------------------------------------- nuclear@0: // ***** HSWDISPLAY_LOG nuclear@0: // nuclear@0: // Debug log wrapper. nuclear@0: nuclear@0: #if !defined(HSWDISPLAY_LOG_ENABLED) nuclear@0: #ifdef OVR_BUILD_DEBUG nuclear@0: #define HSWDISPLAY_LOG_ENABLED 1 nuclear@0: #else nuclear@0: #define HSWDISPLAY_LOG_ENABLED 0 nuclear@0: #endif nuclear@0: #endif nuclear@0: nuclear@0: #if HSWDISPLAY_LOG_ENABLED nuclear@0: #define HSWDISPLAY_LOG(...) OVR_DEBUG_LOG(__VA_ARGS__) nuclear@0: #else nuclear@0: #define HSWDISPLAY_LOG(...) nuclear@0: #endif nuclear@0: nuclear@0: nuclear@0: //------------------------------------------------------------------------------------- nuclear@0: // ***** HSWDISPLAY_DISTANCE nuclear@0: // nuclear@0: // Floating point value in the range of ~0.75 to ~3.0 which controls the distance nuclear@0: // (in meters) of the display from the viewer. nuclear@0: nuclear@0: #ifndef HSWDISPLAY_DISTANCE nuclear@0: #define HSWDISPLAY_DISTANCE 1.5f nuclear@0: #endif nuclear@0: nuclear@0: nuclear@0: //------------------------------------------------------------------------------------- nuclear@0: // ***** HSWDISPLAY_SCALE nuclear@0: // nuclear@0: // Floating point value in the range of ~0.1 to ~2.0 which controls the size scale of the nuclear@0: // SDK-rendered HSW display. The value is an arbitrary relative value, though this may nuclear@0: // change in future SDK versions. nuclear@0: nuclear@0: #ifndef HSWDISPLAY_SCALE nuclear@0: #define HSWDISPLAY_SCALE 0.92f nuclear@0: #endif nuclear@0: nuclear@0: nuclear@0: nuclear@0: nuclear@0: //------------------------------------------------------------------------------------- nuclear@0: // ***** Experimental C API functions nuclear@0: // nuclear@0: // These are currently not formally supported and may be promoted to the formal C API nuclear@0: // or may be removed in the future. nuclear@0: nuclear@0: extern "C" nuclear@0: { nuclear@0: // Normally if an application uses SDK-based distortion rendering nuclear@0: // (ovrHmd_BeginFrame / ovrHmd_EndFrame) then the SDK also takes care of nuclear@0: // drawing the health and safety warning. If an application is using nuclear@0: // SDK-based rendering but wants to draw the warning display itself, nuclear@0: // it call this function with enabled set to false. nuclear@0: OVR_EXPORT void ovrhmd_EnableHSWDisplaySDKRender(ovrHmd hmd, ovrBool enabled); nuclear@0: } nuclear@0: nuclear@0: nuclear@0: namespace OVR { namespace CAPI { nuclear@0: nuclear@0: nuclear@0: //------------------------------------------------------------------------------------- nuclear@0: // ***** CAPI::HSWDisplay nuclear@0: // nuclear@0: // Note: This will be renamed to HSWDisplay in the future. nuclear@0: // nuclear@0: // Implements the logic for the Health and Safety (HAS) warning display. Primarily this nuclear@0: // is two things: providing information about whether the warning needs to be currently nuclear@0: // displayed, and implementing the display itself. nuclear@0: // nuclear@0: // An HSWDisplay is associated 1:1 with an HMD. There can be at most one HSWDisplay nuclear@0: // being displayed on an HMD at a time. If a warning needs to be displayed while an nuclear@0: // existing one is present, it replaces the existing one. nuclear@0: // nuclear@0: // Notes nuclear@0: // Warnings are displayed per HMD (head mounted display). nuclear@0: // The app can have multiple HMDs. nuclear@0: // There can be multiple users of a given HMD over time, with each identified by a different user profile. nuclear@0: // There can be multiple apps using HMDs. nuclear@0: // nuclear@0: // Shows upon first entering a VR application (or VR mode in an application) when in Event Mode (e.g. trade show). nuclear@0: // Shows upon each wearing of the HMD. nuclear@0: // If the user profile is switched while display is active, the display must restart. nuclear@0: // Doesn't show in app when app was started by a launcher app. nuclear@0: // nuclear@0: // First display ever (per profile): 15 seconds until the display can be dismissed. nuclear@0: // Subsequent displays: 6 seconds until the display can be dismissed. Per profile. nuclear@0: // Dismissing occurs via HMD tap, designated keypress, gaze detection on OK button for N seconds, nuclear@0: // and possibly via an input gesture in the future. nuclear@0: // nuclear@0: // If the warning fades out upon completion, the fade out should begin after the full display time has elapsed, nuclear@0: // but it needs to avoid interfering (e.g. obscuring) with the application. This likely means the application nuclear@0: // would need to put in a couple seconds delay to allow the fade to complete. nuclear@0: // Ideally we'd handle the case of a user switching HMDs and not needing to see the warning again. nuclear@0: nuclear@0: class HSWDisplay : public RefCountBase nuclear@0: { nuclear@0: public: nuclear@0: HSWDisplay(ovrRenderAPIType api, ovrHmd hmd, const HMDRenderState& renderState); nuclear@0: nuclear@0: virtual ~HSWDisplay(); nuclear@0: nuclear@0: // Must be called after construction and before use. nuclear@0: virtual bool Initialize(const ovrRenderAPIConfig*) nuclear@0: { return true; } nuclear@0: nuclear@0: // Must be called before destruction. nuclear@0: virtual void Shutdown() {} nuclear@0: nuclear@0: // Enables or disables the HSW display system. It may be disabled only for development uses. nuclear@0: // It is enabled by default. nuclear@0: void Enable(bool enable); nuclear@0: nuclear@0: // Enables or disables our internal rendering when Render is called. If set to false then the nuclear@0: // application is expected to implement drawing of the display when Displayed is true. nuclear@0: // It is enabled by default. nuclear@0: void EnableRender(bool enable); nuclear@0: nuclear@0: // Triggers a display of the HSW display for the associated HMD. Restarts the display if nuclear@0: // the warning is already being displayed. nuclear@0: void Display(); nuclear@0: nuclear@0: // This function should be called per HMD every frame in order to give this class processing time. nuclear@0: // Writes the new state to newHSWDisplayState if it's non-NULL. nuclear@0: // The graphicsContext argument indicates if the Tick is occurring within a graphics context and nuclear@0: // thus if graphics operations are allowed during the TickState call. nuclear@0: // Returns true if the new state results in a required warning display (ovrHSWDisplayState::Displayed became true). nuclear@0: bool TickState(ovrHSWDisplayState *newHSWDisplayState = NULL, bool graphicsContext = false); nuclear@0: nuclear@0: // Gets the current state of the HSW display. nuclear@0: // Corresponds to ovrhmd_GetHSWDisplayState. nuclear@0: void GetState(ovrHSWDisplayState *hasWarningState) const; nuclear@0: nuclear@0: // Removes the HSW display display if the minimum dismissal time has occurred. nuclear@0: // Returns true if the warning display could be dissmissed or was not displayed at the time of the call. nuclear@0: // Corresponds to ovrhmd_DismissHSWDisplay. nuclear@0: bool Dismiss(); nuclear@0: nuclear@0: // Returns true if the HMD appears to be currently mounted and in a state that a nuclear@0: // warning display would be viewable. nuclear@0: bool IsDisplayViewable() const; nuclear@0: nuclear@0: // Draws the warning to the eye texture(s). This must be done at the end of a nuclear@0: // frame but prior to executing the distortion rendering of the eye textures. nuclear@0: virtual void Render(ovrEyeType, const ovrTexture*); nuclear@0: nuclear@0: // Resets the current profile's HAS settings (e.g. to act as if the user has never seen the HSW display before). nuclear@0: void ResetProfileData(); nuclear@0: nuclear@0: // Returns the ovrRenderAPIType. This is essentially the same as RTTI, as it's indicating what subclass nuclear@0: // is being used for this. nuclear@0: ovrRenderAPIType GetRenderAPIType() const // e.g. ovrRenderAPI_D3D11 nuclear@0: { return RenderAPIType; } nuclear@0: nuclear@0: // Returns the required HSW display text for the current profile's locale. nuclear@0: // Useful for implementing custom warning displays. Returns the required strlen nuclear@0: // of the text, and thus success is indicated by a return value < strCapacity. nuclear@0: // size_t GetText(char *str, size_t strCapacity); nuclear@0: nuclear@0: // Creates and constructs an instance of an HSWDisplay subclass based on the API type. nuclear@0: static HSWDisplay* Factory(ovrRenderAPIType apiType, ovrHmd hmd, const HMDRenderState& renderState); nuclear@0: nuclear@0: private: nuclear@0: OVR_NON_COPYABLE(HSWDisplay) nuclear@0: nuclear@0: protected: nuclear@0: virtual void DisplayInternal() {} nuclear@0: virtual void DismissInternal() {} nuclear@0: virtual void RenderInternal(ovrEyeType, const ovrTexture*) {} nuclear@0: virtual void UnloadGraphics() {} nuclear@0: virtual void LoadGraphics() {} nuclear@0: nuclear@0: // Profile functionality nuclear@0: time_t GetCurrentProfileLastHSWTime() const; nuclear@0: void SetCurrentProfileLastHSWTime(time_t t); nuclear@0: nuclear@0: // Generates an appropriate stereo ortho projection matrix. nuclear@0: static void GetOrthoProjection(const HMDRenderState& RenderState, Matrix4f OrthoProjection[2]); nuclear@0: nuclear@0: // Returns the default HSW display texture data. nuclear@0: static const uint8_t* GetDefaultTexture(size_t& TextureSize); nuclear@0: nuclear@0: protected: nuclear@0: bool Enabled; // If true then the HSW display system is enabled. True by default. nuclear@0: bool Displayed; // If true then the warning is currently visible and the following variables have meaning. Else there is no warning being displayed for this application on the given HMD. nuclear@0: bool SDKRendered; // If true then the display is being rendered by the SDK as opposed to the application. nuclear@0: bool DismissRequested; // If true then the warning has been requested to be hidden. nuclear@0: bool RenderEnabled; // If true then we handle rendering when Render is called. Else we skip it and assume the application is otherwise handling it itself. nuclear@0: bool UnloadGraphicsRequested; // If true then an unload of graphics was requested. This acts as a message from the main thread to the drawing thread so that the unload happens in the expected thread. nuclear@0: double StartTime; // Absolute time when the warning was first displayed. See ovr_GetTimeInSeconds(). nuclear@0: double DismissibleTime; // Absolute time when the warning can be dismissed. nuclear@0: double LastPollTime; // Used to prevent us from polling the required display state every frame but rather more like every 200 milliseconds. nuclear@0: const ovrHmd HMD; // The HMDState this HSWDisplay instance corresponds to. nuclear@0: mutable bool HMDMounted; // True if the HMD was most recently found to be mounted. We need this in order to maintain HMDNewlyMounted. nuclear@0: mutable bool HMDNewlyMounted; // True if HMDMounted has transitioned from false to true. We need this in order to tell if the HMD was recently mounted so we can display the HSW display. nuclear@0: const ovrRenderAPIType RenderAPIType; // e.g. ovrRenderAPI_D3D11 nuclear@0: const HMDRenderState& RenderState; // Information about the rendering setup. nuclear@0: nuclear@0: // Settings cache nuclear@0: mutable String LastProfileName; nuclear@0: mutable int LastHSWTime; nuclear@0: nuclear@0: }; // class HSWDisplay nuclear@0: nuclear@0: nuclear@0: nuclear@0: }} // namespace OVR::CAPI nuclear@0: nuclear@0: nuclear@0: #endif // OVR_CAPI_HSWDisplay_h