OVR_EXPORT ovrBool ovrHmd_AttachToWindow( ovrHmd hmd, void* window, const ovrRecti* destMirrorRect, const ovrRecti* sourceRenderTargetRect ) { OVR_UNUSED( destMirrorRect ); OVR_UNUSED( sourceRenderTargetRect ); if (!CAPI_ovrInitializeCalled) return false; 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 #ifdef OVR_OS_WIN32 Win32::DisplayShim::GetInstance().hWindow = (HWND)window; #endif #ifdef OVR_OS_MAC OVR_UNUSED(window); #endif return true; }
OVR_EXPORT void ovrHmd_EndEyeRender(ovrHmd hmd, ovrEyeType eye, ovrPosef renderPose, ovrTexture* eyeTexture) { HMDState* hmds = (HMDState*)hmd; if (!hmds) return; hmds->EndEyeRender(eye, renderPose, eyeTexture); }
// Returns HSWDisplayTimeNever (0) if there is no profile or this is the first time we are seeing this profile. time_t HSWDisplay::GetCurrentProfileLastHSWTime() const { // We store the timeout value in HMDState's pProfile. HMDState* pHMDState = (HMDState*)HMD->Handle; if (pHMDState) { const char* profileName = pHMDState->pProfile ? pHMDState->pProfile->GetValue(OVR_KEY_USER) : NULL; if (profileName) { if (LastProfileName == profileName) { return LastHSWTime; } LastProfileName = profileName; String timeKey = getHSWTimeKey(profileName); int lastTime = pHMDState->getIntValue(timeKey.ToCStr(), (int)HSWDisplayTimeNever); LastHSWTime = lastTime; return lastTime; } } return HSWDisplayTimeNever; }
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)) { OVR_DEBUG_LOG(("[HMDState] Unable to get HMD info")); return nullptr; } #if !defined(HEADLESS_APP) #ifdef OVR_OS_WIN32 OVR_DEBUG_LOG(("[HMDState] Setting up display shim")); // 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 #endif /* !defined(HEADLESS_APP) */ Ptr<Profile> pDefaultProfile = *ProfileManager::GetInstance()->GetDefaultUserProfile(&hinfo); OVR_DEBUG_LOG(("[HMDState] Using profile %s", pDefaultProfile->GetValue(OVR_KEY_USER))); HMDState* hmds = new HMDState(hinfo, pDefaultProfile, &netInfo, client); if (!hmds->InitializeSharedState()) { delete hmds; return nullptr; } return hmds; }
OVR_EXPORT ovrPosef ovrHmd_GetEyePose(ovrHmd hmd, ovrEyeType eye) { HMDState* hmds = (HMDState*)hmd; if (!hmds) return ovrPosef(); hmds->checkBeginFrameTimingScope("ovrHmd_GetEyePose"); return hmds->TimeManager.GetEyePredictionPose(hmd, eye); }
// Modifies capability bits described by ovrHmdCapBits that can be modified, // such as ovrHmdCap_LowPersistance. OVR_EXPORT void ovrHmd_SetEnabledCaps(ovrHmd hmddesc, unsigned int capsBits) { HMDState* p = (HMDState*)hmddesc->Handle; if (p) { p->SetEnabledHmdCaps(capsBits); } }
OVR_EXPORT ovrBool ovrHmd_SetFloat(ovrHmd hmd, const char* propertyName, float value) { HMDState* hmds = (HMDState*)hmd; if (hmds) { return hmds->setFloatValue(propertyName, value); } return false; }
OVR_EXPORT void ovrHmd_AddDistortionTimeMeasurement(ovrHmd hmddesc, double distortionTimeSeconds) { if (!hmddesc) return; HMDState* hmds = (HMDState*)hmddesc->Handle; hmds->checkBeginFrameTimingScope("ovrHmd_GetTimewarpEyeMatrices"); hmds->TimeManager.AddDistortionTimeMeasurement(distortionTimeSeconds); }
OVR_EXPORT float ovrHmd_GetFloat(ovrHmd hmd, const char* propertyName, float defaultVal) { HMDState* hmds = (HMDState*)hmd; if (hmds) { return hmds->getFloatValue(propertyName, defaultVal); } return defaultVal; }
OVR_EXPORT ovrBool ovrHmd_SetBool(ovrHmd hmddesc, const char* propertyName, ovrBool value) { OVR_ASSERT(hmddesc && propertyName); HMDState* hmds = (HMDState*)hmddesc->Handle; if (hmds) { return hmds->setBoolValue(propertyName, value != 0) ? 1 : 0; } return false; }
OVR_EXPORT const char* ovrHmd_GetString(ovrHmd hmd, const char* propertyName, const char* defaultVal) { HMDState* hmds = (HMDState*)hmd; if (hmds) { return hmds->getString(propertyName, defaultVal); } return defaultVal; }
OVR_EXPORT ovrBool ovrHmd_ConfigureTracking(ovrHmd hmddesc, unsigned int supportedCaps, unsigned int requiredCaps) { if (hmddesc) { HMDState* p = (HMDState*)hmddesc->Handle; return p->ConfigureTracking(supportedCaps, requiredCaps); } return 0; }
// Modify float[] property; false if property doesn't exist or is readonly. OVR_EXPORT ovrBool ovrHmd_SetFloatArray(ovrHmd hmd, const char* propertyName, float values[], unsigned int arraySize) { HMDState* hmds = (HMDState*)hmd; if (hmds) { return hmds->setFloatArray(propertyName, values, arraySize); } return 0; }
// Renders textures to frame buffer OVR_EXPORT void ovrHmd_EndFrame(ovrHmd hmddesc, const ovrPosef renderPose[2], const ovrTexture eyeTexture[2]) { HMDState* hmds = (HMDState*)hmddesc->Handle; if (!hmds) return; // Instrument when the EndFrame() call started hmds->LagStats.InstrumentEndFrameStart(ovr_GetTimeInSeconds()); hmds->SubmitEyeTextures(renderPose, eyeTexture); // 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); ovrHmd_GetLatencyTest2DrawColor(hmddesc, NULL); // We don't actually need to draw color, so send NULL if (hmds->pRenderer) { hmds->pRenderer->SaveGraphicsState(); // See if we need to show the HSWDisplay. if (hmds->pHSWDisplay) // Until we know that these are valid, assume any of them can't be. { ovrHSWDisplayState hswDisplayState; hmds->pHSWDisplay->TickState(&hswDisplayState, true); // This may internally call HASWarning::Display. if (hswDisplayState.Displayed) { hmds->pHSWDisplay->Render(ovrEye_Left, &eyeTexture[ovrEye_Left]); hmds->pHSWDisplay->Render(ovrEye_Right, &eyeTexture[ovrEye_Right]); } } hmds->pRenderer->EndFrame(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()); // Out of BeginFrame hmds->BeginFrameThreadId = 0; hmds->BeginFrameCalled = false; }
OVR_EXPORT int ovrHmd_GetInt(ovrHmd hmddesc, const char* propertyName, int defaultVal) { OVR_ASSERT(hmddesc && propertyName); HMDState* hmds = (HMDState*)hmddesc->Handle; if (hmds) { return hmds->getIntValue(propertyName, defaultVal); } return defaultVal; }
OVR_EXPORT const char* ovrHmd_GetLastError(ovrHmd hmd) { using namespace OVR; if (!hmd) { if (!GlobalState::pInstance) return "LibOVR not initialized."; return GlobalState::pInstance->GetLastError(); } HMDState* p = (HMDState*)hmd; return p->GetLastError(); }
// ----------------------------------------------------------------------------------- // ***** Property Access OVR_EXPORT ovrBool ovrHmd_GetBool(ovrHmd hmddesc, const char* propertyName, ovrBool defaultVal) { OVR_ASSERT(hmddesc && propertyName); HMDState* hmds = (HMDState*)hmddesc->Handle; if (hmds) { return hmds->getBoolValue(propertyName, (defaultVal != 0)); } return defaultVal; }
OVR_EXPORT const char* ovrHmd_GetString(ovrHmd hmddesc, const char* propertyName, const char* defaultVal) { OVR_ASSERT(hmddesc && propertyName); HMDState* hmds = (HMDState*)hmddesc->Handle; if (hmds) { return hmds->getString(propertyName, defaultVal); } return defaultVal; }
// 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_ASSERT(hmddesc && propertyName); HMDState* hmds = (HMDState*)hmddesc->Handle; if (hmds) { return hmds->setFloatArray(propertyName, values, arraySize); } return 0; }
OVR_EXPORT void ovrHmd_EndFrameTiming(ovrHmd hmddesc) { HMDState* hmds = (HMDState*)hmddesc->Handle; if (!hmds) return; // Debug state checks: Must be in BeginFrameTiming, on the same thread. hmds->checkBeginFrameTimingScope("ovrHmd_EndTiming"); // MA TBD: Correct chek or not? // ThreadChecker::Scope checkScope(&hmds->RenderAPIThreadChecker, "ovrHmd_EndFrame"); hmds->TimeManager.EndFrame(); hmds->BeginFrameTimingCalled = false; }
OVR_EXPORT ovrBool ovrHmd_SetString(ovrHmd hmddesc, const char* propertyName, const char* value) { OVR_ASSERT(hmddesc && propertyName); HMDState* hmds = (HMDState*)hmddesc->Handle; if (hmds) { return hmds->setString(propertyName, value) ? 1 : 0; } return 0; }
ovrPosef ovrHmd_GetHmdPosePerEye(ovrHmd hmd, 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) { hmds->LatencyTestActive = hmds->ProcessLatencyTest(hmds->LatencyTestDrawColor); } hmds->checkBeginFrameTimingScope("ovrHmd_GetEyePose"); return hmds->TimeManager.GetEyePredictionPose(hmd, eye); }
OVR_EXPORT const char* ovrHmd_GetLastError(ovrHmd hmddesc) { if (!CAPI_ovrInitializeCalled) { return "System initialize not called"; } if (hmddesc && hmddesc->Handle) { HMDState* p = (HMDState*)hmddesc->Handle; return CAPI_pNetClient->Hmd_GetLastError(p->GetNetId()); } return "Uninitialized Hmd"; }
OVR_EXPORT ovrBool ovrHmd_SetString(ovrHmd hmddesc, const char* propertyName, const char* value) { OVR_ASSERT(propertyName); if (hmddesc) { HMDState* hmds = (HMDState*)hmddesc->Handle; if (hmds) { return hmds->setString(propertyName, value) ? 1 : 0; } } return NetClient::GetInstance()->SetStringValue(InvalidVirtualHmdId, propertyName, value) ? 1 : 0; }
OVR_EXPORT const char* ovrHmd_GetString(ovrHmd hmddesc, const char* propertyName, const char* defaultVal) { OVR_ASSERT(propertyName); if (hmddesc) { HMDState* hmds = (HMDState*)hmddesc->Handle; if (hmds) { return hmds->getString(propertyName, defaultVal); } } return NetClient::GetInstance()->GetStringValue(InvalidVirtualHmdId, propertyName, defaultVal); }
OVR_EXPORT 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(); } return CAPI_pNetClient->Hmd_GetLastError(netId); }
OVR_EXPORT ovrTrackingState ovrHmd_GetTrackingState(ovrHmd hmddesc, double absTime) { ovrTrackingState result = {0}; if (hmddesc) { HMDState* p = (HMDState*)hmddesc->Handle; result = p->PredictedTrackingState(absTime); } #ifdef OVR_OS_WIN32 // Set up display code for Windows Win32::DisplayShim::GetInstance().Active = (result.StatusFlags & ovrStatus_HmdConnected) != 0; #endif return result; }
// ----------------------------------------------------------------------------------- // ***** Property Access OVR_EXPORT ovrBool ovrHmd_GetBool(ovrHmd hmddesc, const char* propertyName, ovrBool defaultVal) { OVR_ASSERT(propertyName); if (hmddesc) { HMDState* hmds = (HMDState*)hmddesc->Handle; OVR_ASSERT(hmds); if (hmds) { return hmds->getBoolValue(propertyName, (defaultVal != 0)); } } return NetClient::GetInstance()->GetBoolValue(InvalidVirtualHmdId, propertyName, (defaultVal != 0)) ? 1 : 0; }
OVR_EXPORT float ovrHmd_GetFloat(ovrHmd hmddesc, const char* propertyName, float defaultVal) { OVR_ASSERT(propertyName); if (hmddesc) { HMDState* hmds = (HMDState*)hmddesc->Handle; OVR_ASSERT(hmds); if (hmds) { return hmds->getFloatValue(propertyName, defaultVal); } } return (float)NetClient::GetInstance()->GetNumberValue(InvalidVirtualHmdId, propertyName, defaultVal); }
// Renders textures to frame buffer OVR_EXPORT void ovrHmd_EndFrame(ovrHmd hmd) { HMDState* hmds = (HMDState*)hmd; if (!hmds) return; // Debug state checks: Must be in BeginFrame, on the same thread. hmds->checkBeginFrameScope("ovrHmd_EndFrame"); ThreadChecker::Scope checkScope(&hmds->RenderAPIThreadChecker, "ovrHmd_EndFrame"); // TBD: Move directly into renderer bool dk2LatencyTest = (hmds->HMDInfo.HmdType == HmdType_DK2) && (hmds->EnabledHmdCaps & ovrHmdCap_LatencyTest); if (dk2LatencyTest) { hmds->LatencyTest2DrawColor[0] = hmds->TimeManager.GetFrameLatencyTestDrawColor(); hmds->LatencyTest2DrawColor[1] = hmds->LatencyTest2DrawColor[0]; hmds->LatencyTest2DrawColor[2] = hmds->LatencyTest2DrawColor[0]; } if (hmds->pRenderer) { hmds->pRenderer->SaveGraphicsState(); hmds->pRenderer->EndFrame(true, hmds->LatencyTestActive ? hmds->LatencyTestDrawColor : NULL, // MA: Use this color since we are running DK2 test all the time. dk2LatencyTest ? hmds->LatencyTest2DrawColor : 0 //hmds->LatencyTest2Active ? hmds->LatencyTest2DrawColor : NULL ); hmds->pRenderer->RestoreGraphicsState(); } // Call after present ovrHmd_EndFrameTiming(hmd); if (dk2LatencyTest) { hmds->TimeManager.UpdateFrameLatencyTrackingAfterEndFrame( hmds->LatencyTest2DrawColor[0], hmds->LatencyUtil2.GetLocklessState()); } // Out of BeginFrame hmds->BeginFrameThreadId = 0; hmds->BeginFrameCalled = false; }