aboutsummaryrefslogtreecommitdiffstats
path: root/LibOVR/Src/CAPI/CAPI_HMDState.h
diff options
context:
space:
mode:
Diffstat (limited to 'LibOVR/Src/CAPI/CAPI_HMDState.h')
-rw-r--r--LibOVR/Src/CAPI/CAPI_HMDState.h334
1 files changed, 334 insertions, 0 deletions
diff --git a/LibOVR/Src/CAPI/CAPI_HMDState.h b/LibOVR/Src/CAPI/CAPI_HMDState.h
new file mode 100644
index 0000000..d178042
--- /dev/null
+++ b/LibOVR/Src/CAPI/CAPI_HMDState.h
@@ -0,0 +1,334 @@
+/************************************************************************************
+
+Filename : CAPI_HMDState.h
+Content : State associated with a single HMD
+Created : January 24, 2014
+Authors : Michael Antonov
+
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
+which is provided at the time of installation or download, or which
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_CAPI_HMDState_h
+#define OVR_CAPI_HMDState_h
+
+#include "../Kernel/OVR_Math.h"
+#include "../Kernel/OVR_List.h"
+#include "../Kernel/OVR_Log.h"
+#include "../OVR_CAPI.h"
+#include "../OVR_SensorFusion.h"
+#include "../Util/Util_LatencyTest.h"
+#include "../Util/Util_LatencyTest2.h"
+
+#include "CAPI_FrameTimeManager.h"
+#include "CAPI_HMDRenderState.h"
+#include "CAPI_DistortionRenderer.h"
+
+// Define OVR_CAPI_VISIONSUPPORT to compile in vision support
+#ifdef OVR_CAPI_VISIONSUPPORT
+ #define OVR_CAPI_VISION_CODE(c) c
+ #include "../Vision/Vision_PoseTracker.h"
+#else
+ #define OVR_CAPI_VISION_CODE(c)
+#endif
+
+
+struct ovrHmdStruct { };
+
+namespace OVR { namespace CAPI {
+
+using namespace OVR::Util::Render;
+
+
+//-------------------------------------------------------------------------------------
+// ***** ThreadChecker
+
+// This helper class is used to verify that the API is used according to supported
+// thread safety constraints (is not re-entrant for this and related functions).
+class ThreadChecker
+{
+public:
+
+#ifndef OVR_BUILD_DEBUG
+
+ // In release build, thread checks are disabled.
+ ThreadChecker() { }
+ void Begin(const char* functionName) { OVR_UNUSED1(functionName); }
+ void End() { }
+
+ // Add thread-re-entrancy check for function scope
+ struct Scope
+ {
+ Scope(ThreadChecker*, const char *) { }
+ ~Scope() { }
+ };
+
+
+#else // OVR_BUILD_DEBUG
+ ThreadChecker() : pFunctionName(0), FirstThread(0)
+ { }
+
+ void Begin(const char* functionName)
+ {
+ if (!pFunctionName)
+ {
+ pFunctionName = functionName;
+ FirstThread = GetCurrentThreadId();
+ }
+ else
+ {
+ // pFunctionName may be not null here if function is called internally on the same thread.
+ OVR_ASSERT_LOG((FirstThread == GetCurrentThreadId()),
+ ("%s (threadId=%d) called at the same times as %s (threadId=%d)\n",
+ functionName, GetCurrentThreadId(), pFunctionName, FirstThread) );
+ }
+ }
+ void End()
+ {
+ pFunctionName = 0;
+ FirstThread = 0;
+ }
+
+ // Add thread-re-entrancy check for function scope.
+ struct Scope
+ {
+ Scope(ThreadChecker* threadChecker, const char *functionName) : pChecker(threadChecker)
+ { pChecker->Begin(functionName); }
+ ~Scope()
+ { pChecker->End(); }
+ private:
+ ThreadChecker* pChecker;
+ };
+
+private:
+ // If not 0, contains the name of the function that first entered the scope.
+ const char * pFunctionName;
+ ThreadId FirstThread;
+
+#endif // OVR_BUILD_DEBUG
+};
+
+
+//-------------------------------------------------------------------------------------
+// ***** HMDState
+
+// Describes a single HMD.
+class HMDState : public ListNode<HMDState>,
+ public ovrHmdStruct, public NewOverrideBase
+{
+public:
+
+ HMDState(HMDDevice* device);
+ HMDState(ovrHmdType hmdType);
+ virtual ~HMDState();
+
+
+ // *** Sensor Setup
+
+ bool StartSensor(unsigned supportedCaps, unsigned requiredCaps);
+ void StopSensor();
+ void ResetSensor();
+ ovrSensorState PredictedSensorState(double absTime);
+ bool GetSensorDesc(ovrSensorDesc* descOut);
+
+ bool ProcessLatencyTest(unsigned char rgbColorOut[3]);
+ void ProcessLatencyTest2(unsigned char rgbColorOut[3], double startTime);
+
+
+ // *** Rendering Setup
+
+ bool ConfigureRendering(ovrEyeRenderDesc eyeRenderDescOut[2],
+ const ovrEyeDesc eyeDescIn[2],
+ const ovrRenderAPIConfig* apiConfig,
+ unsigned hmdCaps,
+ unsigned distortionCaps);
+
+ ovrPosef BeginEyeRender(ovrEyeType eye);
+ void EndEyeRender(ovrEyeType eye, ovrPosef renderPose, ovrTexture* eyeTexture);
+
+
+ const char* GetLastError()
+ {
+ const char* p = pLastError;
+ pLastError = 0;
+ return p;
+ }
+
+ void NotifyAddDevice(DeviceType deviceType)
+ {
+ if (deviceType == Device_Sensor)
+ AddSensorCount++;
+ else if (deviceType == Device_LatencyTester)
+ {
+ AddLatencyTestCount++;
+ AddLatencyTestDisplayCount++;
+ }
+ }
+
+ bool checkCreateSensor();
+
+ void applyProfileToSensorFusion();
+
+ // INlines so that they can be easily compiled out.
+ // Does debug ASSERT checks for functions that require BeginFrame.
+ // Also verifies that we are on the right thread.
+ void checkBeginFrameScope(const char* functionName)
+ {
+ OVR_UNUSED1(functionName); // for Release build.
+ OVR_ASSERT_LOG(BeginFrameCalled == true,
+ ("%s called outside ovrHmd_BeginFrame."));
+ OVR_ASSERT_LOG(BeginFrameThreadId == OVR::GetCurrentThreadId(),
+ ("%s called on a different thread then ovrHmd_BeginFrame."));
+ }
+
+ void checkRenderingConfigured(const char* functionName)
+ {
+ OVR_UNUSED1(functionName); // for Release build.
+ OVR_ASSERT_LOG(RenderingConfigured == true,
+ ("%s called without ovrHmd_ConfigureRendering."));
+ }
+
+ void checkBeginFrameTimingScope(const char* functionName)
+ {
+ OVR_UNUSED1(functionName); // for Release build.
+ OVR_ASSERT_LOG(BeginFrameTimingCalled == true,
+ ("%s called outside ovrHmd_BeginFrameTiming."));
+ }
+
+
+ HMDState* getThis() { return this; }
+
+ void updateLowPersistenceMode(bool lowPersistence) const;
+ void updateLatencyTestForHmd(bool latencyTesting);
+
+ // Get properties by name.
+ float getFloatValue(const char* propertyName, float defaultVal);
+ bool setFloatValue(const char* propertyName, float value);
+ unsigned getFloatArray(const char* propertyName, float values[], unsigned arraySize);
+ bool setFloatArray(const char* propertyName, float values[], unsigned arraySize);
+ const char* getString(const char* propertyName, const char* defaultVal);
+public:
+
+ // Wrapper to support 'const'
+ struct HMDInfoWrapper
+ {
+ HMDInfoWrapper(ovrHmdType hmdType)
+ {
+ HmdTypeEnum t = HmdType_None;
+ if (hmdType == ovrHmd_DK1)
+ t = HmdType_DK1;
+ else if (hmdType == ovrHmd_CrystalCoveProto)
+ t = HmdType_CrystalCoveProto;
+ else if (hmdType == ovrHmd_DK2)
+ t = HmdType_DK2;
+ h = CreateDebugHMDInfo(t);
+ }
+ HMDInfoWrapper(HMDDevice* device) { if (device) device->GetDeviceInfo(&h); }
+ OVR::HMDInfo h;
+ };
+
+ // Note: pHMD can be null if we are representing a virtualized debug HMD.
+ Ptr<HMDDevice> pHMD;
+
+ // HMDInfo shouldn't change, as its string pointers are passed out.
+ const HMDInfoWrapper HMDInfoW;
+ const OVR::HMDInfo& HMDInfo;
+
+ const char* pLastError;
+
+
+ // *** Sensor
+
+ // Lock used to support thread-safe lifetime access to sensor.
+ Lock DevicesLock;
+
+ // Atomic integer used as a flag that we should check the sensor device.
+ AtomicInt<int> AddSensorCount;
+
+ // All of Sensor variables may be modified/used with DevicesLock, with exception that
+ // the {SensorStarted, SensorCreated} can be read outside the lock to see
+ // if device creation check is necessary.
+ // Whether we called StartSensor() and requested sensor caps.
+ volatile bool SensorStarted;
+ volatile bool SensorCreated;
+ // pSensor may still be null or non-running after start if it wasn't yet available
+ Ptr<SensorDevice> pSensor; // Head
+ unsigned SensorCaps;
+
+ // SensorFusion state may be accessible without a lock.
+ SensorFusion SFusion;
+
+
+ // Vision pose tracker is currently new-allocated
+ OVR_CAPI_VISION_CODE(
+ Vision::PoseTracker* pPoseTracker;
+ )
+
+ // Latency tester
+ Ptr<LatencyTestDevice> pLatencyTester;
+ Util::LatencyTest LatencyUtil;
+ AtomicInt<int> AddLatencyTestCount;
+
+ bool LatencyTestActive;
+ unsigned char LatencyTestDrawColor[3];
+
+ // Using latency tester as debug display
+ Ptr<LatencyTestDevice> pLatencyTesterDisplay;
+ AtomicInt<int> AddLatencyTestDisplayCount;
+ Util::LatencyTest2 LatencyUtil2;
+
+ bool LatencyTest2Active;
+ unsigned char LatencyTest2DrawColor[3];
+ //bool ReadbackColor;
+
+ // Rendering part
+ FrameTimeManager TimeManager;
+ HMDRenderState RenderState;
+ Ptr<DistortionRenderer> pRenderer;
+
+ // Last timing value reported by BeginFrame.
+ double LastFrameTimeSeconds;
+ // Last timing value reported by GetFrameTime. These are separate since the intended
+ // use is from different threads. TBD: Move to FrameTimeManager? Make atomic?
+ double LastGetFrameTimeSeconds;
+
+ // Last cached value returned by ovrHmd_GetString/ovrHmd_GetStringArray.
+ char LastGetStringValue[256];
+
+
+ // Debug flag set after ovrHmd_ConfigureRendering succeeds.
+ bool RenderingConfigured;
+ // Set after BeginFrame succeeds, and its corresponding thread id for debug checks.
+ bool BeginFrameCalled;
+ ThreadId BeginFrameThreadId;
+ // Graphics functions are not re-entrant from other threads.
+ ThreadChecker RenderAPIThreadChecker;
+ //
+ bool BeginFrameTimingCalled;
+
+ // Flags set when we've called BeginEyeRender on a given eye.
+ bool EyeRenderActive[2];
+};
+
+
+}} // namespace OVR::CAPI
+
+
+#endif // OVR_CAPI_HMDState_h
+
+