Bike-X  0.8
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
OVR_CAPI.cpp
Go to the documentation of this file.
1 /************************************************************************************
2 
3 Filename : OVR_CAPI.cpp
4 Content : Experimental simple C interface to the HMD - version 1.
5 Created : November 30, 2013
6 Authors : Michael Antonov
7 
8 Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
9 
10 Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
11 you may not use the Oculus VR Rift SDK except in compliance with the License,
12 which is provided at the time of installation or download, or which
13 otherwise accompanies this software in either electronic or hard copy form.
14 
15 You may obtain a copy of the License at
16 
17 http://www.oculusvr.com/licenses/LICENSE-3.1
18 
19 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
20 distributed under the License is distributed on an "AS IS" BASIS,
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 See the License for the specific language governing permissions and
23 limitations under the License.
24 
25 ************************************************************************************/
26 
27 #include "OVR_CAPI.h"
28 #include "Kernel/OVR_Timer.h"
29 #include "Kernel/OVR_Math.h"
30 #include "Kernel/OVR_System.h"
31 #include "OVR_Stereo.h"
32 #include "OVR_Profile.h"
33 
34 #include "CAPI/CAPI_GlobalState.h"
35 #include "CAPI/CAPI_HMDState.h"
37 
38 
39 using namespace OVR;
40 using namespace OVR::Util::Render;
41 
42 //-------------------------------------------------------------------------------------
43 // Math
44 namespace OVR {
45 
46 
47 // ***** FovPort
48 
49 // C-interop support: FovPort <-> ovrFovPort
51  : UpTan(src.UpTan), DownTan(src.DownTan), LeftTan(src.LeftTan), RightTan(src.RightTan)
52 { }
53 
54 FovPort::operator ovrFovPort () const
55 {
56  ovrFovPort result;
57  result.LeftTan = LeftTan;
58  result.RightTan = RightTan;
59  result.UpTan = UpTan;
60  result.DownTan = DownTan;
61  return result;
62 }
63 
64 // Converts Fov Tan angle units to [-1,1] render target NDC space
66 {
67  ScaleAndOffset2D eyeToSourceNDC = CreateNDCScaleAndOffsetFromFov(*this);
68  return tanEyeAngle * eyeToSourceNDC.Scale + eyeToSourceNDC.Offset;
69 }
70 
71 
72 // ***** SensorState
73 
75 {
76  Predicted = s.Predicted;
77  Recorded = s.Recorded;
80 }
81 
82 SensorState::operator ovrSensorState() const
83 {
84  ovrSensorState result;
85  result.Predicted = Predicted;
86  result.Recorded = Recorded;
87  result.Temperature = Temperature;
88  result.StatusFlags = StatusFlags;
89  return result;
90 }
91 
92 
93 } // namespace OVR
94 
95 //-------------------------------------------------------------------------------------
96 
97 using namespace OVR::CAPI;
98 
99 #ifdef __cplusplus
100 extern "C" {
101 #endif
102 
103 
104 // Used to generate projection from ovrEyeDesc::Fov
105 OVR_EXPORT ovrMatrix4f ovrMatrix4f_Projection(ovrFovPort fov, float znear, float zfar, ovrBool rightHanded)
106 {
107  return CreateProjection(rightHanded ? true : false, fov, znear, zfar);
108 }
109 
110 
112  float orthoDistance, float eyeViewAdjustX)
113 {
114 
115  float orthoHorizontalOffset = eyeViewAdjustX / orthoDistance;
116 
117  // Current projection maps real-world vector (x,y,1) to the RT.
118  // We want to find the projection that maps the range [-FovPixels/2,FovPixels/2] to
119  // the physical [-orthoHalfFov,orthoHalfFov]
120  // Note moving the offset from M[0][2]+M[1][2] to M[0][3]+M[1][3] - this means
121  // we don't have to feed in Z=1 all the time.
122  // The horizontal offset math is a little hinky because the destination is
123  // actually [-orthoHalfFov+orthoHorizontalOffset,orthoHalfFov+orthoHorizontalOffset]
124  // So we need to first map [-FovPixels/2,FovPixels/2] to
125  // [-orthoHalfFov+orthoHorizontalOffset,orthoHalfFov+orthoHorizontalOffset]:
126  // x1 = x0 * orthoHalfFov/(FovPixels/2) + orthoHorizontalOffset;
127  // = x0 * 2*orthoHalfFov/FovPixels + orthoHorizontalOffset;
128  // But then we need the sam mapping as the existing projection matrix, i.e.
129  // x2 = x1 * Projection.M[0][0] + Projection.M[0][2];
130  // = x0 * (2*orthoHalfFov/FovPixels + orthoHorizontalOffset) * Projection.M[0][0] + Projection.M[0][2];
131  // = x0 * Projection.M[0][0]*2*orthoHalfFov/FovPixels +
132  // orthoHorizontalOffset*Projection.M[0][0] + Projection.M[0][2];
133  // So in the new projection matrix we need to scale by Projection.M[0][0]*2*orthoHalfFov/FovPixels and
134  // offset by orthoHorizontalOffset*Projection.M[0][0] + Projection.M[0][2].
135 
136  Matrix4f ortho;
137  ortho.M[0][0] = projection.M[0][0] * orthoScale.x;
138  ortho.M[0][1] = 0.0f;
139  ortho.M[0][2] = 0.0f;
140  ortho.M[0][3] = -projection.M[0][2] + ( orthoHorizontalOffset * projection.M[0][0] );
141 
142  ortho.M[1][0] = 0.0f;
143  ortho.M[1][1] = -projection.M[1][1] * orthoScale.y; // Note sign flip (text rendering uses Y=down).
144  ortho.M[1][2] = 0.0f;
145  ortho.M[1][3] = -projection.M[1][2];
146 
147  /*
148  if ( fabsf ( zNear - zFar ) < 0.001f )
149  {
150  ortho.M[2][0] = 0.0f;
151  ortho.M[2][1] = 0.0f;
152  ortho.M[2][2] = 0.0f;
153  ortho.M[2][3] = zFar;
154  }
155  else
156  {
157  ortho.M[2][0] = 0.0f;
158  ortho.M[2][1] = 0.0f;
159  ortho.M[2][2] = zFar / (zNear - zFar);
160  ortho.M[2][3] = (zFar * zNear) / (zNear - zFar);
161  }
162  */
163 
164  // MA: Undo effect of sign
165  ortho.M[2][0] = 0.0f;
166  ortho.M[2][1] = 0.0f;
167  //ortho.M[2][2] = projection.M[2][2] * projection.M[3][2] * -1.0f; // reverse right-handedness
168  ortho.M[2][2] = 0.0f;
169  ortho.M[2][3] = 0.0f;
170  //projection.M[2][3];
171 
172  // No perspective correction for ortho.
173  ortho.M[3][0] = 0.0f;
174  ortho.M[3][1] = 0.0f;
175  ortho.M[3][2] = 0.0f;
176  ortho.M[3][3] = 1.0f;
177 
178  return ortho;
179 }
180 
181 
183 {
184  return Timer::GetSeconds();
185 }
186 
187 // Waits until the specified absolute time.
188 OVR_EXPORT double ovr_WaitTillTime(double absTime)
189 {
190  volatile int i;
191  double initialTime = ovr_GetTimeInSeconds();
192  double newTime = initialTime;
193 
194  while(newTime < absTime)
195  {
196  for (int j = 0; j < 50; j++)
197  i = 0;
198  newTime = ovr_GetTimeInSeconds();
199  }
200 
201  // How long we waited
202  return newTime - initialTime;
203 }
204 
205 //-------------------------------------------------------------------------------------
206 
207 // 1. Init/shutdown.
208 
210 
212 {
214  return 1;
215 
216  // We must set up the system for the plugin to work
218  {
220  CAPI_SystemInitCalled = 1;
221  }
222 
223  // Constructor detects devices
225  return 1;
226 }
227 
229 {
231  return;
232 
233  delete GlobalState::pInstance;
235 
236  // We should clean up the system to be complete
237  if (CAPI_SystemInitCalled)
238  {
240  CAPI_SystemInitCalled = 0;
241  }
242  return;
243 }
244 
245 
246 // There is a thread safety issue with ovrHmd_Detect in that multiple calls from different
247 // threads can corrupt the global array state. This would lead to two problems:
248 // a) Create(index) enumerator may miss or overshoot items. Probably not a big deal
249 // as game logic can easily be written to only do Detect(s)/Creates in one place.
250 // The alternative would be to return list handle.
251 // b) TBD: Un-mutexed Detect access from two threads could lead to crash. We should
252 // probably check this.
253 //
254 
256 {
258  return 0;
260 }
261 
262 
263 // ovrHmd_Create us explicitly separated from StartSensor and Configure to allow creation of
264 // a relatively light-weight handle that would reference the device going forward and would
265 // survive future ovrHmd_Detect calls. That is once ovrHMD is returned, index is no longer
266 // necessary and can be changed by a ovrHmd_Detect call.
267 
269 {
271  return 0;
273  if (!device)
274  return 0;
275 
276  HMDState* hmds = new HMDState(device);
277  if (!hmds)
278  return 0;
279 
280  return hmds;
281 }
282 
284 {
286  return 0;
287 
288  HMDState* hmds = new HMDState(type);
289  return hmds;
290 }
291 
293 {
294  if (!hmd)
295  return;
296  // TBD: Any extra shutdown?
297  HMDState* hmds = (HMDState*)hmd;
298 
299  { // Thread checker in its own scope, to avoid access after 'delete'.
300  // Essentially just checks that no other RenderAPI function is executing.
301  ThreadChecker::Scope checkScope(&hmds->RenderAPIThreadChecker, "ovrHmd_Destroy");
302  }
303 
304  delete (HMDState*)hmd;
305 }
306 
307 
309 {
310  using namespace OVR;
311  if (!hmd)
312  {
314  return "LibOVR not initialized.";
316  }
317  HMDState* p = (HMDState*)hmd;
318  return p->GetLastError();
319 }
320 
321 
322 //-------------------------------------------------------------------------------------
323 
324 // Returns capability bits that are enabled at this time; described by ovrHmdCapBits.
325 // Note that this value is different font ovrHmdDesc::Caps, which describes what
326 // capabilities are available.
328 {
329  HMDState* p = (HMDState*)hmd;
330  return p ? p->EnabledHmdCaps : 0;
331 }
332 
333 // Modifies capability bits described by ovrHmdCapBits that can be modified,
334 // such as ovrHmd_LowPersistance.
335 OVR_EXPORT void ovrHmd_SetEnabledCaps(ovrHmd hmd, unsigned int capsBits)
336 {
337  HMDState* p = (HMDState*)hmd;
338  if (p)
339  p->SetEnabledHmdCaps(capsBits);
340 }
341 
342 
343 //-------------------------------------------------------------------------------------
344 // *** Sensor
345 
346 // Sensor APIs are separated from Create & Configure for several reasons:
347 // - They need custom parameters that control allocation of heavy resources
348 // such as Vision tracking, which you don't want to create unless necessary.
349 // - A game may want to switch some sensor settings based on user input,
350 // or at lease enable/disable features such as Vision for debugging.
351 // - The same or syntactically similar sensor interface is likely to be used if we
352 // introduce controllers.
353 //
354 // - Sensor interface functions are all Thread-safe, unlike the frame/render API
355 // functions that have different rules (all frame access functions
356 // must be on render thread)
357 
358 OVR_EXPORT ovrBool ovrHmd_StartSensor(ovrHmd hmd, unsigned int supportedCaps, unsigned int requiredCaps)
359 {
360  HMDState* p = (HMDState*)hmd;
361  // TBD: Decide if we null-check arguments.
362  return p->StartSensor(supportedCaps, requiredCaps);
363 }
364 
366 {
367  HMDState* p = (HMDState*)hmd;
368  p->StopSensor();
369 }
370 
372 {
373  HMDState* p = (HMDState*)hmd;
374  p->ResetSensor();
375 }
376 
378 {
379  HMDState* p = (HMDState*)hmd;
380  return p->PredictedSensorState(absTime);
381 }
382 
383 // Returns information about a sensor. Only valid after SensorStart.
385 {
386  HMDState* p = (HMDState*)hmd;
387  return p->GetSensorDesc(descOut) ? 1 : 0;
388 }
389 
390 
391 
392 //-------------------------------------------------------------------------------------
393 // *** General Setup
394 
395 
397 {
398  HMDState* hmds = (HMDState*)hmd;
399  *desc = hmds->RenderState.GetDesc();
400  desc->Handle = hmd;
401 }
402 
403 // Per HMD -> calculateIdealPixelSize
405  float pixelsPerDisplayPixel)
406 {
407  if (!hmd) return Sizei(0);
408 
409  HMDState* hmds = (HMDState*)hmd;
410  return hmds->RenderState.GetFOVTextureSize(eye, fov, pixelsPerDisplayPixel);
411 }
412 
413 
414 //-------------------------------------------------------------------------------------
415 
416 
417 OVR_EXPORT
419  const ovrRenderAPIConfig* apiConfig,
420  unsigned int distortionCaps,
421  const ovrFovPort eyeFovIn[2],
422  ovrEyeRenderDesc eyeRenderDescOut[2] )
423 {
424  if (!hmd) return 0;
425  return ((HMDState*)hmd)->ConfigureRendering(eyeRenderDescOut, eyeFovIn,
426  apiConfig, distortionCaps);
427 }
428 
429 
430 
431 // TBD: MA - Deprecated, need alternative
433 {
434  if (!hmd) return;
435 
436  return ((HMDState*)hmd)->TimeManager.SetVsync(vsync? true : false);
437 }
438 
439 
440 OVR_EXPORT ovrFrameTiming ovrHmd_BeginFrame(ovrHmd hmd, unsigned int frameIndex)
441 {
442  HMDState* hmds = (HMDState*)hmd;
443  if (!hmds)
444  {
445  ovrFrameTiming f;
446  memset(&f, 0, sizeof(f));
447  return f;
448  }
449 
450  // Check: Proper configure and threading state for the call.
451  hmds->checkRenderingConfigured("ovrHmd_BeginFrame");
452  OVR_ASSERT_LOG(hmds->BeginFrameCalled == false, ("ovrHmd_BeginFrame called multiple times."));
453  ThreadChecker::Scope checkScope(&hmds->RenderAPIThreadChecker, "ovrHmd_BeginFrame");
454 
455  hmds->BeginFrameCalled = true;
457 
458  return ovrHmd_BeginFrameTiming(hmd, frameIndex);
459 }
460 
461 
462 // Renders textures to frame buffer
464 {
465  HMDState* hmds = (HMDState*)hmd;
466  if (!hmds) return;
467 
468  // Debug state checks: Must be in BeginFrame, on the same thread.
469  hmds->checkBeginFrameScope("ovrHmd_EndFrame");
470  ThreadChecker::Scope checkScope(&hmds->RenderAPIThreadChecker, "ovrHmd_EndFrame");
471 
472  // TBD: Move directly into renderer
473  bool dk2LatencyTest = (hmds->HMDInfo.HmdType == HmdType_DK2) &&
475  if (dk2LatencyTest)
476  {
478  hmds->LatencyTest2DrawColor[1] = hmds->LatencyTest2DrawColor[0];
479  hmds->LatencyTest2DrawColor[2] = hmds->LatencyTest2DrawColor[0];
480  }
481 
482  if (hmds->pRenderer)
483  {
484  hmds->pRenderer->SaveGraphicsState();
485  hmds->pRenderer->EndFrame(true,
487 
488  // MA: Use this color since we are running DK2 test all the time.
489  dk2LatencyTest ? hmds->LatencyTest2DrawColor : 0
490  //hmds->LatencyTest2Active ? hmds->LatencyTest2DrawColor : NULL
491  );
492  hmds->pRenderer->RestoreGraphicsState();
493  }
494  // Call after present
496 
497  if (dk2LatencyTest)
498  {
501  }
502 
503  // Out of BeginFrame
504  hmds->BeginFrameThreadId = 0;
505  hmds->BeginFrameCalled = false;
506 }
507 
508 
510 {
511  HMDState* hmds = (HMDState*)hmd;
512  if (!hmds) return ovrPosef();
513  return hmds->BeginEyeRender(eye);
514 }
515 
517  ovrPosef renderPose, ovrTexture* eyeTexture)
518 {
519  HMDState* hmds = (HMDState*)hmd;
520  if (!hmds) return;
521  hmds->EndEyeRender(eye, renderPose, eyeTexture);
522 }
523 
524 
525 //-------------------------------------------------------------------------------------
526 // ***** Frame Timing logic
527 
528 
530 {
531  ovrFrameTiming f;
532  memset(&f, 0, sizeof(f));
533 
534  HMDState* hmds = (HMDState*)hmd;
535  if (hmds)
536  {
537  FrameTimeManager::Timing frameTiming = hmds->TimeManager.GetFrameTiming(frameIndex);
538 
539  f.ThisFrameSeconds = frameTiming.ThisFrameTime;
540  f.NextFrameSeconds = frameTiming.NextFrameTime;
541  f.TimewarpPointSeconds = frameTiming.TimewarpPointTime;
542  f.ScanoutMidpointSeconds= frameTiming.MidpointTime;
543  f.EyeScanoutSeconds[0] = frameTiming.EyeRenderTimes[0];
544  f.EyeScanoutSeconds[1] = frameTiming.EyeRenderTimes[1];
545 
546  // Compute DeltaSeconds.
547  f.DeltaSeconds = (hmds->LastGetFrameTimeSeconds == 0.0f) ? 0.0f :
548  (float) (f.ThisFrameSeconds - hmds->LastFrameTimeSeconds);
550  if (f.DeltaSeconds > 1.0f)
551  f.DeltaSeconds = 1.0f;
552  }
553 
554  return f;
555 }
556 
558 {
559  ovrFrameTiming f;
560  memset(&f, 0, sizeof(f));
561 
562  HMDState* hmds = (HMDState*)hmd;
563  if (!hmds) return f;
564 
565  // Check: Proper state for the call.
566  OVR_ASSERT_LOG(hmds->BeginFrameTimingCalled == false,
567  ("ovrHmd_BeginFrameTiming called multiple times."));
568  hmds->BeginFrameTimingCalled = true;
569 
570  double thisFrameTime = hmds->TimeManager.BeginFrame(frameIndex);
571 
572  const FrameTimeManager::Timing &frameTiming = hmds->TimeManager.GetFrameTiming();
573 
574  f.ThisFrameSeconds = thisFrameTime;
575  f.NextFrameSeconds = frameTiming.NextFrameTime;
576  f.TimewarpPointSeconds = frameTiming.TimewarpPointTime;
577  f.ScanoutMidpointSeconds= frameTiming.MidpointTime;
578  f.EyeScanoutSeconds[0] = frameTiming.EyeRenderTimes[0];
579  f.EyeScanoutSeconds[1] = frameTiming.EyeRenderTimes[1];
580 
581  // Compute DeltaSeconds.
582  f.DeltaSeconds = (hmds->LastFrameTimeSeconds == 0.0f) ? 0.0f :
583  (float) (thisFrameTime - hmds->LastFrameTimeSeconds);
584  hmds->LastFrameTimeSeconds = thisFrameTime;
585  if (f.DeltaSeconds > 1.0f)
586  f.DeltaSeconds = 1.0f;
587 
588  return f;
589 }
590 
591 
593 {
594  HMDState* hmds = (HMDState*)hmd;
595  if (!hmds) return;
596 
597  // Debug state checks: Must be in BeginFrameTiming, on the same thread.
598  hmds->checkBeginFrameTimingScope("ovrHmd_EndTiming");
599  // MA TBD: Correct chek or not?
600  // ThreadChecker::Scope checkScope(&hmds->RenderAPIThreadChecker, "ovrHmd_EndFrame");
601 
602  hmds->TimeManager.EndFrame();
603  hmds->BeginFrameTimingCalled = false;
604 }
605 
606 
607 OVR_EXPORT void ovrHmd_ResetFrameTiming(ovrHmd hmd, unsigned int frameIndex)
608 {
609  HMDState* hmds = (HMDState*)hmd;
610  if (!hmds) return;
611 
612  hmds->TimeManager.ResetFrameTiming(frameIndex,
613  false,
614  hmds->RenderingConfigured);
615  hmds->LastFrameTimeSeconds = 0.0;
616  hmds->LastGetFrameTimeSeconds = 0.0;
617 }
618 
619 
620 
622 {
623  HMDState* hmds = (HMDState*)hmd;
624  if (!hmds) return ovrPosef();
625 
626  hmds->checkBeginFrameTimingScope("ovrHmd_GetEyePose");
627  return hmds->TimeManager.GetEyePredictionPose(hmd, eye);
628 }
629 
630 
632  ovrPosef renderPose, ovrMatrix4f twmOut[2])
633 {
634  HMDState* hmds = (HMDState*)hmd;
635  if (!hmd)
636  return;
637 
638  // Debug checks: BeginFrame was called, on the same thread.
639  hmds->checkBeginFrameTimingScope("ovrHmd_GetTimewarpEyeMatrices");
640 
641  hmds->TimeManager.GetTimewarpMatrices(hmd, eye, renderPose, twmOut);
642 
643  /*
644  // MA: Took this out because new latency test approach just sames
645  // the sample times in FrameTimeManager.
646  // TODO: if no timewarp, then test latency in begin eye render
647  if (eye == 0)
648  {
649  hmds->ProcessLatencyTest2(hmds->LatencyTest2DrawColor, -1.0f);
650  }
651  */
652 }
653 
654 
655 
657  ovrEyeType eyeType, ovrFovPort fov)
658 {
659  ovrEyeRenderDesc erd;
660 
661  HMDState* hmds = (HMDState*)hmd;
662  if (!hmds)
663  {
664  memset(&erd, 0, sizeof(erd));
665  return erd;
666  }
667 
668  return hmds->RenderState.calcRenderDesc(eyeType, fov);
669 }
670 
671 
672 
673 #define OVR_OFFSET_OF(s, field) ((size_t)&((s*)0)->field)
674 
675 
676 
677 // Generate distortion mesh per eye.
678 // scaleAndOffsetOut - this will be needed for shader
680  ovrEyeType eyeType, ovrFovPort fov,
681  unsigned int distortionCaps,
682  ovrDistortionMesh *meshData )
683 {
684  if (!meshData)
685  return 0;
686  HMDState* hmds = (HMDState*)hmd;
687 
688  // Not used now, but Chromatic flag or others could possibly be checked for in the future.
689  OVR_UNUSED1(distortionCaps);
690 
691 #if defined (OVR_OS_WIN32)
692  // TBD: We should probably be sharing some C API structures with C++ to avoid this mess...
700 #endif
701 
702 
703  // *** Calculate a part of "StereoParams" needed for mesh generation
704 
705  // Note that mesh distortion generation is invariant of RenderTarget UVs, allowing
706  // render target size and location to be changed after the fact dynamically.
707  // eyeToSourceUV is computed here for convenience, so that users don't need
708  // to call ovrHmd_GetRenderScaleAndOffset unless changing RT dynamically.
709 
710  const HmdRenderInfo& hmdri = hmds->RenderState.RenderInfo;
711  StereoEye stereoEye = (eyeType == ovrEye_Left) ? StereoEye_Left : StereoEye_Right;
712 
713  const DistortionRenderDesc& distortion = hmds->RenderState.Distortion[eyeType];
714 
715  // Find the mapping from TanAngle space to target NDC space.
716  ScaleAndOffset2D eyeToSourceNDC = CreateNDCScaleAndOffsetFromFov(fov);
717 
718  int triangleCount = 0;
719  int vertexCount = 0;
720 
722  &vertexCount, &triangleCount,
723  (stereoEye == StereoEye_Right),
724  hmdri, distortion, eyeToSourceNDC);
725 
726  if (meshData->pVertexData)
727  {
728  // Convert to index
729  meshData->IndexCount = triangleCount * 3;
730  meshData->VertexCount = vertexCount;
731  return 1;
732  }
733 
734  return 0;
735 }
736 
737 
738 // Frees distortion mesh allocated by ovrHmd_GenerateDistortionMesh. meshData elements
739 // are set to null and 0s after the call.
741 {
742  if (meshData->pVertexData)
744  meshData->pIndexData);
745  meshData->pVertexData = 0;
746  meshData->pIndexData = 0;
747  meshData->VertexCount = 0;
748  meshData->IndexCount = 0;
749 }
750 
751 
752 
753 // Computes updated 'uvScaleOffsetOut' to be used with a distortion if render target size or
754 // viewport changes after the fact. This can be used to adjust render size every frame, if desired.
756  ovrSizei textureSize, ovrRecti renderViewport,
757  ovrVector2f uvScaleOffsetOut[2] )
758 {
759  // Find the mapping from TanAngle space to target NDC space.
760  ScaleAndOffset2D eyeToSourceNDC = CreateNDCScaleAndOffsetFromFov(fov);
761  // Find the mapping from TanAngle space to textureUV space.
763  eyeToSourceNDC,
764  renderViewport, textureSize );
765 
766  uvScaleOffsetOut[0] = eyeToSourceUV.Scale;
767  uvScaleOffsetOut[1] = eyeToSourceUV.Offset;
768 }
769 
770 
771 //-------------------------------------------------------------------------------------
772 // ***** Latency Test interface
773 
774 OVR_EXPORT ovrBool ovrHmd_GetLatencyTestDrawColor(ovrHmd hmd, unsigned char rgbColorOut[3])
775 {
776  HMDState* p = (HMDState*)hmd;
777  rgbColorOut[0] = p->LatencyTestDrawColor[0];
778  rgbColorOut[1] = p->LatencyTestDrawColor[1];
779  rgbColorOut[2] = p->LatencyTestDrawColor[2];
780  return p->LatencyTestActive;
781 }
782 
784 {
785  HMDState* p = (HMDState*)hmd;
786  return p->LatencyUtil.GetResultsString();
787 }
788 
790 {
791  HMDState* p = (HMDState*)hmd;
792 
793  // MA Test
794  float latencies[3];
795  p->TimeManager.GetLatencyTimings(latencies);
796  return latencies[2];
797  // return p->LatencyUtil2.GetMeasuredLatency();
798 }
799 
800 
801 // -----------------------------------------------------------------------------------
802 // ***** Property Access
803 
804 OVR_EXPORT float ovrHmd_GetFloat(ovrHmd hmd, const char* propertyName, float defaultVal)
805 {
806  HMDState* hmds = (HMDState*)hmd;
807  if (hmds)
808  {
809  return hmds->getFloatValue(propertyName, defaultVal);
810  }
811 
812  return defaultVal;
813 }
814 
815 OVR_EXPORT ovrBool ovrHmd_SetFloat(ovrHmd hmd, const char* propertyName, float value)
816 {
817  HMDState* hmds = (HMDState*)hmd;
818  if (hmds)
819  {
820  return hmds->setFloatValue(propertyName, value);
821  }
822  return false;
823 }
824 
825 
826 
827 OVR_EXPORT unsigned int ovrHmd_GetFloatArray(ovrHmd hmd, const char* propertyName,
828  float values[], unsigned int arraySize)
829 {
830  HMDState* hmds = (HMDState*)hmd;
831  if (hmds)
832  {
833  return hmds->getFloatArray(propertyName, values, arraySize);
834  }
835 
836  return 0;
837 }
838 
839 
840 // Modify float[] property; false if property doesn't exist or is readonly.
841 OVR_EXPORT ovrBool ovrHmd_SetFloatArray(ovrHmd hmd, const char* propertyName,
842  float values[], unsigned int arraySize)
843 {
844  HMDState* hmds = (HMDState*)hmd;
845  if (hmds)
846  {
847  return hmds->setFloatArray(propertyName, values, arraySize);
848  }
849 
850  return 0;
851 }
852 
853 OVR_EXPORT const char* ovrHmd_GetString(ovrHmd hmd, const char* propertyName,
854  const char* defaultVal)
855 {
856  HMDState* hmds = (HMDState*)hmd;
857  if (hmds)
858  {
859  return hmds->getString(propertyName, defaultVal);
860  }
861 
862  return defaultVal;
863 }
864 
865 /* Not needed yet.
866 
867 // Get array of strings, i.e. const char* [] property.
868 // Returns the number of elements filled in, 0 if property doesn't exist.
869 // Maximum of arraySize elements will be written.
870 // String memory is guaranteed to exist until next call to GetString or GetStringArray, or HMD is destroyed.
871 OVR_EXPORT
872 unsigned int ovrHmd_GetStringArray(ovrHmd hmd, const char* propertyName,
873  const char* values[], unsigned int arraySize)
874 {
875  HMDState* hmds = (HMDState*)hmd;
876  if (hmds && hmds->pHMD && arraySize)
877  {
878  Profile* p = hmds->pHMD->GetProfile();
879 
880  hmds->LastGetStringValue[0] = 0;
881  if (p && p->GetValue(propertyName, hmds->LastGetStringValue, sizeof(hmds->LastGetStringValue)))
882  {
883  values[0] = hmds->LastGetStringValue;
884  return 1;
885  }
886  }
887 
888  return 0;
889 }
890 */
891 
892 // Returns array size of a property, 0 if property doesn't exist.
893 // Can be used to check existence of a property.
894 OVR_EXPORT unsigned int ovrHmd_GetArraySize(ovrHmd hmd, const char* propertyName)
895 {
896  HMDState* hmds = (HMDState*)hmd;
897  if (hmds && hmds->pHMD)
898  {
899  // For now, just access the profile.
900  Profile* p = hmds->pHMD->GetProfile();
901 
902  if (p)
903  return p->GetNumValues(propertyName);
904  }
905  return 0;
906 }
907 
908 
909 #ifdef __cplusplus
910 } // extern "C"
911 #endif
912 
913 
914 //-------------------------------------------------------------------------------------
915 // ****** Special access for VRConfig
916 
917 // Return the sensor fusion object for the purposes of magnetometer calibration. The
918 // function is private and is only exposed through VRConfig header declarations
920 {
921  HMDState* p = (HMDState*)hmd;
922  return &p->SFusion;
923 }
924 
925 
OVR_EXPORT ovrBool ovrHmd_GetLatencyTestDrawColor(ovrHmd hmd, unsigned char rgbColorOut[3])
Definition: OVR_CAPI.cpp:774
float UpTan
Definition: OVR_CAPI.h:102
FrameTimeRecordSet GetLocklessState()
OVR_EXPORT ovrBool ovrHmd_CreateDistortionMesh(ovrHmd hmd, ovrEyeType eyeType, ovrFovPort fov, unsigned int distortionCaps, ovrDistortionMesh *meshData)
Definition: OVR_CAPI.cpp:679
OVR_EXPORT ovrPosef ovrHmd_BeginEyeRender(ovrHmd hmd, ovrEyeType eye)
Definition: OVR_CAPI.cpp:509
void GetLatencyTimings(float latencies[3])
OVR_EXPORT unsigned int ovrHmd_GetFloatArray(ovrHmd hmd, const char *propertyName, float values[], unsigned int arraySize)
Definition: OVR_CAPI.cpp:827
OVR_EXPORT ovrBool ovrHmd_ConfigureRendering(ovrHmd hmd, const ovrRenderAPIConfig *apiConfig, unsigned int distortionCaps, const ovrFovPort eyeFovIn[2], ovrEyeRenderDesc eyeRenderDescOut[2])
Definition: OVR_CAPI.cpp:418
ovrHmdType
Definition: OVR_CAPI.h:113
ovrPoseStatef Predicted
Definition: OVR_CAPI.h:257
Ptr< HMDDevice > pHMD
#define OVR_ASSERT_LOG(c, args)
Definition: OVR_Log.h:198
float M[4][4]
Definition: OVR_CAPI.h:77
double NextFrameSeconds
Definition: OVR_CAPI.h:301
OVR_EXPORT ovrSizei ovrHmd_GetFovTextureSize(ovrHmd hmd, ovrEyeType eye, ovrFovPort fov, float pixelsPerDisplayPixel)
Definition: OVR_CAPI.cpp:404
Timing GetFrameTiming(unsigned frameIndex)
const char * GetResultsString()
int GetNumValues(const char *key) const
OVR_EXPORT void ovrHmd_SetEnabledCaps(ovrHmd hmd, unsigned int capsBits)
Definition: OVR_CAPI.cpp:335
struct ovrSensorState_ ovrSensorState
OVR_EXPORT const char * ovrHmd_GetLatencyTestResult(ovrHmd hmd)
Definition: OVR_CAPI.cpp:783
OVR_EXPORT const char * ovrHmd_GetLastError(ovrHmd hmd)
Definition: OVR_CAPI.cpp:308
static void OVR_CDECL Init(Log *log=Log::ConfigureDefaultLog(LogMask_Debug), Allocator *palloc=DefaultAllocator::InitSystemSingleton())
Definition: OVR_System.cpp:37
static void OVR_CDECL Destroy()
Definition: OVR_System.cpp:51
OVR_EXPORT void ovrHmd_GetDesc(ovrHmd hmd, ovrHmdDesc *desc)
Definition: OVR_CAPI.cpp:396
#define NULL
SensorFusion SFusion
ScaleAndOffset2D CreateUVScaleAndOffsetfromNDCScaleandOffset(ScaleAndOffset2D scaleAndOffsetNDC, Recti renderedViewport, Sizei renderTargetSize)
OVR_EXPORT ovrFrameTiming ovrHmd_GetFrameTiming(ovrHmd hmd, unsigned int frameIndex)
Definition: OVR_CAPI.cpp:529
OVR_EXPORT ovrSensorState ovrHmd_GetSensorState(ovrHmd hmd, double absTime)
Definition: OVR_CAPI.cpp:377
ThreadChecker RenderAPIThreadChecker
OVR::SensorFusion * ovrHmd_GetSensorFusion(ovrHmd hmd)
Definition: OVR_CAPI.cpp:919
OVR_EXPORT void ovrHmd_ResetSensor(ovrHmd hmd)
Definition: OVR_CAPI.cpp:371
OVR_EXPORT ovrEyeRenderDesc ovrHmd_GetRenderDesc(ovrHmd hmd, ovrEyeType eyeType, ovrFovPort fov)
Definition: OVR_CAPI.cpp:656
uint16_t UInt16
Definition: OVR_Types.h:251
float y
Definition: OVR_CAPI.h:69
OVR_EXPORT unsigned int ovrHmd_GetEnabledCaps(ovrHmd hmd)
Definition: OVR_CAPI.cpp:327
unsigned int VertexCount
Definition: OVR_CAPI.h:626
unsigned int StatusFlags
Definition: OVR_CAPI.h:265
OVR_EXPORT void ovrHmd_GetEyeTimewarpMatrices(ovrHmd hmd, ovrEyeType eye, ovrPosef renderPose, ovrMatrix4f twmOut[2])
Definition: OVR_CAPI.cpp:631
const OVR::HMDInfo & HMDInfo
OVR_EXPORT void ovrHmd_Destroy(ovrHmd hmd)
Definition: OVR_CAPI.cpp:292
OVR_EXPORT void ovrHmd_DestroyDistortionMesh(ovrDistortionMesh *meshData)
Definition: OVR_CAPI.cpp:740
OVR_EXPORT ovrMatrix4f ovrMatrix4f_Projection(ovrFovPort fov, float znear, float zfar, ovrBool rightHanded)
Definition: OVR_CAPI.cpp:105
HMDRenderState RenderState
OVR_EXPORT double ovr_GetTimeInSeconds()
Definition: OVR_CAPI.cpp:182
void checkRenderingConfigured(const char *functionName)
Transformf GetEyePredictionPose(ovrHmd hmd, ovrEyeType eye)
ovrHmd Handle
Definition: OVR_CAPI.h:191
DistortionRenderDesc Distortion[2]
OVR_EXPORT double ovr_WaitTillTime(double absTime)
Definition: OVR_CAPI.cpp:188
OVR_EXPORT ovrHmd ovrHmd_Create(int index)
Definition: OVR_CAPI.cpp:268
OVR_EXPORT ovrPosef ovrHmd_GetEyePose(ovrHmd hmd, ovrEyeType eye)
Definition: OVR_CAPI.cpp:621
ovrDistortionVertex * pVertexData
Definition: OVR_CAPI.h:624
OVR_EXPORT const char * ovrHmd_GetString(ovrHmd hmd, const char *propertyName, const char *defaultVal)
Definition: OVR_CAPI.cpp:853
OVR_EXPORT void ovrHmd_GetRenderScaleAndOffset(ovrFovPort fov, ovrSizei textureSize, ovrRecti renderViewport, ovrVector2f uvScaleOffsetOut[2])
Definition: OVR_CAPI.cpp:755
unsigned int StatusFlags
#define OVR_UNUSED1(a1)
OVR_EXPORT ovrFrameTiming ovrHmd_BeginFrameTiming(ovrHmd hmd, unsigned int frameIndex)
Definition: OVR_CAPI.cpp:557
ovrEyeType
Definition: OVR_CAPI.h:177
OVR_EXPORT void ovr_Shutdown()
Definition: OVR_CAPI.cpp:228
double ThisFrameSeconds
Definition: OVR_CAPI.h:297
unsigned char LatencyTestDrawColor[3]
OVR_EXPORT ovrBool ovr_Initialize()
Definition: OVR_CAPI.cpp:211
OVR_EXPORT ovrBool ovrHmd_SetFloatArray(ovrHmd hmd, const char *propertyName, float values[], unsigned int arraySize)
Definition: OVR_CAPI.cpp:841
void checkBeginFrameTimingScope(const char *functionName)
unsigned getFloatArray(const char *propertyName, float values[], unsigned arraySize)
Vector2f TanAngleToRendertargetNDC(Vector2f const &tanEyeAngle)
Definition: OVR_CAPI.cpp:65
unsigned char GetFrameLatencyTestDrawColor()
bool StartSensor(unsigned supportedCaps, unsigned requiredCaps)
bool setFloatArray(const char *propertyName, float values[], unsigned arraySize)
ThreadId BeginFrameThreadId
double TimewarpPointSeconds
Definition: OVR_CAPI.h:299
OVR_EXPORT ovrBool ovrHmd_StartSensor(ovrHmd hmd, unsigned int supportedCaps, unsigned int requiredCaps)
Definition: OVR_CAPI.cpp:358
double ScanoutMidpointSeconds
Definition: OVR_CAPI.h:305
OVR_EXPORT int ovrHmd_Detect()
Definition: OVR_CAPI.cpp:255
double LastGetFrameTimeSeconds
float LeftTan
Definition: OVR_CAPI.h:104
char ovrBool
Definition: OVR_CAPI.h:31
const char * GetLastError()
unsigned int IndexCount
Definition: OVR_CAPI.h:627
float x
Definition: OVR_CAPI.h:69
OVR_EXPORT void ovrHmd_EndFrameTiming(ovrHmd hmd)
Definition: OVR_CAPI.cpp:592
OVR_EXPORT void ovrHmd_StopSensor(ovrHmd hmd)
Definition: OVR_CAPI.cpp:365
Matrix4f CreateProjection(bool rightHanded, FovPort tanHalfFov, float zNear, float zFar)
float DownTan
Definition: OVR_CAPI.h:103
static bool OVR_CDECL IsInitialized()
Definition: OVR_System.cpp:75
void SetEnabledHmdCaps(unsigned caps)
#define OVR_OFFSET_OF(s, field)
Definition: OVR_CAPI.cpp:673
struct ovrFovPort_ ovrFovPort
OVR_EXPORT ovrFrameTiming ovrHmd_BeginFrame(ovrHmd hmd, unsigned int frameIndex)
Definition: OVR_CAPI.cpp:440
void ovrHmd_SetVsync(ovrHmd hmd, ovrBool vsync)
Definition: OVR_CAPI.cpp:432
const char * getString(const char *propertyName, const char *defaultVal)
T M[4][4]
Definition: OVR_Math.h:1197
ovrEyeRenderDesc calcRenderDesc(ovrEyeType eyeType, const ovrFovPort &fov)
OVR_EXPORT void ovrHmd_EndFrame(ovrHmd hmd)
Definition: OVR_CAPI.cpp:463
OVR_EXPORT ovrBool ovrHmd_SetFloat(ovrHmd hmd, const char *propertyName, float value)
Definition: OVR_CAPI.cpp:815
FovPort(float sideTan=0.0f)
Definition: OVR_Stereo.h:72
void DistortionMeshCreate(DistortionMeshVertexData **ppVertices, UInt16 **ppTriangleListIndices, int *pNumVertices, int *pNumTriangles, const StereoEyeParams &stereoParams, const HmdRenderInfo &hmdRenderInfo)
void DistortionMeshDestroy(DistortionMeshVertexData *pVertices, UInt16 *pTriangleMeshIndices)
ovrPosef BeginEyeRender(ovrEyeType eye)
HmdTypeEnum HmdType
Definition: OVR_Device.h:323
double BeginFrame(unsigned frameIndex)
ScaleAndOffset2D CreateNDCScaleAndOffsetFromFov(FovPort tanHalfFov)
float RightTan
Definition: OVR_CAPI.h:105
void UpdateFrameLatencyTrackingAfterEndFrame(unsigned char frameLatencyTestColor, const Util::FrameTimeRecordSet &rs)
OVR_EXPORT void ovrHmd_EndEyeRender(ovrHmd hmd, ovrEyeType eye, ovrPosef renderPose, ovrTexture *eyeTexture)
Definition: OVR_CAPI.cpp:516
Ptr< DistortionRenderer > pRenderer
void checkBeginFrameScope(const char *functionName)
Util::LatencyTest LatencyUtil
double EyeScanoutSeconds[2]
Definition: OVR_CAPI.h:307
void ResetFrameTiming(unsigned frameIndex, bool dynamicPrediction, bool sdkRender)
HMDDevice * CreateDevice(int index)
__BEGIN_NAMESPACE_STD void void __END_NAMESPACE_STD void __BEGIN_NAMESPACE_STD void * memset(void *__s, int __c, size_t __n) __THROW __nonnull((1))
Util::LatencyTest2 LatencyUtil2
OVR_EXPORT void ovrHmd_ResetFrameTiming(ovrHmd hmd, unsigned int frameIndex)
Definition: OVR_CAPI.cpp:607
OVR_EXPORT ovrHmd ovrHmd_CreateDebug(ovrHmdType type)
Definition: OVR_CAPI.cpp:283
unsigned short * pIndexData
Definition: OVR_CAPI.h:625
static double OVR_STDCALL GetSeconds()
Definition: OVR_Timer.cpp:51
void EndEyeRender(ovrEyeType eye, ovrPosef renderPose, ovrTexture *eyeTexture)
int char * index(const char *__s, int __c) __THROW __attribute_pure__ __nonnull((1))
float DeltaSeconds
Definition: OVR_CAPI.h:288
FrameTimeManager TimeManager
static ovrBool CAPI_SystemInitCalled
Definition: OVR_CAPI.cpp:209
ovrSizei GetFOVTextureSize(int eye, ovrFovPort fov, float pixelsPerDisplayPixel)
OVR_EXPORT unsigned int ovrHmd_GetArraySize(ovrHmd hmd, const char *propertyName)
Definition: OVR_CAPI.cpp:894
OVR_EXPORT ovrMatrix4f ovrMatrix4f_OrthoSubProjection(ovrMatrix4f projection, ovrVector2f orthoScale, float orthoDistance, float eyeViewAdjustX)
Definition: OVR_CAPI.cpp:111
OVR_EXPORT float ovrHmd_GetFloat(ovrHmd hmd, const char *propertyName, float defaultVal)
Definition: OVR_CAPI.cpp:804
unsigned char LatencyTest2DrawColor[3]
static GlobalState * pInstance
StereoEye
Definition: OVR_Stereo.h:44
static Log * ConfigureDefaultLog(unsigned logMask=LogMask_Debug)
Definition: OVR_Log.h:157
bool setFloatValue(const char *propertyName, float value)
ThreadId GetCurrentThreadId()
ovrPoseStatef Recorded
Definition: OVR_CAPI.h:260
bool GetSensorDesc(ovrSensorDesc *descOut)
Size< int > Sizei
Definition: OVR_Math.h:636
float Temperature
Definition: OVR_CAPI.h:263
#define OVR_COMPILER_ASSERT(x)
OVR_EXPORT ovrBool ovrHmd_GetSensorDesc(ovrHmd hmd, ovrSensorDesc *descOut)
Definition: OVR_CAPI.cpp:384
ovrSensorState PredictedSensorState(double absTime)
float getFloatValue(const char *propertyName, float defaultVal)
void GetTimewarpMatrices(ovrHmd hmd, ovrEyeType eye, ovrPosef renderPose, ovrMatrix4f twmOut[2])
#define OVR_EXPORT
Definition: OVR_CAPI.h:40
OVR_EXPORT double ovrHmd_GetMeasuredLatencyTest2(ovrHmd hmd)
Definition: OVR_CAPI.cpp:789
struct ovrPosef_ ovrPosef
Definition: OVR_Math.h:113