aboutsummaryrefslogtreecommitdiffstats
path: root/LibOVR/Src/OVR_CAPI.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'LibOVR/Src/OVR_CAPI.cpp')
-rwxr-xr-x[-rw-r--r--]LibOVR/Src/OVR_CAPI.cpp1458
1 files changed, 792 insertions, 666 deletions
diff --git a/LibOVR/Src/OVR_CAPI.cpp b/LibOVR/Src/OVR_CAPI.cpp
index 6d8d711..c530f82 100644..100755
--- a/LibOVR/Src/OVR_CAPI.cpp
+++ b/LibOVR/Src/OVR_CAPI.cpp
@@ -25,69 +25,86 @@ limitations under the License.
************************************************************************************/
#include "OVR_CAPI.h"
+#include "OVR_Version.h"
+
+
#include "Kernel/OVR_Timer.h"
-#include "Kernel/OVR_Math.h"
#include "Kernel/OVR_System.h"
+#include "Kernel/OVR_DebugHelp.h"
+#include "Extras/OVR_Math.h"
#include "OVR_Stereo.h"
#include "OVR_Profile.h"
-#include "../Include/OVR_Version.h"
#include "CAPI/CAPI_HMDState.h"
-#include "CAPI/CAPI_FrameTimeManager.h"
+#include "Net/OVR_Session.h"
#include "Service/Service_NetClient.h"
-#ifdef OVR_SINGLE_PROCESS
+#ifdef OVR_PRIVATE_FILE
#include "Service/Service_NetServer.h"
#endif
+#include "Displays/OVR_Display.h"
+
#if !defined(HEADLESS_APP)
-#ifdef OVR_OS_WIN32
+#if defined(OVR_OS_WIN32)
#include "Displays/OVR_Win32_ShimFunctions.h"
+#include <VersionHelpers.h>
#endif
#endif /* !defined(HEADLESS_APP) */
+// Forward decl to keep the callback static
+
+// Note: Removed CaptureHmdDescTrace from non-Win32 due to build warning.
+#if !defined(OVR_OS_MAC) && !defined(OVR_OS_LINUX)
+static bool CaptureHmdDescTrace(const OVR::CAPI::HMDState *state);
+#endif
+#define TRACE_STATE_CAPTURE_FUNC OVR::CAPI::HMDState::EnumerateHMDStateList(CaptureHmdDescTrace)
+#include "Tracing/Tracing.h"
+
+#if !defined(OVR_OS_MAC) && !defined(OVR_OS_LINUX)
+// EnumerateHMDStateList callback for tracing state capture
+static bool CaptureHmdDescTrace(const OVR::CAPI::HMDState* state)
+{
+ TraceHmdDesc(*state->pHmdDesc);
+ OVR_UNUSED(state); // Avoid potential compiler warnings.
+ return true;
+}
+#endif
+
+// Produce an invalid tracking state that will not mess up the application too badly.
+static ovrTrackingState GetNullTrackingState()
+{
+ ovrTrackingState nullState = ovrTrackingState();
+ nullState.HeadPose.ThePose.Orientation.w = 1.f; // Provide valid quaternions for head pose.
+ return nullState;
+}
+
+// Produce a null frame timing structure that will not break the calling application.
+static ovrFrameTiming GetNullFrameTiming()
+{
+ ovrFrameTiming nullTiming = ovrFrameTiming();
+ nullTiming.DeltaSeconds = 0.013f; // Provide nominal value
+ return nullTiming;
+}
+
using namespace OVR;
using namespace OVR::Util::Render;
-using namespace OVR::Tracking;
+using namespace OVR::Vision;
//-------------------------------------------------------------------------------------
// Math
namespace OVR {
-// ***** FovPort
-
-// C-interop support: FovPort <-> ovrFovPort
-FovPort::FovPort(const ovrFovPort &src)
- : UpTan(src.UpTan), DownTan(src.DownTan), LeftTan(src.LeftTan), RightTan(src.RightTan)
-{ }
-
-FovPort::operator ovrFovPort () const
-{
- ovrFovPort result;
- result.LeftTan = LeftTan;
- result.RightTan = RightTan;
- result.UpTan = UpTan;
- result.DownTan = DownTan;
- return result;
-}
-
-// Converts Fov Tan angle units to [-1,1] render target NDC space
-Vector2f FovPort::TanAngleToRendertargetNDC(Vector2f const &tanEyeAngle)
-{
- ScaleAndOffset2D eyeToSourceNDC = CreateNDCScaleAndOffsetFromFov(*this);
- return tanEyeAngle * eyeToSourceNDC.Scale + eyeToSourceNDC.Offset;
-}
-
// ***** SensorDataType
SensorDataType::SensorDataType(const ovrSensorData& s)
{
- Acceleration = s.Accelerometer;
- RotationRate = s.Gyro;
- MagneticField = s.Magnetometer;
- Temperature = s.Temperature;
+ Acceleration = s.Accelerometer;
+ RotationRate = s.Gyro;
+ MagneticField = s.Magnetometer;
+ Temperature = s.Temperature;
AbsoluteTimeSeconds = s.TimeInSeconds;
}
@@ -95,39 +112,35 @@ SensorDataType::operator ovrSensorData () const
{
ovrSensorData result;
result.Accelerometer = Acceleration;
- result.Gyro = RotationRate;
- result.Magnetometer = MagneticField;
- result.Temperature = Temperature;
- result.TimeInSeconds = (float) AbsoluteTimeSeconds;
+ result.Gyro = RotationRate;
+ result.Magnetometer = MagneticField;
+ result.Temperature = Temperature;
+ result.TimeInSeconds = (float)AbsoluteTimeSeconds;
return result;
}
+
+
// ***** SensorState
TrackingState::TrackingState(const ovrTrackingState& s)
{
- HeadPose = s.HeadPose;
- CameraPose = s.CameraPose;
+ HeadPose = s.HeadPose;
+ CameraPose = s.CameraPose;
LeveledCameraPose = s.LeveledCameraPose;
- RawSensorData = s.RawSensorData;
- StatusFlags = s.StatusFlags;
- LastVisionProcessingTime = s.LastVisionProcessingTime;
- LastVisionFrameLatency = s.LastVisionFrameLatency;
- LastCameraFrameCounter = s.LastCameraFrameCounter;
+ RawSensorData = s.RawSensorData;
+ StatusFlags = s.StatusFlags;
}
TrackingState::operator ovrTrackingState() const
{
ovrTrackingState result;
- result.HeadPose = HeadPose;
- result.CameraPose = CameraPose;
+ result.HeadPose = HeadPose;
+ result.CameraPose = CameraPose;
result.LeveledCameraPose = LeveledCameraPose;
- result.RawSensorData = RawSensorData;
- result.StatusFlags = StatusFlags;
- result.LastVisionProcessingTime = LastVisionProcessingTime;
- result.LastVisionFrameLatency = LastVisionFrameLatency;
- result.LastCameraFrameCounter = LastCameraFrameCounter;
+ result.RawSensorData = RawSensorData;
+ result.StatusFlags = StatusFlags;
return result;
}
@@ -138,184 +151,212 @@ TrackingState::operator ovrTrackingState() const
using namespace OVR::CAPI;
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Used to generate projection from ovrEyeDesc::Fov
-OVR_EXPORT ovrMatrix4f ovrMatrix4f_Projection(ovrFovPort fov, float znear, float zfar, ovrBool rightHanded)
+// Helper function to validate the HMD object provided by the API user.
+static HMDState* GetHMDStateFromOvrHmd(ovrHmd hmddesc)
{
- return CreateProjection(rightHanded ? true : false, fov, znear, zfar);
+ if (!hmddesc || !hmddesc->Handle)
+ return nullptr;
+
+ return (HMDState*)hmddesc->Handle;
}
-OVR_EXPORT ovrMatrix4f ovrMatrix4f_OrthoSubProjection(ovrMatrix4f projection, ovrVector2f orthoScale,
- float orthoDistance, float hmdToEyeViewOffsetX)
+OVR_PUBLIC_FUNCTION(double) ovr_GetTimeInSeconds()
{
+ return Timer::GetSeconds();
+}
- float orthoHorizontalOffset = hmdToEyeViewOffsetX / orthoDistance;
-
- // Current projection maps real-world vector (x,y,1) to the RT.
- // We want to find the projection that maps the range [-FovPixels/2,FovPixels/2] to
- // the physical [-orthoHalfFov,orthoHalfFov]
- // Note moving the offset from M[0][2]+M[1][2] to M[0][3]+M[1][3] - this means
- // we don't have to feed in Z=1 all the time.
- // The horizontal offset math is a little hinky because the destination is
- // actually [-orthoHalfFov+orthoHorizontalOffset,orthoHalfFov+orthoHorizontalOffset]
- // So we need to first map [-FovPixels/2,FovPixels/2] to
- // [-orthoHalfFov+orthoHorizontalOffset,orthoHalfFov+orthoHorizontalOffset]:
- // x1 = x0 * orthoHalfFov/(FovPixels/2) + orthoHorizontalOffset;
- // = x0 * 2*orthoHalfFov/FovPixels + orthoHorizontalOffset;
- // But then we need the same mapping as the existing projection matrix, i.e.
- // x2 = x1 * Projection.M[0][0] + Projection.M[0][2];
- // = x0 * (2*orthoHalfFov/FovPixels + orthoHorizontalOffset) * Projection.M[0][0] + Projection.M[0][2];
- // = x0 * Projection.M[0][0]*2*orthoHalfFov/FovPixels +
- // orthoHorizontalOffset*Projection.M[0][0] + Projection.M[0][2];
- // So in the new projection matrix we need to scale by Projection.M[0][0]*2*orthoHalfFov/FovPixels and
- // offset by orthoHorizontalOffset*Projection.M[0][0] + Projection.M[0][2].
-
- Matrix4f ortho;
- ortho.M[0][0] = projection.M[0][0] * orthoScale.x;
- ortho.M[0][1] = 0.0f;
- ortho.M[0][2] = 0.0f;
- ortho.M[0][3] = -projection.M[0][2] + ( orthoHorizontalOffset * projection.M[0][0] );
-
- ortho.M[1][0] = 0.0f;
- ortho.M[1][1] = -projection.M[1][1] * orthoScale.y; // Note sign flip (text rendering uses Y=down).
- ortho.M[1][2] = 0.0f;
- ortho.M[1][3] = -projection.M[1][2];
-
- /*
- if ( fabsf ( zNear - zFar ) < 0.001f )
- {
- ortho.M[2][0] = 0.0f;
- ortho.M[2][1] = 0.0f;
- ortho.M[2][2] = 0.0f;
- ortho.M[2][3] = zFar;
- }
- else
- {
- ortho.M[2][0] = 0.0f;
- ortho.M[2][1] = 0.0f;
- ortho.M[2][2] = zFar / (zNear - zFar);
- ortho.M[2][3] = (zFar * zNear) / (zNear - zFar);
- }
- */
- // MA: Undo effect of sign
- ortho.M[2][0] = 0.0f;
- ortho.M[2][1] = 0.0f;
- //ortho.M[2][2] = projection.M[2][2] * projection.M[3][2] * -1.0f; // reverse right-handedness
- ortho.M[2][2] = 0.0f;
- ortho.M[2][3] = 0.0f;
- //projection.M[2][3];
+//-------------------------------------------------------------------------------------
- // No perspective correction for ortho.
- ortho.M[3][0] = 0.0f;
- ortho.M[3][1] = 0.0f;
- ortho.M[3][2] = 0.0f;
- ortho.M[3][3] = 1.0f;
+// 1. Init/shutdown.
- return ortho;
-}
+static ovrBool CAPI_ovrInitializeCalled = ovrFalse;
+static OVR::Service::NetClient* CAPI_pNetClient = nullptr;
-OVR_EXPORT double ovr_GetTimeInSeconds()
+#if !defined(HEADLESS_APP)
+ovrBool ovr_InitializeRenderingShim()
{
- return Timer::GetSeconds();
+ OVR::Display::Initialize();
+
+ return OVR::Display::GetDirectDisplayInitialized();
}
-// Waits until the specified absolute time.
-OVR_EXPORT double ovr_WaitTillTime(double absTime)
+OVR_PUBLIC_FUNCTION(ovrBool) ovr_InitializeRenderingShimVersion(int requestedMinorVersion)
{
- double initialTime = ovr_GetTimeInSeconds();
- double newTime = initialTime;
+ // We ignore the patch and build versions here, as they aren't relevant to compatibility.
+ // And we don't store them away here, as we do that in ovr_Initialize() instead.
- while(newTime < absTime)
+ if (requestedMinorVersion > OVR_MINOR_VERSION)
+ return ovrFalse;
+
+ return ovr_InitializeRenderingShim();
+}
+#endif /* !defined(HEADLESS_APP) */
+
+// Write out to the log where the current running module is located on disk.
+static void LogLocationOfThisModule()
+{
+#if defined (OVR_OS_WIN32)
+ // Log out the DLL file path on startup.
{
- for (int j = 0; j < 5; j++)
- OVR_PROCESSOR_PAUSE();
+ bool success = false;
+
+ HMODULE hModule = nullptr;
+ GetModuleHandleEx(
+ GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+ (LPCTSTR)&ovr_Initialize,
+ &hModule);
+ if (hModule)
+ {
+ wchar_t filename[_MAX_PATH];
+ DWORD len = GetModuleFileNameW(hModule, filename, OVR_ARRAY_COUNT(filename));
+ if (len > 0 && filename[0])
+ {
+ success = true;
+ LogText("[CAPI] LibOVR module is located at %ws\n", filename);
+ }
+ }
- newTime = ovr_GetTimeInSeconds();
+ if (!success)
+ {
+ LogError("[CAPI] WARNING: Unable to find LibOVR module.");
+ }
}
-
- // How long we waited
- return newTime - initialTime;
+#endif // OVR_OS_WIN32
}
+// These defaults are also in OVR_CAPIShim.c
+static const ovrInitParams DefaultParams = {
+ ovrInit_RequestVersion, // Flags
+ OVR_MINOR_VERSION, // RequestedMinorVersion
+ 0, // LogCallback
+ 0 // ConnectionTimeoutSeconds
+};
-//-------------------------------------------------------------------------------------
+// Precondition: params is not null
+OVR_PUBLIC_FUNCTION(ovrBool) ovr_Initialize(ovrInitParams const* params)
+{
+ // TBD: Should we check if the version requested changed and fail here?
+ if (CAPI_ovrInitializeCalled) // If already initialized...
+ return ovrTrue;
-// 1. Init/shutdown.
+ TraceInit();
+ TraceCall(0);
-static ovrBool CAPI_SystemInitCalled = 0;
-static ovrBool CAPI_ovrInitializeCalled = 0;
+ if (!params)
+ {
+ params = &DefaultParams;
+ }
-static OVR::Service::NetClient* CAPI_pNetClient = 0;
+ bool DebugMode = (params->Flags & ovrInit_Debug) != 0;
-#if !defined(HEADLESS_APP)
-OVR_EXPORT ovrBool ovr_InitializeRenderingShim()
-{
- OVR::System::DirectDisplayInitialize();
- return OVR::System::DirectDisplayEnabled();
-}
-#endif /* !defined(HEADLESS_APP) */
+#if defined(OVR_BUILD_DEBUG)
+ // If no debug setting is provided,
+ if (!(params->Flags & (ovrInit_Debug | ovrInit_ForceNoDebug)))
+ {
+ DebugMode = true;
+ }
+#endif
-OVR_EXPORT ovrBool ovr_Initialize()
-{
- if (CAPI_ovrInitializeCalled)
- return 1;
+ // We ignore the requested patch version and build version, as they are not currently relevant to
+ // the library compatibility. Our test for minor version compatibility is currently simple: we support
+ // only older or equal minor versions, and don't change our behavior if the requested minor version
+ // is older than than OVR_MINOR_VERSION.
- // We must set up the system for the plugin to work
- if (!OVR::System::IsInitialized())
+ if ((params->Flags & ovrInit_RequestVersion) != 0 &&
+ (params->RequestedMinorVersion > OVR_MINOR_VERSION))
{
- OVR::System::Init(OVR::Log::ConfigureDefaultLog(OVR::LogMask_All));
- CAPI_SystemInitCalled = 1;
+ goto Abort;
}
- if (!OVR::System::DirectDisplayEnabled() && !OVR::Display::InCompatibilityMode(false))
+#if defined(OVR_OS_WIN32)
+ // Older than Windows 7 SP1?
+ if (!IsWindows7SP1OrGreater())
{
+ MessageBoxA(nullptr, "This software depends on features available starting with \nWindows 7 Service Pack 1, and it cannot start.", "LibOVR: Cannot start", 0);
OVR_ASSERT(false);
- return 0;
+ goto Abort;
}
+#endif // OVR_OS_WIN32
- CAPI_pNetClient = NetClient::GetInstance();
+ OVR::Net::RuntimeSDKVersion.SetCurrent(); // Fill in the constant parts of this struct.
+ OVR::Net::RuntimeSDKVersion.RequestedMinorVersion = (uint16_t)params->RequestedMinorVersion;
-#ifdef OVR_SINGLE_PROCESS
+ // Initialize display subsystem regardless of Allocator initialization.
+ OVR::Display::Initialize();
- // If the server could not start running,
- if (Service::NetServer::GetInstance()->IsInitialized())
+ // We must set up the system for the plugin to work
+ if (!OVR::System::IsInitialized())
{
- CAPI_pNetClient->Connect(true);
+ // TBD: Base this on registry setting?
+ Allocator::SetLeakTracking(DebugMode);
+
+ OVR::Log* logger = OVR::Log::ConfigureDefaultLog(OVR::LogMask_All);
+
+ // Set the CAPI logger callback
+ logger->SetCAPICallback(params->LogCallback);
+
+ OVR::System::Init(logger);
}
- else
+
+ if (!OVR::Display::GetDirectDisplayInitialized() && !OVR::Display::InCompatibilityMode(true))
{
- // This normally will happen if the OVRService is running in the background,
- // or another SingleProcess-mode app is running in the background.
- // In this case, it's using the hardware and we should not also attempt to use
- // the hardware.
- LogError("{ERR-079} [LibOVR] Server is already running");
+ OVR_ASSERT(false);
+ goto Abort;
}
-#else
- CAPI_pNetClient->Connect(true);
-#endif
+ CAPI_pNetClient = NetClient::GetInstance();
+
+ // Store off the initialization parameters from ovr_Initialize()
+ CAPI_pNetClient->ApplyParameters(params);
+
+ // Mark as initialized regardless of whether or not we can connect to the server.
CAPI_ovrInitializeCalled = 1;
- return 1;
+ // Log the location of the module after most of the bring-up, as the game
+ // could do almost anything in response to a log message callback.
+ LogLocationOfThisModule();
+
+ // If unable to connect to server and we are not in a debug mode,
+ if (!CAPI_pNetClient->Connect(true) && !DebugMode)
+ {
+ // Then it's a failure when the server is unreachable.
+ // This means that a DebugHMD cannot be created unless the ovrInit_Debug flag is set.
+ goto Abort;
+ }
+
+ // everything is okay
+ TraceReturn(0);
+ return ovrTrue;
+
+Abort:
+ // clean up and return failure
+ TraceReturn(0);
+ TraceFini();
+ return ovrFalse;
}
-OVR_EXPORT void ovr_Shutdown()
+
+OVR_PUBLIC_FUNCTION(void) ovr_Shutdown()
{
- // We should clean up the system to be complete
- if (OVR::System::IsInitialized() && CAPI_SystemInitCalled)
+ if (CAPI_ovrInitializeCalled)
+ {
+ OVR::Display::Shutdown();
+ TraceCall(0);
+ TraceFini();
+ CAPI_ovrInitializeCalled = 0;
+ }
+
+ if (OVR::System::IsInitialized())
{
OVR::System::Destroy();
}
- CAPI_SystemInitCalled = 0;
- CAPI_ovrInitializeCalled = 0;
+ OVR::Net::RuntimeSDKVersion.Reset();
+ CAPI_pNetClient = nullptr; // Not strictly necessary, but useful for debugging and cleanliness.
}
@@ -328,10 +369,10 @@ OVR_EXPORT void ovr_Shutdown()
// probably check this.
//
-OVR_EXPORT int ovrHmd_Detect()
+OVR_PUBLIC_FUNCTION(int) ovrHmd_Detect()
{
if (!CAPI_ovrInitializeCalled)
- return 0;
+ return -2;
return CAPI_pNetClient->Hmd_Detect();
}
@@ -341,7 +382,7 @@ OVR_EXPORT int ovrHmd_Detect()
// a relatively light-weight handle that would reference the device going forward and would
// survive future ovrHmd_Detect calls. That is once ovrHMD is returned, index is no longer
// necessary and can be changed by a ovrHmd_Detect call.
-OVR_EXPORT ovrHmd ovrHmd_Create(int index)
+OVR_PUBLIC_FUNCTION(ovrHmd) ovrHmd_Create(int index)
{
if (!CAPI_ovrInitializeCalled)
return 0;
@@ -355,18 +396,35 @@ OVR_EXPORT ovrHmd ovrHmd_Create(int index)
while (!CAPI_pNetClient->Hmd_Create(index, &netInfo) ||
netInfo.NetId == InvalidVirtualHmdId)
{
- // If two seconds elapse and still no HMD detected,
- if (Timer::GetSeconds() - t0 > 2.)
+ double waitTime = 2.0; // Default wait time
+
+ if (NetClient::GetInstance()->IsConnected(false, false))
{
- if (!NetClient::GetInstance()->IsConnected(false, false))
+ NetClient::GetInstance()->SetLastError("No HMD Detected");
+
+ // If in single process mode,
+ if (Net::Session::IsSingleProcess())
{
- NetClient::GetInstance()->SetLastError("Not connected to service");
+ // Wait 8 seconds for HMD to be detected, as this is a single process
+ // build and we expect that the operator has the system set up properly.
+ waitTime = 8.0;
}
else
{
- NetClient::GetInstance()->SetLastError("No HMD Detected");
+ // Wait 1/2 second for HMD to be detected.
+ waitTime = 0.5;
}
+ }
+ else
+ {
+ NetClient::GetInstance()->SetLastError("Not connected to service");
+ // Wait the default amount of time for the service to start up.
+ }
+
+ // If two seconds elapse and still no HMD detected,
+ if (Timer::GetSeconds() - t0 > waitTime)
+ {
return 0;
}
}
@@ -384,25 +442,27 @@ OVR_EXPORT ovrHmd ovrHmd_Create(int index)
// Reset frame timing so that FrameTimeManager values are properly initialized in AppRendered mode.
ovrHmd_ResetFrameTiming(hmds->pHmdDesc, 0);
+ TraceHmdDesc(*hmds->pHmdDesc);
+
return hmds->pHmdDesc;
}
#if !defined(HEADLESS_APP)
-OVR_EXPORT ovrBool ovrHmd_AttachToWindow( ovrHmd hmd, void* window,
- const ovrRecti* destMirrorRect,
- const ovrRecti* sourceRenderTargetRect )
+OVR_PUBLIC_FUNCTION(ovrBool) ovrHmd_AttachToWindow(ovrHmd hmddesc, void* window,
+ const ovrRecti* destMirrorRect,
+ const ovrRecti* sourceRenderTargetRect)
{
- OVR_UNUSED( destMirrorRect );
- OVR_UNUSED( sourceRenderTargetRect );
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ return ovrFalse;
+
+ OVR_UNUSED3(destMirrorRect, sourceRenderTargetRect, hmds);
if (!CAPI_ovrInitializeCalled)
- return false;
+ return ovrFalse;
- if (!hmd || !hmd->Handle)
- return false;
#ifndef OVR_OS_MAC
- HMDState* hmds = (HMDState*)hmd->Handle;
CAPI_pNetClient->Hmd_AttachToWindow(hmds->GetNetId(), window);
hmds->pWindow = window;
#endif
@@ -413,29 +473,29 @@ OVR_EXPORT ovrBool ovrHmd_AttachToWindow( ovrHmd hmd, void* window,
OVR_UNUSED(window);
#endif
- return true;
+ return ovrTrue;
}
#endif /* !defined(HEADLESS_APP) */
-OVR_EXPORT ovrHmd ovrHmd_CreateDebug(ovrHmdType type)
+OVR_PUBLIC_FUNCTION(ovrHmd) ovrHmd_CreateDebug(ovrHmdType type)
{
if (!CAPI_ovrInitializeCalled)
return 0;
- HMDState* hmds = HMDState::CreateHMDState(type);
+ HMDState* hmds = HMDState::CreateDebugHMDState(type);
+ if (!hmds)
+ return nullptr;
return hmds->pHmdDesc;
}
-OVR_EXPORT void ovrHmd_Destroy(ovrHmd hmddesc)
+OVR_PUBLIC_FUNCTION(void) ovrHmd_Destroy(ovrHmd hmddesc)
{
- if (!hmddesc || !hmddesc->Handle)
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
return;
-
- // TBD: Any extra shutdown?
- HMDState* hmds = (HMDState*)hmddesc->Handle;
-
+
{ // Thread checker in its own scope, to avoid access after 'delete'.
// Essentially just checks that no other RenderAPI function is executing.
ThreadChecker::Scope checkScope(&hmds->RenderAPIThreadChecker, "ovrHmd_Destroy");
@@ -457,20 +517,16 @@ OVR_EXPORT void ovrHmd_Destroy(ovrHmd hmddesc)
}
-OVR_EXPORT const char* ovrHmd_GetLastError(ovrHmd hmddesc)
+OVR_PUBLIC_FUNCTION(const char*) ovrHmd_GetLastError(ovrHmd hmddesc)
{
if (!CAPI_ovrInitializeCalled)
- {
return "System initialize not called";
- }
VirtualHmdId netId = InvalidVirtualHmdId;
- if (hmddesc && hmddesc->Handle)
- {
- HMDState* p = (HMDState*)hmddesc->Handle;
- netId = p->GetNetId();
- }
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (hmds)
+ netId = hmds->GetNetId();
return CAPI_pNetClient->Hmd_GetLastError(netId);
}
@@ -479,7 +535,7 @@ OVR_EXPORT const char* ovrHmd_GetLastError(ovrHmd hmddesc)
// Returns version string representing libOVR version. Static, so
// string remains valid for app lifespan
-OVR_EXPORT const char* ovr_GetVersionString()
+OVR_PUBLIC_FUNCTION(const char*) ovr_GetVersionString()
{
static const char* version = OVR_VERSION_LIBOVR_PFX OVR_VERSION_STRING;
return version + sizeof(OVR_VERSION_LIBOVR_PFX) - 1;
@@ -492,21 +548,24 @@ OVR_EXPORT const char* ovr_GetVersionString()
// Returns capability bits that are enabled at this time; described by ovrHmdCapBits.
// Note that this value is different font ovrHmdDesc::Caps, which describes what
// capabilities are available.
-OVR_EXPORT unsigned int ovrHmd_GetEnabledCaps(ovrHmd hmddesc)
+OVR_PUBLIC_FUNCTION(unsigned int) ovrHmd_GetEnabledCaps(ovrHmd hmddesc)
{
- HMDState* p = (HMDState*)hmddesc->Handle;
- return p ? p->EnabledHmdCaps : 0;
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ return 0;
+
+ return hmds->EnabledHmdCaps;
}
// Modifies capability bits described by ovrHmdCapBits that can be modified,
// such as ovrHmdCap_LowPersistance.
-OVR_EXPORT void ovrHmd_SetEnabledCaps(ovrHmd hmddesc, unsigned int capsBits)
+OVR_PUBLIC_FUNCTION(void) ovrHmd_SetEnabledCaps(ovrHmd hmddesc, unsigned int capsBits)
{
- HMDState* p = (HMDState*)hmddesc->Handle;
- if (p)
- {
- p->SetEnabledHmdCaps(capsBits);
- }
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ return;
+
+ hmds->SetEnabledHmdCaps(capsBits);
}
@@ -525,64 +584,50 @@ OVR_EXPORT void ovrHmd_SetEnabledCaps(ovrHmd hmddesc, unsigned int capsBits)
// functions that have different rules (all frame access functions
// must be on render thread)
-OVR_EXPORT ovrBool ovrHmd_ConfigureTracking(ovrHmd hmddesc, unsigned int supportedCaps,
- unsigned int requiredCaps)
+OVR_PUBLIC_FUNCTION(ovrBool) ovrHmd_ConfigureTracking(ovrHmd hmddesc, unsigned int supportedCaps,
+ unsigned int requiredCaps)
{
- if (hmddesc)
- {
- HMDState* p = (HMDState*)hmddesc->Handle;
- return p->ConfigureTracking(supportedCaps, requiredCaps);
- }
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ return ovrFalse;
- return 0;
+ return hmds->ConfigureTracking(supportedCaps, requiredCaps) ? ovrTrue : ovrFalse;
}
-OVR_EXPORT void ovrHmd_RecenterPose(ovrHmd hmddesc)
+
+OVR_PUBLIC_FUNCTION(void) ovrHmd_RecenterPose(ovrHmd hmddesc)
{
- if (hmddesc)
- {
- HMDState* p = (HMDState*)hmddesc->Handle;
- p->TheSensorStateReader.RecenterPose();
- }
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ return;
+
+ hmds->RecenterPose();
}
-OVR_EXPORT ovrTrackingState ovrHmd_GetTrackingState(ovrHmd hmddesc, double absTime)
+OVR_PUBLIC_FUNCTION(ovrTrackingState) ovrHmd_GetTrackingState(ovrHmd hmddesc, double absTime)
{
- ovrTrackingState result;
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ return GetNullTrackingState();
- if (hmddesc)
- {
- HMDState* p = (HMDState*)hmddesc->Handle;
- result = p->PredictedTrackingState(absTime);
+ return hmds->PredictedTrackingState(absTime);
+}
- // Instrument data from eye pose
- p->LagStats.InstrumentEyePose(result);
- }
- else
- memset(&result, 0, sizeof(result));
-#if !defined(HEADLESS_APP)
-#ifdef OVR_OS_WIN32
- // Set up display code for Windows
- Win32::DisplayShim::GetInstance().Active = (result.StatusFlags & ovrStatus_HmdConnected) != 0;
-#endif
-#endif /* !defined(HEADLESS_APP) */
- return result;
-}
//-------------------------------------------------------------------------------------
// *** General Setup
// Per HMD -> calculateIdealPixelSize
-OVR_EXPORT ovrSizei ovrHmd_GetFovTextureSize(ovrHmd hmddesc, ovrEyeType eye, ovrFovPort fov,
- float pixelsPerDisplayPixel)
+OVR_PUBLIC_FUNCTION(ovrSizei) ovrHmd_GetFovTextureSize(ovrHmd hmddesc, ovrEyeType eye,
+ ovrFovPort fov, float pixelsPerDisplayPixel)
{
- ovrHmdStruct * hmd = hmddesc->Handle;
- if (!hmd) return Sizei(0);
-
- HMDState* hmds = (HMDState*)hmd;
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ return Sizei(0);
+
return hmds->RenderState.GetFOVTextureSize(eye, fov, pixelsPerDisplayPixel);
}
@@ -590,73 +635,69 @@ OVR_EXPORT ovrSizei ovrHmd_GetFovTextureSize(ovrHmd hmddesc, ovrEyeType eye, ovr
//-------------------------------------------------------------------------------------
-OVR_EXPORT
-ovrBool ovrHmd_ConfigureRendering( ovrHmd hmddesc,
- const ovrRenderAPIConfig* apiConfig,
- unsigned int distortionCaps,
- const ovrFovPort eyeFovIn[2],
- ovrEyeRenderDesc eyeRenderDescOut[2] )
+OVR_PUBLIC_FUNCTION(ovrBool) ovrHmd_ConfigureRendering(ovrHmd hmddesc,
+ const ovrRenderAPIConfig* apiConfig,
+ unsigned int distortionCaps,
+ const ovrFovPort eyeFovIn[2],
+ ovrEyeRenderDesc eyeRenderDescOut[2])
{
- ovrHmdStruct * hmd = hmddesc->Handle;
- if (!hmd) return 0;
- return ((HMDState*)hmd)->ConfigureRendering(eyeRenderDescOut, eyeFovIn,
- apiConfig, distortionCaps);
-}
-
-
-
-// TBD: MA - Deprecated, need alternative
-void ovrHmd_SetVsync(ovrHmd hmddesc, ovrBool vsync)
-{
- ovrHmdStruct * hmd = hmddesc->Handle;
- if (!hmd) return;
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ return ovrFalse;
- return ((HMDState*)hmd)->TimeManager.SetVsync(vsync? true : false);
+ return hmds->ConfigureRendering(eyeRenderDescOut, eyeFovIn,
+ apiConfig, distortionCaps);
}
+OVR_PUBLIC_FUNCTION(ovrFrameTiming) ovrHmd_BeginFrame(ovrHmd hmddesc, unsigned int frameIndex)
+{
+ // NOTE: frameIndex == 0 is handled inside ovrHmd_BeginFrameTiming()
-OVR_EXPORT ovrFrameTiming ovrHmd_BeginFrame(ovrHmd hmddesc, unsigned int frameIndex)
-{
- HMDState* hmds = (HMDState*)hmddesc->Handle;
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
if (!hmds)
- {
- ovrFrameTiming f;
- memset(&f, 0, sizeof(f));
- return f;
- }
+ return GetNullFrameTiming();
+
+ TraceCall(frameIndex);
// Check: Proper configure and threading state for the call.
hmds->checkRenderingConfigured("ovrHmd_BeginFrame");
- OVR_DEBUG_LOG_COND(hmds->BeginFrameCalled, ("ovrHmd_BeginFrame called multiple times."));
+ OVR_DEBUG_LOG_COND(hmds->BeginFrameCalled, ("ovrHmd_BeginFrame called multiple times."));
ThreadChecker::Scope checkScope(&hmds->RenderAPIThreadChecker, "ovrHmd_BeginFrame");
-
+
hmds->BeginFrameCalled = true;
hmds->BeginFrameThreadId = OVR::GetCurrentThreadId();
- return ovrHmd_BeginFrameTiming(hmddesc, frameIndex);
+ ovrFrameTiming timing = ovrHmd_BeginFrameTiming(hmddesc, frameIndex);
+
+ TraceReturn(frameIndex);
+
+ return timing;
}
// Renders textures to frame buffer
-OVR_EXPORT void ovrHmd_EndFrame(ovrHmd hmddesc,
- const ovrPosef renderPose[2],
- const ovrTexture eyeTexture[2])
+OVR_PUBLIC_FUNCTION(void) ovrHmd_EndFrame(ovrHmd hmddesc,
+ const ovrPosef renderPose[2],
+ const ovrTexture eyeTexture[2])
{
- HMDState* hmds = (HMDState*)hmddesc->Handle;
- if (!hmds) return;
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ return;
- // Instrument when the EndFrame() call started
- hmds->LagStats.InstrumentEndFrameStart(ovr_GetTimeInSeconds());
+ const ovrTexture* eyeDepthTexture = nullptr;
+ ovrPositionTimewarpDesc* posTimewarpDesc = nullptr;
- hmds->SubmitEyeTextures(renderPose, eyeTexture);
+ TraceCall(hmds->BeginFrameIndex);
+
+ hmds->SubmitEyeTextures(renderPose, eyeTexture, eyeDepthTexture);
// Debug state checks: Must be in BeginFrame, on the same thread.
hmds->checkBeginFrameScope("ovrHmd_EndFrame");
ThreadChecker::Scope checkScope(&hmds->RenderAPIThreadChecker, "ovrHmd_EndFrame");
- hmds->pRenderer->SetLatencyTestColor(hmds->LatencyTestActive ? hmds->LatencyTestDrawColor : NULL);
+ hmds->pRenderer->SetLatencyTestColor(hmds->LatencyTestActive ? hmds->LatencyTestDrawColor : nullptr);
- ovrHmd_GetLatencyTest2DrawColor(hmddesc, NULL); // We don't actually need to draw color, so send NULL
+ ovrHmd_GetLatencyTest2DrawColor(hmddesc, nullptr); // We don't actually need to draw color, so send nullptr
if (hmds->pRenderer)
{
@@ -677,36 +718,33 @@ OVR_EXPORT void ovrHmd_EndFrame(ovrHmd hmddesc,
}
#endif /* !defined(HEADLESS_APP) */
- hmds->pRenderer->EndFrame(true);
+ if (posTimewarpDesc)
+ hmds->pRenderer->SetPositionTimewarpDesc(*posTimewarpDesc);
+
+ hmds->pRenderer->EndFrame(hmds->BeginFrameIndex, true);
hmds->pRenderer->RestoreGraphicsState();
}
// Call after present
ovrHmd_EndFrameTiming(hmddesc);
- // Instrument latency tester
- hmds->LagStats.InstrumentLatencyTimings(hmds->TimeManager);
-
- // Instrument when the EndFrame() call ended
- hmds->LagStats.InstrumentEndFrameEnd(ovr_GetTimeInSeconds());
+ TraceReturn(hmds->BeginFrameIndex);
// Out of BeginFrame
hmds->BeginFrameThreadId = 0;
hmds->BeginFrameCalled = false;
+ hmds->BeginFrameIndex++; // Set frame index to the next value in case 0 is passed.
}
-
#if !defined(HEADLESS_APP)
// Not exposed as part of public API
-OVR_EXPORT void ovrHmd_RegisterPostDistortionCallback(ovrHmd hmddesc, PostDistortionCallback callback)
+OVR_PUBLIC_FUNCTION(void) ovrHmd_RegisterPostDistortionCallback(ovrHmd hmddesc, PostDistortionCallback callback)
{
- HMDState* hmds = (HMDState*)hmddesc->Handle;
- if (!hmds) return;
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds || !hmds->pRenderer)
+ return;
- if (hmds->pRenderer)
- {
- hmds->pRenderer->RegisterPostDistortionCallback(callback);
- }
+ hmds->pRenderer->RegisterPostDistortionCallback(callback);
}
#endif /* !defined(HEADLESS_APP) */
@@ -715,209 +753,209 @@ OVR_EXPORT void ovrHmd_RegisterPostDistortionCallback(ovrHmd hmddesc, PostDistor
//-------------------------------------------------------------------------------------
// ***** Frame Timing logic
-
-OVR_EXPORT ovrFrameTiming ovrHmd_GetFrameTiming(ovrHmd hmddesc, unsigned int frameIndex)
+OVR_PUBLIC_FUNCTION(ovrFrameTiming) ovrHmd_GetFrameTiming(ovrHmd hmddesc, unsigned int frameIndex)
{
- ovrHmdStruct * hmd = hmddesc->Handle;
- ovrFrameTiming f;
- memset(&f, 0, sizeof(f));
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ return GetNullFrameTiming();
- HMDState* hmds = (HMDState*)hmd;
- if (hmds)
+ // If no frame index is provided,
+ if (frameIndex == 0)
{
- FrameTimeManager::Timing frameTiming = hmds->TimeManager.GetFrameTiming(frameIndex);
-
- f.ThisFrameSeconds = frameTiming.ThisFrameTime;
- f.NextFrameSeconds = frameTiming.NextFrameTime;
- f.TimewarpPointSeconds = frameTiming.TimewarpPointTime;
- f.ScanoutMidpointSeconds = frameTiming.MidpointTime;
- f.EyeScanoutSeconds[0] = frameTiming.EyeRenderTimes[0];
- f.EyeScanoutSeconds[1] = frameTiming.EyeRenderTimes[1];
-
- // Compute DeltaSeconds.
- f.DeltaSeconds = (hmds->LastGetFrameTimeSeconds == 0.0f) ? 0.0f :
- (float) (f.ThisFrameSeconds - hmds->LastFrameTimeSeconds);
- hmds->LastGetFrameTimeSeconds = f.ThisFrameSeconds;
- if (f.DeltaSeconds > 1.0f)
- f.DeltaSeconds = 1.0f;
+ // Use the next one in the series.
+ frameIndex = hmds->BeginFrameIndex;
}
-
- return f;
+
+ return hmds->GetFrameTiming(frameIndex);
}
-OVR_EXPORT ovrFrameTiming ovrHmd_BeginFrameTiming(ovrHmd hmddesc, unsigned int frameIndex)
+OVR_PUBLIC_FUNCTION(ovrFrameTiming) ovrHmd_BeginFrameTiming(ovrHmd hmddesc, unsigned int frameIndex)
{
- ovrHmdStruct * hmd = hmddesc->Handle;
- ovrFrameTiming f;
- memset(&f, 0, sizeof(f));
-
- HMDState* hmds = (HMDState*)hmd;
- if (!hmds) return f;
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ return GetNullFrameTiming();
// Check: Proper state for the call.
OVR_DEBUG_LOG_COND(hmds->BeginFrameTimingCalled,
("ovrHmd_BeginFrameTiming called multiple times."));
hmds->BeginFrameTimingCalled = true;
- double thisFrameTime = hmds->TimeManager.BeginFrame(frameIndex);
-
- const FrameTimeManager::Timing &frameTiming = hmds->TimeManager.GetFrameTiming();
+ // If a frame index is specified,
+ if (frameIndex != 0)
+ {
+ // Use the next one after the last BeginFrame() index.
+ hmds->BeginFrameIndex = (uint32_t)frameIndex;
+ }
+ else
+ {
+ frameIndex = hmds->BeginFrameIndex;
+ }
- f.ThisFrameSeconds = thisFrameTime;
- f.NextFrameSeconds = frameTiming.NextFrameTime;
- f.TimewarpPointSeconds = frameTiming.TimewarpPointTime;
- f.ScanoutMidpointSeconds= frameTiming.MidpointTime;
- f.EyeScanoutSeconds[0] = frameTiming.EyeRenderTimes[0];
- f.EyeScanoutSeconds[1] = frameTiming.EyeRenderTimes[1];
+ // Update latency tester once per frame
+ hmds->LatencyTestActive = hmds->ProcessLatencyTest(hmds->LatencyTestDrawColor);
- // Compute DeltaSeconds.
- f.DeltaSeconds = (hmds->LastFrameTimeSeconds == 0.0f) ? 0.0f :
- (float) (thisFrameTime - hmds->LastFrameTimeSeconds);
- hmds->LastFrameTimeSeconds = thisFrameTime;
- if (f.DeltaSeconds > 1.0f)
- f.DeltaSeconds = 1.0f;
+ if (!hmds->BeginFrameCalled)
+ {
+ hmds->TimewarpTimer.CalculateTimewarpTiming(frameIndex);
+ }
- return f;
+ return hmds->GetFrameTiming(frameIndex);
}
-
-OVR_EXPORT void ovrHmd_EndFrameTiming(ovrHmd hmddesc)
+OVR_PUBLIC_FUNCTION(void) ovrHmd_EndFrameTiming(ovrHmd hmddesc)
{
- HMDState* hmds = (HMDState*)hmddesc->Handle;
- if (!hmds) return;
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ return;
// Debug state checks: Must be in BeginFrameTiming, on the same thread.
hmds->checkBeginFrameTimingScope("ovrHmd_EndTiming");
// MA TBD: Correct check or not?
// ThreadChecker::Scope checkScope(&hmds->RenderAPIThreadChecker, "ovrHmd_EndFrame");
- hmds->TimeManager.EndFrame();
hmds->BeginFrameTimingCalled = false;
- bool dk2LatencyTest = (hmds->EnabledHmdCaps & ovrHmdCap_DynamicPrediction) != 0;
- if (dk2LatencyTest)
- {
- Util::FrameTimeRecordSet recordset;
- hmds->TheLatencyTestStateReader.GetRecordSet(recordset);
- hmds->TimeManager.UpdateFrameLatencyTrackingAfterEndFrame( hmds->LatencyTest2DrawColor,
- recordset);
- }
+ hmds->endFrameRenderTiming();
}
-
-OVR_EXPORT void ovrHmd_ResetFrameTiming(ovrHmd hmddesc, unsigned int frameIndex)
+OVR_PUBLIC_FUNCTION(void) ovrHmd_ResetFrameTiming(ovrHmd hmddesc, unsigned int frameIndex)
{
- HMDState* hmds = (HMDState*)hmddesc->Handle;
- if (!hmds) return;
-
- hmds->TimeManager.ResetFrameTiming(frameIndex,
- false,
- hmds->RenderingConfigured);
- hmds->LastFrameTimeSeconds = 0.0;
- hmds->LastGetFrameTimeSeconds = 0.0;
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ return;
+
+ OVR_UNUSED(frameIndex);
+
+ // Clear timing-related state.
+ hmds->BeginFrameIndex = frameIndex;
+ hmds->TimewarpTimer.Reset();
}
-OVR_EXPORT void ovrHmd_GetEyePoses(ovrHmd hmd, unsigned int frameIndex, ovrVector3f hmdToEyeViewOffset[2],
- ovrPosef outEyePoses[2], ovrTrackingState* outHmdTrackingState)
+OVR_PUBLIC_FUNCTION(void) ovrHmd_GetEyePoses(ovrHmd hmddesc, unsigned int frameIndex, const ovrVector3f hmdToEyeViewOffset[2],
+ ovrPosef outEyePoses[2], ovrTrackingState* outHmdTrackingState)
{
- HMDState* hmds = (HMDState*)hmd->Handle;
- if (!hmds) return;
+ if (!hmdToEyeViewOffset || !outEyePoses)
+ {
+ OVR_ASSERT(false);
+ return;
+ }
- hmds->LatencyTestActive = hmds->ProcessLatencyTest(hmds->LatencyTestDrawColor);
-
- ovrTrackingState hmdTrackingState = hmds->TimeManager.GetEyePredictionTracking(hmd, ovrEye_Count, frameIndex);
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ {
+ outEyePoses[0] = ovrPosef(); outEyePoses[0].Orientation.w = 1;
+ outEyePoses[1] = ovrPosef(); outEyePoses[1].Orientation.w = 1;
+ if (outHmdTrackingState)
+ *outHmdTrackingState = GetNullTrackingState();
+ return;
+ }
+
+ // If no frame index is provided,
+ if (frameIndex == 0)
+ {
+ // Use the next one in the series.
+ frameIndex = hmds->BeginFrameIndex;
+ }
+
+ ovrTrackingState hmdTrackingState = hmds->GetMidpointPredictionTracking(frameIndex);
+ TraceTrackingState(hmdTrackingState);
ovrPosef hmdPose = hmdTrackingState.HeadPose.ThePose;
// caller passed in a valid pointer, so copy to output
- if(outHmdTrackingState)
+ if (outHmdTrackingState)
*outHmdTrackingState = hmdTrackingState;
// Currently HmdToEyeViewOffset is only a 3D vector
// (Negate HmdToEyeViewOffset because offset is a view matrix offset and not a camera offset)
outEyePoses[0] = Posef(hmdPose.Orientation, ((Posef)hmdPose).Apply(-((Vector3f)hmdToEyeViewOffset[0])));
outEyePoses[1] = Posef(hmdPose.Orientation, ((Posef)hmdPose).Apply(-((Vector3f)hmdToEyeViewOffset[1])));
-
- // Instrument data from eye pose
- hmds->LagStats.InstrumentEyePose(hmdTrackingState);
}
-ovrPosef ovrHmd_GetHmdPosePerEye(ovrHmd hmd, ovrEyeType eye)
+OVR_PUBLIC_FUNCTION(ovrPosef) ovrHmd_GetHmdPosePerEye(ovrHmd hmddesc, ovrEyeType eye)
{
- HMDState* hmds = (HMDState*)hmd->Handle;
- if (!hmds) return ovrPosef();
-
- // This isn't a great place, but since we removed ovrHmd_BeginEyeRender...
- // Only process latency tester for drawing the left eye (assumes left eye is drawn first)
- if (hmds->pRenderer && eye == 0)
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
{
- hmds->LatencyTestActive = hmds->ProcessLatencyTest(hmds->LatencyTestDrawColor);
+ ovrPosef nullPose = ovrPosef();
+ nullPose.Orientation.w = 1.0f; // Return a proper quaternion.
+ return nullPose;
}
hmds->checkBeginFrameTimingScope("ovrHmd_GetEyePose");
- return hmds->TimeManager.GetEyePredictionPose(hmd, eye);
+
+ return hmds->GetEyePredictionPose(eye);
}
-OVR_EXPORT void ovrHmd_AddDistortionTimeMeasurement(ovrHmd hmddesc, double distortionTimeSeconds)
+OVR_PUBLIC_FUNCTION(void) ovrHmd_AddDistortionTimeMeasurement(ovrHmd hmddesc, double distortionTimeSeconds)
{
- if (!hmddesc)
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
return;
- HMDState* hmds = (HMDState*)hmddesc->Handle;
hmds->checkBeginFrameTimingScope("ovrHmd_GetTimewarpEyeMatrices");
- hmds->TimeManager.AddDistortionTimeMeasurement(distortionTimeSeconds);
-}
-
+ hmds->TimewarpTimer.AddDistortionTimeMeasurement(distortionTimeSeconds);
+}
-OVR_EXPORT void ovrHmd_GetEyeTimewarpMatricesDebug(ovrHmd hmddesc, ovrEyeType eye,
- ovrPosef renderPose, ovrMatrix4f twmOut[2],double debugTimingOffsetInSeconds)
+OVR_PUBLIC_FUNCTION(void) ovrHmd_GetEyeTimewarpMatricesDebug(ovrHmd hmddesc, ovrEyeType eye, ovrPosef renderPose,
+ ovrQuatf playerTorsoMotion, ovrMatrix4f twmOut[2],
+ double debugTimingOffsetInSeconds)
{
- if (!hmddesc)
+ if (!twmOut)
+ {
+ OVR_ASSERT(false);
+ return;
+ }
+
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
return;
- HMDState* hmds = (HMDState*)hmddesc->Handle;
// Debug checks: BeginFrame was called, on the same thread.
hmds->checkBeginFrameTimingScope("ovrHmd_GetTimewarpEyeMatrices");
- hmds->TimeManager.GetTimewarpMatrices(hmddesc, eye, renderPose, twmOut, debugTimingOffsetInSeconds);
+ // TODO: Position input disabled for now
+ bool calcPosition = false;
+ ovrVector3f* hmdToEyeViewOffset = nullptr;
- /*
- // MA: Took this out because new latency test approach just sames
- // the sample times in FrameTimeManager.
- // TODO: if no timewarp, then test latency in begin eye render
- if (eye == 0)
- {
- hmds->ProcessLatencyTest2(hmds->LatencyTest2DrawColor, -1.0f);
- }
- */
+ // playerTorsoMotion can be fed in by the app to indicate player rotation,
+ // i.e. renderPose is in torso space, and playerTorsoMotion says that torso space changed.
+ Quatf playerTorsoMotionInv = Quatf(playerTorsoMotion).Inverted();
+ Posef renderPoseTorso = (Posef)renderPose * Posef(playerTorsoMotionInv, Vector3f::Zero());
+ hmds->GetTimewarpMatricesEx(eye, renderPoseTorso, calcPosition, hmdToEyeViewOffset, twmOut,
+ debugTimingOffsetInSeconds);
}
-OVR_EXPORT void ovrHmd_GetEyeTimewarpMatrices(ovrHmd hmddesc, ovrEyeType eye,
- ovrPosef renderPose, ovrMatrix4f twmOut[2])
+OVR_PUBLIC_FUNCTION(void) ovrHmd_GetEyeTimewarpMatrices(ovrHmd hmddesc, ovrEyeType eye, ovrPosef renderPose, ovrMatrix4f twmOut[2])
{
- return(ovrHmd_GetEyeTimewarpMatricesDebug(hmddesc, eye, renderPose, twmOut, 0.0));
-}
+ if (!twmOut)
+ {
+ OVR_ASSERT(false);
+ return;
+ }
+
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ return;
+
+ // Shortcut to doing orientation-only timewarp.
+ hmds->GetTimewarpMatrices(eye, renderPose, twmOut);
+}
-OVR_EXPORT ovrEyeRenderDesc ovrHmd_GetRenderDesc(ovrHmd hmddesc,
- ovrEyeType eyeType, ovrFovPort fov)
+OVR_PUBLIC_FUNCTION(ovrEyeRenderDesc) ovrHmd_GetRenderDesc(ovrHmd hmddesc,
+ ovrEyeType eyeType, ovrFovPort fov)
{
- HMDState* hmds = (HMDState*)hmddesc->Handle;
- ovrEyeRenderDesc erd;
-
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
if (!hmds)
- {
- memset(&erd, 0, sizeof(erd));
- return erd;
- }
+ return ovrEyeRenderDesc();
return hmds->RenderState.CalcRenderDesc(eyeType, fov);
}
-
#if defined(OVR_CC_MSVC)
#define OVR_OFFSET_OF(s, field) ((size_t)&((s*)0)->field)
#else
@@ -925,39 +963,56 @@ OVR_EXPORT ovrEyeRenderDesc ovrHmd_GetRenderDesc(ovrHmd hmddesc,
#endif
+OVR_PUBLIC_FUNCTION(ovrBool) ovrHmd_CreateDistortionMeshDebug(ovrHmd hmddesc,
+ ovrEyeType eyeType, ovrFovPort fov,
+ unsigned int distortionCaps,
+ ovrDistortionMesh *meshData,
+ float debugEyeReliefOverrideInMetres)
+{
+ if (!meshData)
+ {
+ OVR_ASSERT(false);
+ return ovrFalse;
+ }
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ return ovrFalse;
-OVR_EXPORT ovrBool ovrHmd_CreateDistortionMeshDebug( ovrHmd hmddesc,
- ovrEyeType eyeType, ovrFovPort fov,
- unsigned int distortionCaps,
- ovrDistortionMesh *meshData,
- float debugEyeReliefOverrideInMetres)
-{
- // The 'internal' function below can be found in CAPI_HMDState.
- // Not ideal, but navigating the convolutions of what compiles
- // where, meant they are in the few places which actually lets these compile.
- // Please relocate (if you wish) to a more meaningful place if you can navigate the compiler gymnastics :)
- return(ovrHmd_CreateDistortionMeshInternal( hmddesc->Handle,
- eyeType, fov,
- distortionCaps,
- meshData,
- debugEyeReliefOverrideInMetres));
-
-}
-OVR_EXPORT ovrBool ovrHmd_CreateDistortionMesh( ovrHmd hmddesc,
- ovrEyeType eyeType, ovrFovPort fov,
- unsigned int distortionCaps,
- ovrDistortionMesh *meshData)
+ return hmds->CreateDistortionMesh(eyeType, fov,
+ distortionCaps,
+ meshData,
+ debugEyeReliefOverrideInMetres)
+ ? ovrTrue : ovrFalse;
+}
+
+
+OVR_PUBLIC_FUNCTION(ovrBool) ovrHmd_CreateDistortionMesh(ovrHmd hmddesc,
+ ovrEyeType eyeType, ovrFovPort fov,
+ unsigned int distortionCaps,
+ ovrDistortionMesh *meshData)
{
- return(ovrHmd_CreateDistortionMeshDebug( hmddesc, eyeType, fov, distortionCaps,meshData, 0));
+ if (!meshData)
+ {
+ OVR_ASSERT(false);
+ return ovrFalse;
+ }
+
+ return ovrHmd_CreateDistortionMeshDebug(hmddesc, eyeType, fov, distortionCaps, meshData, 0);
}
// Frees distortion mesh allocated by ovrHmd_GenerateDistortionMesh. meshData elements
// are set to null and 0s after the call.
-OVR_EXPORT void ovrHmd_DestroyDistortionMesh(ovrDistortionMesh* meshData)
+OVR_PUBLIC_FUNCTION(void) ovrHmd_DestroyDistortionMesh(ovrDistortionMesh* meshData)
{
+ if (!meshData)
+ {
+ OVR_ASSERT(false);
+ return;
+ }
+
if (meshData->pVertexData)
DistortionMeshDestroy((DistortionMeshVertexData*)meshData->pVertexData,
meshData->pIndexData);
@@ -971,10 +1026,16 @@ OVR_EXPORT void ovrHmd_DestroyDistortionMesh(ovrDistortionMesh* meshData)
// Computes updated 'uvScaleOffsetOut' to be used with a distortion if render target size or
// viewport changes after the fact. This can be used to adjust render size every frame, if desired.
-OVR_EXPORT void ovrHmd_GetRenderScaleAndOffset( ovrFovPort fov,
- ovrSizei textureSize, ovrRecti renderViewport,
- ovrVector2f uvScaleOffsetOut[2] )
+OVR_PUBLIC_FUNCTION(void) ovrHmd_GetRenderScaleAndOffset(ovrFovPort fov,
+ ovrSizei textureSize, ovrRecti renderViewport,
+ ovrVector2f uvScaleOffsetOut[2] )
{
+ if (!uvScaleOffsetOut)
+ {
+ OVR_ASSERT(false);
+ return;
+ }
+
// Find the mapping from TanAngle space to target NDC space.
ScaleAndOffset2D eyeToSourceNDC = CreateNDCScaleAndOffsetFromFov(fov);
// Find the mapping from TanAngle space to textureUV space.
@@ -982,73 +1043,95 @@ OVR_EXPORT void ovrHmd_GetRenderScaleAndOffset( ovrFovPort fov,
eyeToSourceNDC,
renderViewport, textureSize );
- uvScaleOffsetOut[0] = eyeToSourceUV.Scale;
- uvScaleOffsetOut[1] = eyeToSourceUV.Offset;
+ if (uvScaleOffsetOut)
+ {
+ uvScaleOffsetOut[0] = eyeToSourceUV.Scale;
+ uvScaleOffsetOut[1] = eyeToSourceUV.Offset;
+ }
}
//-------------------------------------------------------------------------------------
// ***** Latency Test interface
-OVR_EXPORT ovrBool ovrHmd_GetLatencyTestDrawColor(ovrHmd hmddesc, unsigned char rgbColorOut[3])
+OVR_PUBLIC_FUNCTION(ovrBool) ovrHmd_GetLatencyTestDrawColor(ovrHmd hmddesc, unsigned char rgbColorOut[3])
{
- HMDState* p = (HMDState*)hmddesc->Handle;
- rgbColorOut[0] = p->LatencyTestDrawColor[0];
- rgbColorOut[1] = p->LatencyTestDrawColor[1];
- rgbColorOut[2] = p->LatencyTestDrawColor[2];
- return p->LatencyTestActive;
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ return ovrFalse;
+
+ if (rgbColorOut)
+ {
+ rgbColorOut[0] = hmds->LatencyTestDrawColor[0];
+ rgbColorOut[1] = hmds->LatencyTestDrawColor[1];
+ rgbColorOut[2] = hmds->LatencyTestDrawColor[2];
+ }
+
+ return hmds->LatencyTestActive;
}
-OVR_EXPORT ovrBool ovrHmd_ProcessLatencyTest(ovrHmd hmddesc, unsigned char rgbColorOut[3])
+OVR_PUBLIC_FUNCTION(ovrBool) ovrHmd_ProcessLatencyTest(ovrHmd hmddesc, unsigned char rgbColorOut[3])
{
OVR_UNUSED(hmddesc);
+
+ if (!rgbColorOut)
+ {
+ OVR_ASSERT(false);
+ return ovrFalse;
+ }
+
return NetClient::GetInstance()->LatencyUtil_ProcessInputs(Timer::GetSeconds(), rgbColorOut);
}
-OVR_EXPORT const char* ovrHmd_GetLatencyTestResult(ovrHmd hmddesc)
+OVR_PUBLIC_FUNCTION(const char*) ovrHmd_GetLatencyTestResult(ovrHmd hmddesc)
{
OVR_UNUSED(hmddesc);
+
return NetClient::GetInstance()->LatencyUtil_GetResultsString();
}
-OVR_EXPORT ovrBool ovrHmd_GetLatencyTest2DrawColor(ovrHmd hmddesc, unsigned char rgbColorOut[3])
+OVR_PUBLIC_FUNCTION(ovrBool) ovrHmd_GetLatencyTest2DrawColor(ovrHmd hmddesc, unsigned char rgbColorOut[3])
{
- HMDState* hmds = (HMDState*)hmddesc->Handle;
- if (!hmds) return false;
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ return ovrFalse;
// TBD: Move directly into renderer
bool dk2LatencyTest = (hmds->EnabledHmdCaps & ovrHmdCap_DynamicPrediction) != 0;
if (dk2LatencyTest)
{
- hmds->TimeManager.GetFrameLatencyTestDrawColor(hmds->LatencyTest2DrawColor);
- if(rgbColorOut != NULL)
+ hmds->LatencyTest2DrawColor[0] = hmds->ScreenLatencyTracker.GetNextDrawColor();
+ hmds->LatencyTest2DrawColor[1] = hmds->ScreenLatencyTracker.IsLatencyTimingAvailable() ? 255 : 0;
+ hmds->LatencyTest2DrawColor[2] = hmds->ScreenLatencyTracker.IsLatencyTimingAvailable() ? 0 : 255;
+
+ if (rgbColorOut)
{
rgbColorOut[0] = hmds->LatencyTest2DrawColor[0];
rgbColorOut[1] = hmds->LatencyTest2DrawColor[1];
rgbColorOut[2] = hmds->LatencyTest2DrawColor[2];
}
- if(hmds->pRenderer != NULL)
+ if (hmds->pRenderer)
hmds->pRenderer->SetLatencyTest2Color(hmds->LatencyTest2DrawColor);
}
else
{
- if(hmds->pRenderer != NULL)
- hmds->pRenderer->SetLatencyTest2Color(NULL);
+ if (hmds->pRenderer)
+ hmds->pRenderer->SetLatencyTest2Color(nullptr);
}
- return dk2LatencyTest;
+ return dk2LatencyTest ? ovrTrue : ovrFalse;
}
-OVR_EXPORT double ovrHmd_GetMeasuredLatencyTest2(ovrHmd hmddesc)
+OVR_PUBLIC_FUNCTION(double) ovrHmd_GetMeasuredLatencyTest2(ovrHmd hmddesc)
{
- HMDState* p = (HMDState*)hmddesc->Handle;
-
- // MA Test
- float latencyRender, latencyTimewarp, latencyPostPresent;
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ return 0.;
- p->TimeManager.GetLatencyTimings(latencyRender, latencyTimewarp, latencyPostPresent);
+ double latencyPostPresent = 0.;
+ hmds->ScreenLatencyTracker.GetVsyncToScanout(latencyPostPresent);
return latencyPostPresent;
}
@@ -1059,253 +1142,296 @@ OVR_EXPORT double ovrHmd_GetMeasuredLatencyTest2(ovrHmd hmddesc)
#if !defined(HEADLESS_APP)
-OVR_EXPORT void ovrHmd_GetHSWDisplayState(ovrHmd hmd, ovrHSWDisplayState *hswDisplayState)
+OVR_PUBLIC_FUNCTION(void) ovrHmd_GetHSWDisplayState(ovrHmd hmddesc, ovrHSWDisplayState *hswDisplayState)
{
- OVR::CAPI::HMDState* pHMDState = (OVR::CAPI::HMDState*)hmd->Handle;
-
- if (pHMDState)
+ if (!hswDisplayState)
{
- OVR::CAPI::HSWDisplay* pHSWDisplay = pHMDState->pHSWDisplay;
-
- if(pHSWDisplay)
- pHSWDisplay->TickState(hswDisplayState); // This may internally call HSWDisplay::Display.
+ OVR_ASSERT(false);
+ return;
}
+
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ return;
+
+ OVR::CAPI::HSWDisplay* pHSWDisplay = hmds->pHSWDisplay;
+
+ if (pHSWDisplay)
+ pHSWDisplay->TickState(hswDisplayState); // This may internally call HSWDisplay::Display.
}
-OVR_EXPORT ovrBool ovrHmd_DismissHSWDisplay(ovrHmd hmd)
+OVR_PUBLIC_FUNCTION(ovrBool) ovrHmd_DismissHSWDisplay(ovrHmd hmddesc)
{
- OVR::CAPI::HMDState* pHMDState = (OVR::CAPI::HMDState*)hmd->Handle;
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds)
+ return ovrFalse;
- if (pHMDState)
- {
- OVR::CAPI::HSWDisplay* pHSWDisplay = pHMDState->pHSWDisplay;
+ OVR::CAPI::HSWDisplay* pHSWDisplay = hmds->pHSWDisplay;
- if(pHSWDisplay)
- return (pHSWDisplay->Dismiss() ? 1 : 0);
- }
+ if (pHSWDisplay && pHSWDisplay->Dismiss())
+ return ovrTrue;
- return false;
+ return ovrFalse;
}
#endif /* !defined(HEADLESS_APP) */
// -----------------------------------------------------------------------------------
// ***** Property Access
-OVR_EXPORT ovrBool ovrHmd_GetBool(ovrHmd hmddesc,
- const char* propertyName,
- ovrBool defaultVal)
+
+OVR_PUBLIC_FUNCTION(ovrBool) ovrHmd_GetBool(ovrHmd hmddesc,
+ const char* propertyName,
+ ovrBool defaultVal)
{
- OVR_ASSERT(propertyName);
- if (hmddesc)
+ OVR_ASSERT(propertyName != nullptr);
+ if (!propertyName)
+ return ovrFalse;
+
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ bool success = false;
+ if (hmds)
{
- HMDState* hmds = (HMDState*)hmddesc->Handle;
- OVR_ASSERT(hmds);
- if (hmds)
- {
- return hmds->getBoolValue(propertyName, (defaultVal != 0));
- }
+ success = hmds->getBoolValue(propertyName, (defaultVal != ovrFalse));
}
-
- return NetClient::GetInstance()->GetBoolValue(InvalidVirtualHmdId, propertyName, (defaultVal != 0)) ? 1 : 0;
-}
-
-OVR_EXPORT ovrBool ovrHmd_SetBool(ovrHmd hmddesc,
- const char* propertyName,
- ovrBool value)
-{
- OVR_ASSERT(propertyName);
- if (hmddesc)
+ else
{
- HMDState* hmds = (HMDState*)hmddesc->Handle;
- OVR_ASSERT(hmds);
- if (hmds)
- {
- return hmds->setBoolValue(propertyName, value != 0) ? 1 : 0;
- }
+ success = NetClient::GetInstance()->GetBoolValue(InvalidVirtualHmdId, propertyName, (defaultVal != ovrFalse));
}
-
- return NetClient::GetInstance()->SetBoolValue(InvalidVirtualHmdId, propertyName, (value != 0)) ? 1 : 0;
+ return success ? ovrTrue : ovrFalse;
}
-OVR_EXPORT int ovrHmd_GetInt(ovrHmd hmddesc,
- const char* propertyName,
- int defaultVal)
+OVR_PUBLIC_FUNCTION(ovrBool) ovrHmd_SetBool(ovrHmd hmddesc,
+ const char* propertyName,
+ ovrBool value)
{
- OVR_ASSERT(propertyName);
- if (hmddesc)
+ OVR_ASSERT(propertyName != nullptr);
+ if (!propertyName)
+ return ovrFalse;
+
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ bool retval = false;
+ if (hmds)
{
- HMDState* hmds = (HMDState*)hmddesc->Handle;
- OVR_ASSERT(hmds);
- if (hmds)
- {
- return hmds->getIntValue(propertyName, defaultVal);
- }
+ retval = hmds->setBoolValue(propertyName, value != ovrFalse);
}
-
- return NetClient::GetInstance()->GetIntValue(InvalidVirtualHmdId, propertyName, defaultVal);
+ else
+ {
+ retval = NetClient::GetInstance()->SetBoolValue(InvalidVirtualHmdId, propertyName, (value != ovrFalse));
+ }
+ return retval ? ovrTrue : ovrFalse;
}
-OVR_EXPORT ovrBool ovrHmd_SetInt(ovrHmd hmddesc,
- const char* propertyName,
- int value)
+OVR_PUBLIC_FUNCTION(int) ovrHmd_GetInt(ovrHmd hmddesc,
+ const char* propertyName,
+ int defaultVal)
{
- OVR_ASSERT(propertyName);
- if (hmddesc)
+ OVR_ASSERT(propertyName != nullptr);
+ if (!propertyName)
+ return ovrFalse;
+
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (hmds)
{
- HMDState* hmds = (HMDState*)hmddesc->Handle;
- OVR_ASSERT(hmds);
- if (hmds)
- {
- return hmds->setIntValue(propertyName, value) ? 1 : 0;
- }
+ return hmds->getIntValue(propertyName, defaultVal);
+ }
+ else
+ {
+ return NetClient::GetInstance()->GetIntValue(InvalidVirtualHmdId, propertyName, defaultVal);
}
-
- return NetClient::GetInstance()->SetIntValue(InvalidVirtualHmdId, propertyName, value) ? 1 : 0;
}
-OVR_EXPORT float ovrHmd_GetFloat(ovrHmd hmddesc,
- const char* propertyName,
- float defaultVal)
+OVR_PUBLIC_FUNCTION(ovrBool) ovrHmd_SetInt(ovrHmd hmddesc,
+ const char* propertyName,
+ int value)
{
- OVR_ASSERT(propertyName);
- if (hmddesc)
+ OVR_ASSERT(propertyName != nullptr);
+ if (!propertyName)
+ return ovrFalse;
+
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ bool success = false;
+ if (hmds)
{
- HMDState* hmds = (HMDState*)hmddesc->Handle;
- OVR_ASSERT(hmds);
- if (hmds)
- {
- return hmds->getFloatValue(propertyName, defaultVal);
- }
+ success = hmds->setIntValue(propertyName, value);
}
-
- return (float)NetClient::GetInstance()->GetNumberValue(InvalidVirtualHmdId, propertyName, defaultVal);
+ else
+ {
+ success = NetClient::GetInstance()->SetIntValue(InvalidVirtualHmdId, propertyName, value);
+ }
+ return success ? ovrTrue : ovrFalse;
}
-OVR_EXPORT ovrBool ovrHmd_SetFloat(ovrHmd hmddesc,
- const char* propertyName,
- float value)
+OVR_PUBLIC_FUNCTION(float) ovrHmd_GetFloat(ovrHmd hmddesc,
+ const char* propertyName,
+ float defaultVal)
{
- OVR_ASSERT(propertyName);
- if (hmddesc)
+ OVR_ASSERT(propertyName != nullptr);
+ if (!propertyName)
+ return ovrFalse;
+
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (hmds)
{
- HMDState* hmds = (HMDState*)hmddesc->Handle;
- OVR_ASSERT(hmds);
- if (hmds)
- {
- return hmds->setFloatValue(propertyName, value) ? 1 : 0;
- }
+ return hmds->getFloatValue(propertyName, defaultVal);
+ }
+ else
+ {
+ return (float)NetClient::GetInstance()->GetNumberValue(InvalidVirtualHmdId, propertyName, defaultVal);
}
-
- return NetClient::GetInstance()->SetNumberValue(InvalidVirtualHmdId, propertyName, value) ? 1 : 0;
}
-OVR_EXPORT unsigned int ovrHmd_GetFloatArray(ovrHmd hmddesc,
+OVR_PUBLIC_FUNCTION(ovrBool) ovrHmd_SetFloat(ovrHmd hmddesc,
const char* propertyName,
- float values[],
- unsigned int arraySize)
+ float value)
{
- OVR_ASSERT(propertyName);
- OVR_ASSERT(hmddesc);
- if (hmddesc)
+ OVR_ASSERT(propertyName != nullptr);
+ if (!propertyName)
+ return ovrFalse;
+
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ bool success = false;
+ if (hmds)
{
- HMDState* hmds = (HMDState*)hmddesc->Handle;
- OVR_ASSERT(hmds);
- if (hmds)
- {
- return hmds->getFloatArray(propertyName, values, arraySize);
- }
+ success = hmds->setFloatValue(propertyName, value);
+ }
+ else
+ {
+ success = NetClient::GetInstance()->SetNumberValue(InvalidVirtualHmdId, propertyName, value);
}
+ return success ? ovrTrue : ovrFalse;
+}
+
+OVR_PUBLIC_FUNCTION(unsigned int) ovrHmd_GetFloatArray(ovrHmd hmddesc,
+ const char* propertyName,
+ float values[],
+ unsigned int arraySize)
+{
+ OVR_ASSERT(propertyName != nullptr && values != nullptr);
+ if (!propertyName || !values)
+ return 0;
+
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds) return 0;
- // FIXME: Currently it takes a few lines of code to do this, so just not supported for now.
- return 0;
+ return hmds->getFloatArray(propertyName, values, arraySize);
}
// Modify float[] property; false if property doesn't exist or is readonly.
-OVR_EXPORT ovrBool ovrHmd_SetFloatArray(ovrHmd hmddesc,
- const char* propertyName,
- float values[],
- unsigned int arraySize)
+OVR_PUBLIC_FUNCTION(ovrBool) ovrHmd_SetFloatArray(ovrHmd hmddesc,
+ const char* propertyName,
+ float values[],
+ unsigned int arraySize)
{
- OVR_ASSERT(propertyName);
- OVR_ASSERT(hmddesc);
- if (hmddesc)
- {
- HMDState* hmds = (HMDState*)hmddesc->Handle;
- OVR_ASSERT(hmds);
- if (hmds)
- {
- return hmds->setFloatArray(propertyName, values, arraySize) ? 1 : 0;
- }
- }
+ OVR_ASSERT(propertyName != nullptr && values != nullptr);
+ if (!propertyName || !values)
+ return ovrFalse;
- // FIXME: Currently it takes a few lines of code to do this, so just not supported for now.
- return 0;
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (!hmds) return ovrFalse;
+
+ return hmds->setFloatArray(propertyName, values, arraySize) ? ovrTrue : ovrFalse;
}
-OVR_EXPORT const char* ovrHmd_GetString(ovrHmd hmddesc,
- const char* propertyName,
- const char* defaultVal)
+OVR_PUBLIC_FUNCTION(const char*) ovrHmd_GetString(ovrHmd hmddesc,
+ const char* propertyName,
+ const char* defaultVal)
{
- OVR_ASSERT(propertyName);
- if (hmddesc)
+ OVR_ASSERT(propertyName != nullptr);
+ if (!propertyName)
+ return "";
+
+ // Replace null default with empty string
+ if (!defaultVal)
+ defaultVal = "";
+
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ if (hmds)
{
- HMDState* hmds = (HMDState*)hmddesc->Handle;
- if (hmds)
- {
- return hmds->getString(propertyName, defaultVal);
- }
+ return hmds->getString(propertyName, defaultVal);
+ }
+ else
+ {
+ return NetClient::GetInstance()->GetStringValue(InvalidVirtualHmdId, propertyName, defaultVal);
}
-
- return NetClient::GetInstance()->GetStringValue(InvalidVirtualHmdId, propertyName, defaultVal);
}
-
-OVR_EXPORT ovrBool ovrHmd_SetString(ovrHmd hmddesc,
- const char* propertyName,
- const char* value)
+
+OVR_PUBLIC_FUNCTION(ovrBool) ovrHmd_SetString(ovrHmd hmddesc,
+ const char* propertyName,
+ const char* value)
{
- OVR_ASSERT(propertyName);
- if (hmddesc)
+ OVR_ASSERT(propertyName != nullptr);
+ if (!propertyName)
+ return ovrFalse;
+
+ // Replace null value with empty string
+ if (!value)
+ value = "";
+
+ HMDState* hmds = GetHMDStateFromOvrHmd(hmddesc);
+ bool success = false;
+ if (hmds)
{
- HMDState* hmds = (HMDState*)hmddesc->Handle;
- if (hmds)
- {
- return hmds->setString(propertyName, value) ? 1 : 0;
- }
+ success = hmds->setString(propertyName, value);
}
-
- return NetClient::GetInstance()->SetStringValue(InvalidVirtualHmdId, propertyName, value) ? 1 : 0;
+ else
+ {
+ success = NetClient::GetInstance()->SetStringValue(InvalidVirtualHmdId, propertyName, value);
+ }
+ return success ? ovrTrue : ovrFalse;
}
+
// -----------------------------------------------------------------------------------
// ***** Logging
-OVR_EXPORT ovrBool ovrHmd_StartPerfLog(ovrHmd hmd, const char* fileName, const char* userData1)
-{
- OVR_ASSERT(fileName && fileName[0]);
+// make sure OVR_Log.h's enum matches CAPI's
+static_assert(
+ ((ovrLogLevel_Debug == ovrLogLevel(LogLevel_Debug)) &&
+ (ovrLogLevel_Info == ovrLogLevel(LogLevel_Info)) &&
+ (ovrLogLevel_Error == ovrLogLevel(LogLevel_Error))),
+ "mismatched LogLevel enums"
+);
- OVR::CAPI::HMDState* pHMDState = (OVR::CAPI::HMDState*)hmd->Handle;
+#define OVR_TRACEMSG_MAX_LEN 1024 /* in chars */
- if (pHMDState)
- {
- ovrBool started = pHMDState->LagStatsCSV.Start(fileName, userData1) ? 1 : 0;
- if (started)
- pHMDState->LagStats.AddResultsObserver(pHMDState->LagStatsCSV.GetObserver());
- return started;
- }
- return 0;
-}
-OVR_EXPORT ovrBool ovrHmd_StopPerfLog(ovrHmd hmd)
+OVR_PUBLIC_FUNCTION(int) ovr_TraceMessage(int level, const char* message)
{
- OVR::CAPI::HMDState* pHMDState = (OVR::CAPI::HMDState*)hmd->Handle;
+ OVR_ASSERT(message != nullptr);
+ if (!message)
+ return -1;
+
+ // Keep traced messages to some reasonable maximum length
+ int len = (int)strnlen(message, OVR_TRACEMSG_MAX_LEN);
+ if (len >= OVR_TRACEMSG_MAX_LEN)
+ return -1;
- if (pHMDState)
+ switch (level)
{
- return pHMDState->LagStatsCSV.Stop() ? 1 : 0;
+ case ovrLogLevel_Debug:
+ TraceLogDebug(message);
+ break;
+ case ovrLogLevel_Info:
+ default:
+ TraceLogInfo(message);
+ break;
+ case ovrLogLevel_Error:
+ TraceLogError(message);
+ break;
}
- return false;
+
+ return len;
}
+OVR_PUBLIC_FUNCTION(ovrBool) ovrHmd_StartPerfLog(ovrHmd hmddesc, const char* fileName, const char* userData1)
+{
+ // DEPRECATED
+ OVR_UNUSED3(hmddesc, fileName, userData1);
+ return ovrFalse;
+}
-#ifdef __cplusplus
-} // extern "C"
-#endif
+OVR_PUBLIC_FUNCTION(ovrBool) ovrHmd_StopPerfLog(ovrHmd hmddesc)
+{
+ // DEPRECATED
+ OVR_UNUSED(hmddesc);
+ return ovrFalse;
+}