// 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; }
// 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; 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); // TBD: Move directly into renderer bool dk2LatencyTest = (hmds->EnabledHmdCaps & ovrHmdCap_DynamicPrediction) != 0; if (dk2LatencyTest) { hmds->TimeManager.GetFrameLatencyTestDrawColor(hmds->LatencyTest2DrawColor); hmds->pRenderer->SetLatencyTest2Color(hmds->LatencyTest2DrawColor); } else { hmds->pRenderer->SetLatencyTest2Color(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); // 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); if (dk2LatencyTest) { Util::FrameTimeRecordSet recordset; hmds->TheLatencyTestStateReader.GetRecordSet(recordset); hmds->TimeManager.UpdateFrameLatencyTrackingAfterEndFrame( hmds->LatencyTest2DrawColor, recordset); } // Out of BeginFrame hmds->BeginFrameThreadId = 0; hmds->BeginFrameCalled = false; }