aboutsummaryrefslogtreecommitdiffstats
path: root/LibOVR/Src/CAPI/CAPI_HMDState.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'LibOVR/Src/CAPI/CAPI_HMDState.cpp')
-rw-r--r--LibOVR/Src/CAPI/CAPI_HMDState.cpp858
1 files changed, 424 insertions, 434 deletions
diff --git a/LibOVR/Src/CAPI/CAPI_HMDState.cpp b/LibOVR/Src/CAPI/CAPI_HMDState.cpp
index fd98225..6d6162d 100644
--- a/LibOVR/Src/CAPI/CAPI_HMDState.cpp
+++ b/LibOVR/Src/CAPI/CAPI_HMDState.cpp
@@ -25,495 +25,396 @@ limitations under the License.
************************************************************************************/
#include "CAPI_HMDState.h"
-#include "CAPI_GlobalState.h"
#include "../OVR_Profile.h"
+#include "../Service/Service_NetClient.h"
+#ifdef OVR_OS_WIN32
+#include "../Displays/OVR_Win32_ShimFunctions.h"
+#endif
+
namespace OVR { namespace CAPI {
+
//-------------------------------------------------------------------------------------
// ***** HMDState
-
-HMDState::HMDState(HMDDevice* device)
- : pHMD(device), HMDInfoW(device), HMDInfo(HMDInfoW.h),
- EnabledHmdCaps(0), HmdCapsAppliedToSensor(0),
- SensorStarted(0), SensorCreated(0), SensorCaps(0),
- AddSensorCount(0), AddLatencyTestCount(0), AddLatencyTestDisplayCount(0),
- RenderState(getThis(), pHMD->GetProfile(), HMDInfoW.h),
- LastFrameTimeSeconds(0.0f), LastGetFrameTimeSeconds(0.0),
- LatencyTestActive(false),
- LatencyTest2Active(false)
+HMDState::HMDState(const OVR::Service::HMDNetworkInfo& netInfo,
+ const OVR::HMDInfo& hmdInfo,
+ Profile* profile,
+ Service::NetClient* client) :
+ pClient(client),
+ pProfile(profile),
+ pHmdDesc(0),
+ pWindow(0),
+ NetInfo(netInfo),
+ NetId(netInfo.NetId),
+ OurHMDInfo(hmdInfo),
+ EnabledHmdCaps(0),
+ LastFrameTimeSeconds(0.f),
+ LastGetFrameTimeSeconds(0.),
+ LatencyTestActive(false),
+ LatencyTest2Active(false)
{
- pLastError = 0;
- GlobalState::pInstance->AddHMD(this);
-
- // Should be in renderer?
- TimeManager.Init(RenderState.RenderInfo);
+ sharedInit(profile);
+}
- EyeRenderActive[0] = false;
- EyeRenderActive[1] = false;
+HMDState::HMDState(const OVR::HMDInfo& hmdInfo, Profile* profile) :
+ pClient(0),
+ pHmdDesc(0),
+ NetId(InvalidVirtualHmdId),
+ pProfile(profile),
+ OurHMDInfo(hmdInfo),
+ EnabledHmdCaps(0),
+ LastFrameTimeSeconds(0.),
+ LastGetFrameTimeSeconds(0.)
+{
+ sharedInit(profile);
+}
- LatencyTestDrawColor[0] = 0;
- LatencyTestDrawColor[1] = 0;
- LatencyTestDrawColor[2] = 0;
+HMDState::~HMDState()
+{
+ if (pClient)
+ {
+ pClient->Hmd_Release(NetId);
+ pClient = 0;
+ }
- OVR_CAPI_VISION_CODE( pPoseTracker = 0; )
+ ConfigureRendering(0,0,0,0);
- RenderingConfigured = false;
- BeginFrameCalled = false;
- BeginFrameThreadId = 0;
- BeginFrameTimingCalled = false;
+ if (pHmdDesc)
+ delete pHmdDesc;
}
-HMDState::HMDState(ovrHmdType hmdType)
- : pHMD(0), HMDInfoW(hmdType), HMDInfo(HMDInfoW.h),
- EnabledHmdCaps(0),
- SensorStarted(0), SensorCreated(0), SensorCaps(0),
- AddSensorCount(0), AddLatencyTestCount(0), AddLatencyTestDisplayCount(0),
- RenderState(getThis(), 0, HMDInfoW.h), // No profile.
- LastFrameTimeSeconds(0.0), LastGetFrameTimeSeconds(0.0)
+void HMDState::sharedInit(Profile* profile)
{
// TBD: We should probably be looking up the default profile for the given
- // device type + user.
-
+ // device type + user if profile == 0.
pLastError = 0;
- GlobalState::pInstance->AddHMD(this);
- // Should be in renderer?
- TimeManager.Init(RenderState.RenderInfo);
+ RenderState.OurHMDInfo = OurHMDInfo;
+
+ UpdateRenderProfile(profile);
+
+ OVR_ASSERT(!pHmdDesc);
+ pHmdDesc = new ovrHmdDesc;
+ *pHmdDesc = RenderState.GetDesc();
+ pHmdDesc->Handle = this;
- EyeRenderActive[0] = false;
- EyeRenderActive[1] = false;
+ RenderState.ClearColor[0] = 0.0f;
+ RenderState.ClearColor[1] = 0.0f;
+ RenderState.ClearColor[2] = 0.0f;
+ RenderState.ClearColor[3] = 0.0f;
- OVR_CAPI_VISION_CODE( pPoseTracker = 0; )
+ RenderState.EnabledHmdCaps = 0;
+
+ TimeManager.Init(RenderState.RenderInfo);
+
+ /*
+ LatencyTestDrawColor[0] = 0;
+ LatencyTestDrawColor[1] = 0;
+ LatencyTestDrawColor[2] = 0;
+ */
RenderingConfigured = false;
BeginFrameCalled = false;
BeginFrameThreadId = 0;
BeginFrameTimingCalled = false;
-}
+ // Construct the HSWDisplay. We will later reconstruct it with a specific ovrRenderAPI type if the application starts using SDK-based rendering.
+ if(!pHSWDisplay)
+ pHSWDisplay = *OVR::CAPI::HSWDisplay::Factory(ovrRenderAPI_None, pHmdDesc, RenderState);
+}
-HMDState::~HMDState()
+static Vector3f GetNeckModelFromProfile(Profile* profile)
{
- OVR_ASSERT(GlobalState::pInstance);
-
- StopSensor();
- ConfigureRendering(0,0,0,0);
+ OVR_ASSERT(profile);
- OVR_CAPI_VISION_CODE( OVR_ASSERT(pPoseTracker == 0); )
-
- GlobalState::pInstance->RemoveHMD(this);
-}
+ float neckeye[2] = { OVR_DEFAULT_NECK_TO_EYE_HORIZONTAL, OVR_DEFAULT_NECK_TO_EYE_VERTICAL };
+ profile->GetFloatValues(OVR_KEY_NECK_TO_EYE_DISTANCE, neckeye, 2);
+ // Make sure these are vaguely sensible values.
+ //OVR_ASSERT((neckeye[0] > 0.05f) && (neckeye[0] < 0.5f));
+ //OVR_ASSERT((neckeye[1] > 0.05f) && (neckeye[1] < 0.5f));
+ // Named for clarity
+ float NeckToEyeHorizontal = neckeye[0];
+ float NeckToEyeVertical = neckeye[1];
-//-------------------------------------------------------------------------------------
-// *** Sensor
+ // Store the neck model
+ return Vector3f(0.0, NeckToEyeVertical, -NeckToEyeHorizontal);
+}
-bool HMDState::StartSensor(unsigned supportedCaps, unsigned requiredCaps)
+static float GetCenterPupilDepthFromRenderInfo(HmdRenderInfo* hmdRenderInfo)
{
- Lock::Locker lockScope(&DevicesLock);
-
- bool crystalCoveOrBetter = (HMDInfo.HmdType == HmdType_CrystalCoveProto) ||
- (HMDInfo.HmdType == HmdType_DK2);
- bool sensorCreatedJustNow = false;
-
- // TBD: In case of sensor not being immediately available, it would be good to check
- // yaw config availability to match it with ovrHmdCap_YawCorrection requirement.
- //
+ OVR_ASSERT(hmdRenderInfo);
+
+ // Find the distance from the center of the screen to the "center eye"
+ // This center eye is used by systems like rendering & audio to represent the player,
+ // and they will handle the offsets needed from there to each actual eye.
+
+ // HACK HACK HACK
+ // We know for DK1 the screen->lens surface distance is roughly 0.049f, and that the faceplate->lens is 0.02357f.
+ // We're going to assume(!!!!) that all HMDs have the same screen->faceplate distance.
+ // Crystal Cove was measured to be roughly 0.025 screen->faceplate which agrees with this assumption.
+ // TODO: do this properly! Update: Measured this at 0.02733 with a CC prototype, CES era (PT7), on 2/19/14 -Steve
+ float screenCenterToMidplate = 0.02733f;
+ float centerEyeRelief = hmdRenderInfo->GetEyeCenter().ReliefInMeters;
+ float CenterPupilDepth = screenCenterToMidplate + hmdRenderInfo->LensSurfaceToMidplateInMeters + centerEyeRelief;
+
+ return CenterPupilDepth;
+}
- if (!crystalCoveOrBetter)
- {
- if (requiredCaps & ovrSensorCap_Position)
- {
- pLastError = "ovrSensorCap_Position not supported on this HMD.";
- return false;
- }
+void HMDState::UpdateRenderProfile(Profile* profile)
+{
+ // Apply the given profile to generate a render context
+ RenderState.RenderInfo = GenerateHmdRenderInfoFromHmdInfo(RenderState.OurHMDInfo, profile);
+ RenderState.Distortion[0] = CalculateDistortionRenderDesc(StereoEye_Left, RenderState.RenderInfo, 0);
+ RenderState.Distortion[1] = CalculateDistortionRenderDesc(StereoEye_Right, RenderState.RenderInfo, 0);
+
+ if (pClient)
+ {
+ // Center pupil depth
+ float centerPupilDepth = GetCenterPupilDepthFromRenderInfo(&RenderState.RenderInfo);
+ pClient->SetNumberValue(GetNetId(), "CenterPupilDepth", centerPupilDepth);
+
+ // Neck model
+ Vector3f neckModel = GetNeckModelFromProfile(profile);
+ double neckModelArray[3] = {
+ neckModel.x,
+ neckModel.y,
+ neckModel.z
+ };
+ pClient->SetNumberValues(GetNetId(), "NeckModelVector3f", neckModelArray, 3);
}
+}
- supportedCaps |= requiredCaps;
-
- if (pHMD && !pSensor)
+HMDState* HMDState::CreateHMDState(NetClient* client, const HMDNetworkInfo& netInfo)
+{
+ // HMDState works through a handle to service HMD....
+ HMDInfo hinfo;
+ if (!client->Hmd_GetHmdInfo(netInfo.NetId, &hinfo))
{
- // Zero AddSensorCount before creation, in case it fails (or succeeds but then
- // immediately gets disconnected) followed by another Add notification.
- AddSensorCount = 0;
- pSensor = *pHMD->GetSensor();
- sensorCreatedJustNow= true;
-
- if (pSensor)
- {
- pSensor->SetReportRate(500);
- SFusion.AttachToSensor(pSensor);
- applyProfileToSensorFusion();
- }
- else
- {
- if (requiredCaps & ovrSensorCap_Orientation)
- {
- pLastError = "Failed to create sensor.";
- return false;
- }
- }
+ OVR_DEBUG_LOG(("[HMDState] Unable to get HMD info"));
+ return NULL;
}
+#ifdef OVR_OS_WIN32
+ OVR_DEBUG_LOG(("Setting up display shim"));
- if ((requiredCaps & ovrSensorCap_YawCorrection) && !pSensor->IsMagCalibrated())
- {
- pLastError = "ovrHmdCap_YawCorrection not available.";
- if (sensorCreatedJustNow)
- {
- SFusion.AttachToSensor(0);
- SFusion.Reset();
- pSensor.Clear();
- }
- return false;
- }
+ // Initialize the display shim before reporting the display to the user code
+ // so that this will happen before the D3D display object is created.
+ Win32::DisplayShim::GetInstance().Update(&hinfo.ShimInfo);
+#endif
- SFusion.SetYawCorrectionEnabled((supportedCaps & ovrSensorCap_YawCorrection) != 0);
+ Ptr<Profile> pDefaultProfile = *ProfileManager::GetInstance()->GetDefaultUserProfile(&hinfo);
+ OVR_DEBUG_LOG(("Using profile %s", pDefaultProfile->GetValue(OVR_KEY_USER)));
- if (pSensor && sensorCreatedJustNow)
- {
- LogText("Sensor created.\n");
- SensorCreated = true;
- }
-
- updateDK2FeaturesTiedToSensor(sensorCreatedJustNow);
-
+ HMDState* hmds = new HMDState(netInfo, hinfo, pDefaultProfile, client);
-#ifdef OVR_CAPI_VISIONSUPPORT
-
- if (crystalCoveOrBetter && (supportedCaps & ovrSensorCap_Position))
+ if (!hmds->SharedStateReader.Open(netInfo.SharedMemoryName.ToCStr()))
{
- if (!pPoseTracker)
- {
- pPoseTracker = new Vision::PoseTracker(SFusion);
- if (pPoseTracker)
- {
- pPoseTracker->AssociateHMD(pSensor);
- LogText("Sensor Pose tracker created.\n");
- }
- }
-
- // TBD: How do we verify that position tracking is actually available
- // i.e. camera is plugged in?
- }
- else if (pPoseTracker)
- {
- // TBD: Internals not thread safe - must fix!!
- delete pPoseTracker;
- pPoseTracker = 0;
- LogText("Sensor Pose tracker destroyed.\n");
+ delete hmds;
+ return NULL;
}
-#endif // OVR_CAPI_VISIONSUPPORT
-
- SensorCaps = supportedCaps;
- SensorStarted = true;
+ hmds->TheSensorStateReader.SetUpdater(hmds->SharedStateReader.Get());
+ hmds->TheLatencyTestStateReader.SetUpdater(hmds->SharedStateReader.Get());
- return true;
+ return hmds;
}
-
-// Stops sensor sampling, shutting down internal resources.
-void HMDState::StopSensor()
+HMDState* HMDState::CreateHMDState(ovrHmdType hmdType)
{
- Lock::Locker lockScope(&DevicesLock);
-
- if (SensorStarted)
- {
-#ifdef OVR_CAPI_VISIONSUPPORT
- if (pPoseTracker)
- {
- // TBD: Internals not thread safe - must fix!!
- delete pPoseTracker;
- pPoseTracker = 0;
- LogText("Sensor Pose tracker destroyed.\n");
- }
-#endif // OVR_CAPI_VISION_CODE
+ HmdTypeEnum t = HmdType_None;
+ if (hmdType == ovrHmd_DK1)
+ t = HmdType_DK1;
+ else if (hmdType == ovrHmd_DK2)
+ t = HmdType_DK2;
- SFusion.AttachToSensor(0);
- SFusion.Reset();
- pSensor.Clear();
- HmdCapsAppliedToSensor = 0;
- AddSensorCount = 0;
- SensorCaps = 0;
- SensorCreated = false;
- SensorStarted = false;
+ // FIXME: This does not actually grab the right user..
+ Ptr<Profile> pDefaultProfile = *ProfileManager::GetInstance()->GetDefaultProfile(t);
- LogText("StopSensor succeeded.\n");
- }
+ return new HMDState(CreateDebugHMDInfo(t), pDefaultProfile);
}
+
-// Resets sensor orientation.
-void HMDState::ResetSensor()
+//-------------------------------------------------------------------------------------
+// *** Sensor
+
+bool HMDState::ConfigureTracking(unsigned supportedCaps, unsigned requiredCaps)
{
- SFusion.Reset();
+ return pClient ? pClient->Hmd_ConfigureTracking(NetId, supportedCaps, requiredCaps) : true;
}
+void HMDState::ResetTracking()
+{
+ if (pClient) pClient->Hmd_ResetTracking(NetId);
+}
+
+// Re-center the orientation.
+void HMDState::RecenterPose()
+{
+ TheSensorStateReader.RecenterPose();
+}
// Returns prediction for time.
-ovrSensorState HMDState::PredictedSensorState(double absTime)
+ovrTrackingState HMDState::PredictedTrackingState(double absTime)
{
- SensorState ss;
-
- // We are trying to keep this path lockless unless we are notified of new device
- // creation while not having a sensor yet. It's ok to check SensorCreated volatile
- // flag here, since GetSensorStateAtTime() is internally lockless and safe.
-
- if (SensorCreated || checkCreateSensor())
- {
- ss = SFusion.GetSensorStateAtTime(absTime);
+ Tracking::TrackingState ss;
+ TheSensorStateReader.GetSensorStateAtTime(absTime, ss);
- if (!(ss.StatusFlags & ovrStatus_OrientationTracked))
- {
- Lock::Locker lockScope(&DevicesLock);
-
-#ifdef OVR_CAPI_VISIONSUPPORT
- if (pPoseTracker)
- {
- // TBD: Internals not thread safe - must fix!!
- delete pPoseTracker;
- pPoseTracker = 0;
- LogText("Sensor Pose tracker destroyed.\n");
- }
-#endif // OVR_CAPI_VISION_CODE
- // Not needed yet; SFusion.AttachToSensor(0);
- // This seems to reset orientation anyway...
- pSensor.Clear();
- SensorCreated = false;
- HmdCapsAppliedToSensor = 0;
- }
- }
- else
+ // Zero out the status flags
+ if (!pClient || !pClient->IsConnected())
{
- // SensorState() defaults to 0s.
- // ss.Pose.Orientation = Quatf();
- // ..
-
- // John:
- // We still want valid times so frames will get a delta-time
- // and allow operation with a joypad when the sensor isn't
- // connected.
- ss.Recorded.TimeInSeconds = absTime;
- ss.Predicted.TimeInSeconds = absTime;
+ ss.StatusFlags = 0;
}
- ss.StatusFlags |= ovrStatus_HmdConnected;
return ss;
}
-
-bool HMDState::checkCreateSensor()
+void HMDState::SetEnabledHmdCaps(unsigned hmdCaps)
{
- if (!(SensorStarted && !SensorCreated && AddSensorCount))
- return false;
+ if (OurHMDInfo.HmdType < HmdType_DK2)
+ {
+ // disable low persistence
+ hmdCaps &= ~ovrHmdCap_LowPersistence;
- Lock::Locker lockScope(&DevicesLock);
+ // disable dynamic prediction using the internal latency tester
+ hmdCaps &= ~ovrHmdCap_DynamicPrediction;
+ }
- // Re-check condition once in the lock, in case the state changed.
- if (SensorStarted && !SensorCreated && AddSensorCount)
- {
- if (pHMD)
+ if (OurHMDInfo.HmdType >= HmdType_DK2)
+ {
+ if ((EnabledHmdCaps ^ hmdCaps) & ovrHmdCap_DynamicPrediction)
{
- AddSensorCount = 0;
- pSensor = *pHMD->GetSensor();
+ // DynamicPrediction change
+ TimeManager.ResetFrameTiming(TimeManager.GetFrameTiming().FrameIndex,
+ (hmdCaps & ovrHmdCap_DynamicPrediction) ? true : false,
+ RenderingConfigured);
}
+ }
- if (pSensor)
- {
- pSensor->SetReportRate(500);
- SFusion.AttachToSensor(pSensor);
- SFusion.SetYawCorrectionEnabled((SensorCaps & ovrSensorCap_YawCorrection) != 0);
- applyProfileToSensorFusion();
-
-#ifdef OVR_CAPI_VISIONSUPPORT
- if (SensorCaps & ovrSensorCap_Position)
- {
- pPoseTracker = new Vision::PoseTracker(SFusion);
- if (pPoseTracker)
- {
- pPoseTracker->AssociateHMD(pSensor);
- }
- LogText("Sensor Pose tracker created.\n");
- }
-#endif // OVR_CAPI_VISION_CODE
-
- LogText("Sensor created.\n");
+ if ((EnabledHmdCaps ^ hmdCaps) & ovrHmdCap_NoVSync)
+ {
+ TimeManager.SetVsync((hmdCaps & ovrHmdCap_NoVSync) ? false : true);
+ }
- SensorCreated = true;
- return true;
+ if ((EnabledHmdCaps ^ hmdCaps) & ovrHmdCap_NoMirrorToWindow)
+ {
+#ifdef OVR_OS_WIN32
+ Win32::DisplayShim::GetInstance().UseMirroring = (hmdCaps & ovrHmdCap_NoMirrorToWindow) ?
+ false : true;
+ if (pWindow)
+ { // Force window repaint so that stale mirrored image doesn't persist.
+ ::InvalidateRect((HWND)pWindow, 0, true);
}
+#endif
}
- return SensorCreated;
-}
-
-bool HMDState::GetSensorDesc(ovrSensorDesc* descOut)
-{
- Lock::Locker lockScope(&DevicesLock);
+ // TBD: Should this include be only the rendering flags? Otherwise, bits that failed
+ // modification in Hmd_SetEnabledCaps may mis-match...
+ EnabledHmdCaps = hmdCaps & ovrHmdCap_Writable_Mask;
+ RenderState.EnabledHmdCaps = EnabledHmdCaps;
- if (SensorCreated)
- {
- OVR_ASSERT(pSensor);
- OVR::SensorInfo si;
- pSensor->GetDeviceInfo(&si);
- descOut->VendorId = si.VendorId;
- descOut->ProductId = si.ProductId;
- OVR_ASSERT(si.SerialNumber.GetSize() <= sizeof(descOut->SerialNumber));
- OVR_strcpy(descOut->SerialNumber, sizeof(descOut->SerialNumber), si.SerialNumber.ToCStr());
- return true;
- }
- return false;
-}
+ // If any of the modifiable service caps changed, call on the service.
+ unsigned prevServiceCaps = EnabledServiceHmdCaps & ovrHmdCap_Writable_Mask;
+ unsigned newServiceCaps = hmdCaps & ovrHmdCap_Writable_Mask & ovrHmdCap_Service_Mask;
-void HMDState::applyProfileToSensorFusion()
-{
- if (!pHMD)
- return;
- Profile* profile = pHMD->GetProfile();
- if (!profile)
- {
- OVR_ASSERT(false);
- return;
+ if (prevServiceCaps ^ newServiceCaps)
+ {
+ EnabledServiceHmdCaps = pClient ? pClient->Hmd_SetEnabledCaps(NetId, newServiceCaps)
+ : newServiceCaps;
}
- SFusion.SetUserHeadDimensions ( *profile, RenderState.RenderInfo );
}
-void HMDState::updateLowPersistenceMode(bool lowPersistence) const
-{
- OVR_ASSERT(pSensor);
- DisplayReport dr;
-
- if (pSensor.GetPtr())
- {
- pSensor->GetDisplayReport(&dr);
- dr.Persistence = (UInt16) (dr.TotalRows * (lowPersistence ? 0.18f : 1.0f));
- dr.Brightness = lowPersistence ? 255 : 0;
+unsigned HMDState::SetEnabledHmdCaps()
+{
+ unsigned serviceCaps = pClient ? pClient->Hmd_GetEnabledCaps(NetId) :
+ EnabledServiceHmdCaps;
- pSensor->SetDisplayReport(dr);
- }
+ return serviceCaps & ((~ovrHmdCap_Service_Mask) | EnabledHmdCaps);
}
-void HMDState::updateLatencyTestForHmd(bool latencyTesting)
-{
- if (pSensor.GetPtr())
- {
- DisplayReport dr;
- pSensor->GetDisplayReport(&dr);
- dr.ReadPixel = latencyTesting;
+//-------------------------------------------------------------------------------------
+// ***** Property Access
- pSensor->SetDisplayReport(dr);
- }
+// FIXME: Remove the EGetBoolValue stuff and do it with a "Server:" prefix, so we do not
+// need to keep a white-list of keys. This is also way cool because it allows us to add
+// new settings keys from outside CAPI that can modify internal server data.
- if (latencyTesting)
+bool HMDState::getBoolValue(const char* propertyName, bool defaultVal)
+{
+ if (NetSessionCommon::IsServiceProperty(NetSessionCommon::EGetBoolValue, propertyName))
{
- LatencyUtil2.SetSensorDevice(pSensor.GetPtr());
+ return NetClient::GetInstance()->GetBoolValue(GetNetId(), propertyName, defaultVal);
}
- else
+ else if (pProfile)
{
- LatencyUtil2.SetSensorDevice(NULL);
+ return pProfile->GetBoolValue(propertyName, defaultVal);
}
+ return defaultVal;
}
-
-void HMDState::updateDK2FeaturesTiedToSensor(bool sensorCreatedJustNow)
+bool HMDState::setBoolValue(const char* propertyName, bool value)
{
- Lock::Locker lockScope(&DevicesLock);
-
- if (!SensorCreated || (HMDInfo.HmdType != HmdType_DK2))
- return;
+ NetClient::GetInstance()->SetBoolValue(GetNetId(), propertyName, value);
+ return true;
+}
- // Only send display reports if state changed or sensor initializing first time.
- if (sensorCreatedJustNow ||
- ((HmdCapsAppliedToSensor ^ EnabledHmdCaps) & ovrHmdCap_LowPersistence))
+int HMDState::getIntValue(const char* propertyName, int defaultVal)
+{
+ if (NetSessionCommon::IsServiceProperty(NetSessionCommon::EGetIntValue, propertyName))
{
- updateLowPersistenceMode((EnabledHmdCaps & ovrHmdCap_LowPersistence) ? true : false);
+ return NetClient::GetInstance()->GetIntValue(GetNetId(), propertyName, defaultVal);
}
-
- if (sensorCreatedJustNow || ((HmdCapsAppliedToSensor ^ EnabledHmdCaps) & ovrHmdCap_LatencyTest))
+ else if (pProfile)
{
- updateLatencyTestForHmd((EnabledHmdCaps & ovrHmdCap_LatencyTest) != 0);
+ return pProfile->GetIntValue(propertyName, defaultVal);
}
-
- HmdCapsAppliedToSensor = EnabledHmdCaps & (ovrHmdCap_LowPersistence|ovrHmdCap_LatencyTest);
+ return defaultVal;
}
+bool HMDState::setIntValue(const char* propertyName, int value)
+{
+ NetClient::GetInstance()->SetIntValue(GetNetId(), propertyName, value);
+ return true;
+}
-
-void HMDState::SetEnabledHmdCaps(unsigned hmdCaps)
+float HMDState::getFloatValue(const char* propertyName, float defaultVal)
{
-
- if (HMDInfo.HmdType == HmdType_DK2)
+ if (OVR_strcmp(propertyName, "LensSeparation") == 0)
{
- if ((EnabledHmdCaps ^ hmdCaps) & ovrHmdCap_DynamicPrediction)
- {
- // DynamicPrediction change
- TimeManager.ResetFrameTiming(TimeManager.GetFrameTiming().FrameIndex,
- (hmdCaps & ovrHmdCap_DynamicPrediction) ? true : false,
- RenderingConfigured);
- }
+ return OurHMDInfo.LensSeparationInMeters;
}
-
- if ((EnabledHmdCaps ^ hmdCaps) & ovrHmdCap_NoVSync)
+ else if (OVR_strcmp(propertyName, "VsyncToNextVsync") == 0)
{
- TimeManager.SetVsync((hmdCaps & ovrHmdCap_NoVSync) ? false : true);
+ return OurHMDInfo.Shutter.VsyncToNextVsync;
}
-
-
- EnabledHmdCaps = hmdCaps & ovrHmdCap_Writable_Mask;
- RenderState.EnabledHmdCaps = EnabledHmdCaps;
-
- // Unfortunately, LowPersistance and other flags are tied to sensor.
- // This flag will apply the state of sensor is created; otherwise this will be delayed
- // till StartSensor.
- // Such behavior is less then ideal, but should be resolved with the service model.
-
- updateDK2FeaturesTiedToSensor(false);
-}
-
-
-//-------------------------------------------------------------------------------------
-// ***** Property Access
-
-// TBD: This all needs to be cleaned up and organized into namespaces.
-
-float HMDState::getFloatValue(const char* propertyName, float defaultVal)
-{
- if (OVR_strcmp(propertyName, "LensSeparation") == 0)
- {
- return HMDInfo.LensSeparationInMeters;
- }
- else if (OVR_strcmp(propertyName, "CenterPupilDepth") == 0)
- {
- return SFusion.GetCenterPupilDepth();
+ else if (OVR_strcmp(propertyName, "PixelPersistence") == 0)
+ {
+ return OurHMDInfo.Shutter.PixelPersistence;
}
- else if (pHMD)
- {
- Profile* p = pHMD->GetProfile();
- if (p)
- {
- return p->GetFloatValue(propertyName, defaultVal);
- }
- }
- return defaultVal;
+ else if (NetSessionCommon::IsServiceProperty(NetSessionCommon::EGetNumberValue, propertyName))
+ {
+ return (float)NetClient::GetInstance()->GetNumberValue(GetNetId(), propertyName, defaultVal);
+ }
+ else if (pProfile)
+ {
+ return pProfile->GetFloatValue(propertyName, defaultVal);
+ }
+
+ return defaultVal;
}
bool HMDState::setFloatValue(const char* propertyName, float value)
{
- if (OVR_strcmp(propertyName, "CenterPupilDepth") == 0)
- {
- SFusion.SetCenterPupilDepth(value);
- return true;
- }
- return false;
+ NetClient::GetInstance()->SetNumberValue(GetNetId(), propertyName, value);
+ return true;
}
-
static unsigned CopyFloatArrayWithLimit(float dest[], unsigned destSize,
float source[], unsigned sourceSize)
{
@@ -523,14 +424,13 @@ static unsigned CopyFloatArrayWithLimit(float dest[], unsigned destSize,
return count;
}
-
unsigned HMDState::getFloatArray(const char* propertyName, float values[], unsigned arraySize)
{
if (arraySize)
{
if (OVR_strcmp(propertyName, "ScreenSize") == 0)
{
- float data[2] = { HMDInfo.ScreenSizeInMeters.w, HMDInfo.ScreenSizeInMeters.h };
+ float data[2] = { OurHMDInfo.ScreenSizeInMeters.w, OurHMDInfo.ScreenSizeInMeters.h };
return CopyFloatArrayWithLimit(values, arraySize, data, 2);
}
@@ -540,38 +440,44 @@ unsigned HMDState::getFloatArray(const char* propertyName, float values[], unsig
}
else if (OVR_strcmp(propertyName, "DK2Latency") == 0)
{
- if (HMDInfo.HmdType != HmdType_DK2)
+ if (OurHMDInfo.HmdType != HmdType_DK2)
+ {
return 0;
+ }
float data[3];
TimeManager.GetLatencyTimings(data);
return CopyFloatArrayWithLimit(values, arraySize, data, 3);
}
-
- /*
- else if (OVR_strcmp(propertyName, "CenterPupilDepth") == 0)
+ else if (NetSessionCommon::IsServiceProperty(NetSessionCommon::EGetNumberValues, propertyName))
{
- if (arraySize >= 1)
+ // Convert floats to doubles
+ double* da = new double[arraySize];
+ for (int i = 0; i < (int)arraySize; ++i)
{
- values[0] = SFusion.GetCenterPupilDepth();
- return 1;
+ da[i] = values[i];
}
- return 0;
- } */
- else if (pHMD)
- {
- Profile* p = pHMD->GetProfile();
+ int count = NetClient::GetInstance()->GetNumberValues(GetNetId(), propertyName, da, (int)arraySize);
+
+ for (int i = 0; i < count; ++i)
+ {
+ values[i] = (float)da[i];
+ }
+
+ delete[] da;
+
+ return count;
+ }
+ else if (pProfile)
+ {
// TBD: Not quite right. Should update profile interface, so that
// we can return 0 in all conditions if property doesn't exist.
- if (p)
- {
- unsigned count = p->GetFloatValues(propertyName, values, arraySize);
- return count;
+
+ return pProfile->GetFloatValues(propertyName, values, arraySize);
}
}
- }
return 0;
}
@@ -579,26 +485,40 @@ unsigned HMDState::getFloatArray(const char* propertyName, float values[], unsig
bool HMDState::setFloatArray(const char* propertyName, float values[], unsigned arraySize)
{
if (!arraySize)
+ {
return false;
+ }
if (OVR_strcmp(propertyName, "DistortionClearColor") == 0)
{
CopyFloatArrayWithLimit(RenderState.ClearColor, 4, values, arraySize);
return true;
}
- return false;
-}
+ double* da = new double[arraySize];
+ for (int i = 0; i < (int)arraySize; ++i)
+ {
+ da[i] = values[i];
+ }
+
+ NetClient::GetInstance()->SetNumberValues(GetNetId(), propertyName, da, arraySize);
+
+ delete[] da;
+
+ return true;
+}
const char* HMDState::getString(const char* propertyName, const char* defaultVal)
{
- if (pHMD)
- {
- // For now, just access the profile.
- Profile* p = pHMD->GetProfile();
+ if (NetSessionCommon::IsServiceProperty(NetSessionCommon::EGetStringValue, propertyName))
+ {
+ return NetClient::GetInstance()->GetStringValue(GetNetId(), propertyName, defaultVal);
+ }
+ if (pProfile)
+ {
LastGetStringValue[0] = 0;
- if (p && p->GetValue(propertyName, LastGetStringValue, sizeof(LastGetStringValue)))
+ if (pProfile->GetValue(propertyName, LastGetStringValue, sizeof(LastGetStringValue)))
{
return LastGetStringValue;
}
@@ -607,13 +527,23 @@ const char* HMDState::getString(const char* propertyName, const char* defaultVal
return defaultVal;
}
+bool HMDState::setString(const char* propertyName, const char* value)
+{
+ NetClient::GetInstance()->SetStringValue(GetNetId(), propertyName, value);
+ return true;
+}
+
+
//-------------------------------------------------------------------------------------
// *** Latency Test
bool HMDState::ProcessLatencyTest(unsigned char rgbColorOut[3])
-{
+{
bool result = false;
+ result = NetClient::GetInstance()->LatencyUtil_ProcessInputs(Timer::GetSeconds(), rgbColorOut);
+
+#if 0 //def ENABLE_LATENCY_TESTER
// Check create.
if (pLatencyTester)
{
@@ -640,20 +570,22 @@ bool HMDState::ProcessLatencyTest(unsigned char rgbColorOut[3])
// This might have some unlikely race condition issue which could cause us to miss a device...
AddLatencyTestCount = 0;
- pLatencyTester = *GlobalState::pInstance->GetManager()->
- EnumerateDevices<LatencyTestDevice>().CreateDevice();
+ pLatencyTester = *GlobalState::pInstance->GetManager()->EnumerateDevices<LatencyTestDevice>().CreateDevice();
if (pLatencyTester)
{
LatencyUtil.SetDevice(pLatencyTester);
LogText("LATENCY TESTER connected\n");
}
}
+#endif
return result;
}
void HMDState::ProcessLatencyTest2(unsigned char rgbColorOut[3], double startTime)
{
+ OVR_UNUSED2(rgbColorOut, startTime);
+ /*
// Check create.
if (!(EnabledHmdCaps & ovrHmdCap_LatencyTest))
return;
@@ -693,6 +625,7 @@ void HMDState::ProcessLatencyTest2(unsigned char rgbColorOut[3], double startTim
{
LatencyTest2Active = false;
}
+ */
}
//-------------------------------------------------------------------------------------
@@ -708,6 +641,12 @@ bool HMDState::ConfigureRendering(ovrEyeRenderDesc eyeRenderDescOut[2],
// null -> shut down.
if (!apiConfig)
{
+ if (pHSWDisplay)
+ {
+ pHSWDisplay->Shutdown();
+ pHSWDisplay.Clear();
+ }
+
if (pRenderer)
pRenderer.Clear();
RenderingConfigured = false;
@@ -718,15 +657,25 @@ bool HMDState::ConfigureRendering(ovrEyeRenderDesc eyeRenderDescOut[2],
(apiConfig->Header.API != pRenderer->GetRenderAPI()))
{
// Shutdown old renderer.
+ if (pHSWDisplay)
+ {
+ pHSWDisplay->Shutdown();
+ pHSWDisplay.Clear();
+ }
+
if (pRenderer)
pRenderer.Clear();
}
+ distortionCaps = distortionCaps & pHmdDesc->DistortionCaps;
// Step 1: do basic setup configuration
- RenderState.setupRenderDesc(eyeRenderDescOut, eyeFovIn);
RenderState.EnabledHmdCaps = EnabledHmdCaps; // This is a copy... Any cleaner way?
RenderState.DistortionCaps = distortionCaps;
+ RenderState.EyeRenderDesc[0] = RenderState.CalcRenderDesc(ovrEye_Left, eyeFovIn[0]);
+ RenderState.EyeRenderDesc[1] = RenderState.CalcRenderDesc(ovrEye_Right, eyeFovIn[1]);
+ eyeRenderDescOut[0] = RenderState.EyeRenderDesc[0];
+ eyeRenderDescOut[1] = RenderState.EyeRenderDesc[1];
TimeManager.ResetFrameTiming(0,
(EnabledHmdCaps & ovrHmdCap_DynamicPrediction) ? true : false,
@@ -740,7 +689,7 @@ bool HMDState::ConfigureRendering(ovrEyeRenderDesc eyeRenderDescOut[2],
if (!pRenderer)
{
pRenderer = *DistortionRenderer::APICreateRegistry
- [apiConfig->Header.API](this, TimeManager, RenderState);
+ [apiConfig->Header.API](pHmdDesc, TimeManager, RenderState);
}
if (!pRenderer ||
@@ -750,55 +699,96 @@ bool HMDState::ConfigureRendering(ovrEyeRenderDesc eyeRenderDescOut[2],
return false;
}
+ // Setup the Health and Safety Warning display system.
+ if(pHSWDisplay && (pHSWDisplay->GetRenderAPIType() != apiConfig->Header.API)) // If we need to reconstruct the HSWDisplay for a different graphics API type, delete the existing display.
+ {
+ pHSWDisplay->Shutdown();
+ pHSWDisplay.Clear();
+ }
+
+ if(!pHSWDisplay) // Use * below because that for of operator= causes it to inherit the refcount the factory gave the object.
+ pHSWDisplay = *OVR::CAPI::HSWDisplay::Factory(apiConfig->Header.API, pHmdDesc, RenderState);
+
+ if (pHSWDisplay)
+ pHSWDisplay->Initialize(apiConfig); // This is potentially re-initializing it with a new config.
+
return true;
}
-
-ovrPosef HMDState::BeginEyeRender(ovrEyeType eye)
+void HMDState::SubmitEyeTextures(const ovrPosef renderPose[2],
+ const ovrTexture eyeTexture[2])
{
- // Debug checks.
- checkBeginFrameScope("ovrHmd_BeginEyeRender");
- ThreadChecker::Scope checkScope(&RenderAPIThreadChecker, "ovrHmd_BeginEyeRender");
+ RenderState.EyeRenderPoses[0] = renderPose[0];
+ RenderState.EyeRenderPoses[1] = renderPose[1];
- // Unknown eyeId provided in ovrHmd_BeginEyeRender
- OVR_ASSERT_LOG(eye == ovrEye_Left || eye == ovrEye_Right,
- ("ovrHmd_BeginEyeRender eyeId out of range."));
- OVR_ASSERT_LOG(EyeRenderActive[eye] == false,
- ("Multiple calls to ovrHmd_BeginEyeRender for the same eye."));
-
- EyeRenderActive[eye] = true;
-
- // Only process latency tester for drawing the left eye (assumes left eye is drawn first)
- if (pRenderer && eye == 0)
+ if (pRenderer)
{
- LatencyTestActive = ProcessLatencyTest(LatencyTestDrawColor);
+ pRenderer->SubmitEye(0, &eyeTexture[0]);
+ pRenderer->SubmitEye(1, &eyeTexture[1]);
}
-
- return ovrHmd_GetEyePose(this, eye);
}
-void HMDState::EndEyeRender(ovrEyeType eye, ovrPosef renderPose, ovrTexture* eyeTexture)
+// I appreciate this is not an idea place for this function, but it didn't seem to be
+// being linked properly when in OVR_CAPI.cpp.
+// Please relocate if you know of a better place
+ovrBool ovrHmd_CreateDistortionMeshInternal( ovrHmdStruct * hmd,
+ ovrEyeType eyeType, ovrFovPort fov,
+ unsigned int distortionCaps,
+ ovrDistortionMesh *meshData,
+ float overrideEyeReliefIfNonZero )
{
- // Debug checks.
- checkBeginFrameScope("ovrHmd_EndEyeRender");
- ThreadChecker::Scope checkScope(&RenderAPIThreadChecker, "ovrHmd_EndEyeRender");
+ if (!meshData)
+ return 0;
+ HMDState* hmds = (HMDState*)hmd;
+
+ // Not used now, but Chromatic flag or others could possibly be checked for in the future.
+ OVR_UNUSED1(distortionCaps);
+
+#if defined (OVR_OS_WIN32)
+ OVR_COMPILER_ASSERT(sizeof(DistortionMeshVertexData) == sizeof(ovrDistortionVertex));
+#endif
+
+ // *** Calculate a part of "StereoParams" needed for mesh generation
+
+ // Note that mesh distortion generation is invariant of RenderTarget UVs, allowing
+ // render target size and location to be changed after the fact dynamically.
+ // eyeToSourceUV is computed here for convenience, so that users don't need
+ // to call ovrHmd_GetRenderScaleAndOffset unless changing RT dynamically.
+
+ const HmdRenderInfo& hmdri = hmds->RenderState.RenderInfo;
+ StereoEye stereoEye = (eyeType == ovrEye_Left) ? StereoEye_Left : StereoEye_Right;
+
+ DistortionRenderDesc& distortion = hmds->RenderState.Distortion[eyeType];
+ if (overrideEyeReliefIfNonZero)
+ {
+ distortion.Lens = GenerateLensConfigFromEyeRelief(overrideEyeReliefIfNonZero,hmdri);
+ }
- if (!EyeRenderActive[eye])
+ // Find the mapping from TanAngle space to target NDC space.
+ ScaleAndOffset2D eyeToSourceNDC = CreateNDCScaleAndOffsetFromFov(fov);
+
+ int triangleCount = 0;
+ int vertexCount = 0;
+
+ DistortionMeshCreate((DistortionMeshVertexData**)&meshData->pVertexData,
+ (uint16_t**)&meshData->pIndexData,
+ &vertexCount, &triangleCount,
+ (stereoEye == StereoEye_Right),
+ hmdri, distortion, eyeToSourceNDC);
+
+ if (meshData->pVertexData)
{
- OVR_ASSERT_LOG(false,
- ("ovrHmd_EndEyeRender called without ovrHmd_BeginEyeRender."));
- return;
+ // Convert to index
+ meshData->IndexCount = triangleCount * 3;
+ meshData->VertexCount = vertexCount;
+ return 1;
}
- RenderState.EyeRenderPoses[eye] = renderPose;
+ return 0;
+}
- if (pRenderer)
- pRenderer->SubmitEye(eye, eyeTexture);
- EyeRenderActive[eye] = false;
-}
}} // namespace OVR::CAPI
-