Torque3D Documentation / _generateds / oculusVRHMDDevice.cpp

oculusVRHMDDevice.cpp

Engine/source/platform/input/oculusVR/oculusVRHMDDevice.cpp

More...

Classes:

Public Defines

define

Public Variables

bool

Detailed Description

Public Defines

OCULUS_USE_GL() 

Public Variables

bool sInFrame 
  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "platform/input/oculusVR/oculusVRHMDDevice.h"
 25#include "platform/input/oculusVR/oculusVRDevice.h"
 26#include "platform/input/oculusVR/oculusVRSensorDevice.h"
 27#include "postFx/postEffectCommon.h"
 28#include "gui/core/guiCanvas.h"
 29#include "platform/input/oculusVR/oculusVRUtil.h"
 30#include "core/stream/fileStream.h"
 31
 32
 33#include "gfx/D3D11/gfxD3D11Device.h"
 34#include "gfx/D3D11/gfxD3D11EnumTranslate.h"
 35#include "gfx/gfxStringEnumTranslate.h"
 36#undef D3D11
 37
 38// Use D3D11 for win32
 39#ifdef TORQUE_OS_WIN
 40#define OVR_D3D_VERSION 11
 41#include "OVR_CAPI_D3D.h"
 42#define OCULUS_USE_D3D
 43#else
 44#include "OVR_CAPI_GL.h"
 45#define OCULUS_USE_GL
 46#endif
 47
 48struct OculusTexture
 49{
 50   virtual void AdvanceToNextTexture() = 0;
 51
 52   virtual ~OculusTexture() {
 53   }
 54};
 55
 56//------------------------------------------------------------
 57// ovrSwapTextureSet wrapper class that also maintains the render target views
 58// needed for D3D11 rendering.
 59struct D3D11OculusTexture : public OculusTexture
 60{
 61   ovrHmd                   hmd;
 62   ovrSwapTextureSet      * TextureSet;
 63   static const int         TextureCount = 2;
 64   GFXTexHandle  TexRtv[TextureCount];
 65   GFXDevice *Owner;
 66
 67   D3D11OculusTexture(GFXDevice* owner) :
 68      hmd(nullptr),
 69      TextureSet(nullptr),
 70      Owner(owner)
 71   {
 72      TexRtv[0] = TexRtv[1] = nullptr;
 73   }
 74
 75   bool Init(ovrHmd _hmd, int sizeW, int sizeH)
 76   {
 77      hmd = _hmd;
 78
 79      D3D11_TEXTURE2D_DESC dsDesc;
 80      dsDesc.Width = sizeW;
 81      dsDesc.Height = sizeH;
 82      dsDesc.MipLevels = 1;
 83      dsDesc.ArraySize = 1;
 84      dsDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;// DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
 85      dsDesc.SampleDesc.Count = 1;   // No multi-sampling allowed
 86      dsDesc.SampleDesc.Quality = 0;
 87      dsDesc.Usage = D3D11_USAGE_DEFAULT;
 88      dsDesc.CPUAccessFlags = 0;
 89      dsDesc.MiscFlags = 0;
 90      dsDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
 91
 92
 93      GFXD3D11Device* device = static_cast<GFXD3D11Device*>(GFX);
 94      ovrResult result = ovr_CreateSwapTextureSetD3D11(hmd, device->mD3DDevice, &dsDesc, ovrSwapTextureSetD3D11_Typeless, &TextureSet);
 95      if (!OVR_SUCCESS(result))
 96         return false;
 97
 98      AssertFatal(TextureSet->TextureCount == TextureCount, "TextureCount mismatch.");
 99
100      for (int i = 0; i < TextureCount; ++i)
101      {
102         ovrD3D11Texture* tex = (ovrD3D11Texture*)&TextureSet->Textures[i];
103         D3D11_RENDER_TARGET_VIEW_DESC rtvd = {};
104         rtvd.Format = DXGI_FORMAT_B8G8R8A8_UNORM;// DXGI_FORMAT_R8G8B8A8_UNORM;
105         rtvd.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
106
107         GFXD3D11TextureObject* object = new GFXD3D11TextureObject(GFX, &VRTextureProfile);
108         object->registerResourceWithDevice(GFX);
109         *(object->getSRViewPtr()) = tex->D3D11.pSRView;
110         *(object->get2DTexPtr()) = tex->D3D11.pTexture;
111         device->mD3DDevice->CreateRenderTargetView(tex->D3D11.pTexture, &rtvd, object->getRTViewPtr());
112
113         // Add refs for texture release later on
114         if (object->getSRView()) object->getSRView()->AddRef();
115         //object->getRTView()->AddRef();
116         if (object->get2DTex()) object->get2DTex()->AddRef();
117         object->isManaged = true;
118
119         // Get the actual size of the texture...
120         D3D11_TEXTURE2D_DESC probeDesc;
121         ZeroMemory(&probeDesc, sizeof(D3D11_TEXTURE2D_DESC));
122         object->get2DTex()->GetDesc(&probeDesc);
123
124         object->mTextureSize.set(probeDesc.Width, probeDesc.Height, 0);
125         object->mBitmapSize = object->mTextureSize;
126         int fmt = probeDesc.Format;
127
128         if (fmt == DXGI_FORMAT_R8G8B8A8_TYPELESS || fmt == DXGI_FORMAT_B8G8R8A8_TYPELESS)
129         {
130            object->mFormat = GFXFormatR8G8B8A8; // usual case
131         }
132         else
133         {
134            // TODO: improve this. this can be very bad.
135            GFXREVERSE_LOOKUP(GFXD3D11TextureFormat, GFXFormat, fmt);
136            object->mFormat = (GFXFormat)fmt;
137         }
138         TexRtv[i] = object;
139      }
140
141      return true;
142   }
143
144   ~D3D11OculusTexture()
145   {
146      for (int i = 0; i < TextureCount; ++i)
147      {
148         SAFE_DELETE(TexRtv[i]);
149      }
150      if (TextureSet)
151      {
152         ovr_DestroySwapTextureSet(hmd, TextureSet);
153      }
154   }
155
156   void AdvanceToNextTexture()
157   {
158      TextureSet->CurrentIndex = (TextureSet->CurrentIndex + 1) % TextureSet->TextureCount;
159   }
160};
161
162
163OculusVRHMDDevice::OculusVRHMDDevice()
164{
165   mIsValid = false;
166   mDevice = NULL;
167   mCurrentCaps = 0;
168   mSupportedCaps = 0;
169   mVsync = true;
170   mTimewarp = true;
171   mRenderConfigurationDirty = true;
172   mCurrentPixelDensity = OculusVRDevice::smDesiredPixelDensity;
173   mDesiredRenderingMode = GFXDevice::RS_StereoSideBySide;
174   mRTFormat = GFXFormatR8G8B8A8;
175   mDrawCanvas = NULL;
176   mFrameReady = false;
177   mConnection = NULL;
178   mSensor = NULL;
179   mActionCodeIndex = 0;
180   mTextureSwapSet = NULL;
181}
182
183OculusVRHMDDevice::~OculusVRHMDDevice()
184{
185   cleanUp();
186}
187
188void OculusVRHMDDevice::cleanUp()
189{
190   onDeviceDestroy();
191
192   if (mSensor)
193   {
194      delete mSensor;
195      mSensor = NULL;
196   }
197
198   if(mDevice)
199   {
200      ovr_Destroy(mDevice);
201      mDevice = NULL;
202   }
203
204   mIsValid = false;
205}
206
207void OculusVRHMDDevice::set(ovrHmd hmd, ovrGraphicsLuid luid, U32 actionCodeIndex)
208{
209   cleanUp();
210
211   mIsValid = false;
212   mRenderConfigurationDirty = true;
213
214   mDevice = hmd;
215
216   ovrHmdDesc desc = ovr_GetHmdDesc(hmd);
217   int caps = ovr_GetTrackingCaps(hmd);
218
219   mSupportedCaps = desc.AvailableHmdCaps;
220   mCurrentCaps = mSupportedCaps;
221   
222   mTimewarp = true;
223
224   // DeviceInfo
225   mProductName = desc.ProductName;
226   mManufacturer = desc.Manufacturer;
227   mVersion = desc.FirmwareMajor;
228
229   //
230   Vector<GFXAdapter*> adapterList;
231   GFXD3D11Device::enumerateAdapters(adapterList);
232
233   dMemcpy(&mLuid, &luid, sizeof(mLuid));
234   mDisplayId = -1;
235
236   for (U32 i = 0, sz = adapterList.size(); i < sz; i++)
237   {
238      GFXAdapter* adapter = adapterList[i];
239      if (dMemcmp(&adapter->mLUID, &mLuid, sizeof(mLuid)) == 0)
240      {
241         mDisplayId = adapter->mIndex;
242         mDisplayDeviceType = "D3D11"; // TOFIX this
243      }
244   }
245
246   mResolution.x = desc.Resolution.w;
247   mResolution.y = desc.Resolution.h;
248
249   mProfileInterpupillaryDistance = ovr_GetFloat(hmd, OVR_KEY_IPD, OVR_DEFAULT_IPD);
250   mLensSeparation = ovr_GetFloat(hmd, "LensSeparation", 0);
251   ovr_GetFloatArray(hmd, "ScreenSize", &mScreenSize.x, 2);
252
253   mActionCodeIndex = actionCodeIndex;
254
255   mIsValid = true;
256
257   mSensor = new OculusVRSensorDevice();
258   mSensor->set(mDevice, mActionCodeIndex);
259
260   mDebugMirrorTexture = NULL;
261
262   updateCaps();
263}
264
265void OculusVRHMDDevice::setIPD(F32 ipd)
266{
267   mInterpupillaryDistance = ipd;
268}
269
270void OculusVRHMDDevice::setOptimalDisplaySize(GuiCanvas *canvas)
271{
272   if (!mDevice)
273      return;
274
275   PlatformWindow *window = canvas->getPlatformWindow();
276   GFXTarget *target = window->getGFXTarget();
277
278   Point2I requiredSize(0, 0);
279
280   ovrHmdDesc desc = ovr_GetHmdDesc(mDevice);
281   ovrSizei leftSize = ovr_GetFovTextureSize(mDevice, ovrEye_Left, desc.DefaultEyeFov[0], mCurrentPixelDensity);
282   ovrSizei rightSize = ovr_GetFovTextureSize(mDevice, ovrEye_Right, desc.DefaultEyeFov[1], mCurrentPixelDensity);
283
284   requiredSize.x = leftSize.w + rightSize.h;
285   requiredSize.y = mMax(leftSize.h, rightSize.h);
286   
287   if (target && target->getSize() != requiredSize)
288   {
289      GFXVideoMode newMode;
290      newMode.antialiasLevel = 0;
291      newMode.bitDepth = 32;
292      newMode.fullScreen = false;
293      newMode.refreshRate = 75;
294      newMode.resolution = requiredSize;
295      newMode.wideScreen = false;
296      window->setVideoMode(newMode);
297      //AssertFatal(window->getClientExtent().x == requiredSize.x && window->getClientExtent().y == requiredSize.y, "Window didn't resize to correct dimensions");
298   }
299}
300
301bool OculusVRHMDDevice::isDisplayingWarning()
302{
303   if (!mIsValid || !mDevice)
304      return false;
305
306   return false;/*
307   ovrHSWDisplayState displayState;
308   ovrHmd_GetHSWDisplayState(mDevice, &displayState);
309
310   return displayState.Displayed;*/
311}
312
313void OculusVRHMDDevice::dismissWarning()
314{
315   if (!mIsValid || !mDevice)
316      return;
317   //ovr_DismissHSWDisplay(mDevice);
318}
319
320GFXTexHandle OculusVRHMDDevice::getPreviewTexture()
321{
322   if (!mIsValid || !mDevice)
323      return NULL;
324
325   return mDebugMirrorTextureHandle;
326}
327
328bool OculusVRHMDDevice::setupTargets()
329{
330   // Create eye render buffers
331   ID3D11RenderTargetView * eyeRenderTexRtv[2];
332   ovrLayerEyeFov           ld = { { ovrLayerType_EyeFov } };
333   mRenderLayer = ld;
334
335   GFXD3D11Device* device = static_cast<GFXD3D11Device*>(GFX);
336
337   ovrHmdDesc desc = ovr_GetHmdDesc(mDevice);
338   for (int i = 0; i < 2; i++)
339   {
340      mRenderLayer.Fov[i] = desc.DefaultEyeFov[i];
341      mRenderLayer.Viewport[i].Size = ovr_GetFovTextureSize(mDevice, (ovrEyeType)i, mRenderLayer.Fov[i], mCurrentPixelDensity);
342      mEyeRenderDesc[i] = ovr_GetRenderDesc(mDevice, (ovrEyeType_)(ovrEye_Left+i), mRenderLayer.Fov[i]);
343   }
344
345   ovrSizei recommendedEyeTargetSize[2];
346   recommendedEyeTargetSize[0] = mRenderLayer.Viewport[0].Size;
347   recommendedEyeTargetSize[1] = mRenderLayer.Viewport[1].Size;
348
349   if (mTextureSwapSet)
350   {
351      delete mTextureSwapSet;
352      mTextureSwapSet = NULL;
353   }
354
355   // Calculate render target size
356   if (mDesiredRenderingMode == GFXDevice::RS_StereoSideBySide)
357   {
358      // Setup a single texture, side-by-side viewports
359      Point2I rtSize(
360         recommendedEyeTargetSize[0].w + recommendedEyeTargetSize[1].w,
361         recommendedEyeTargetSize[0].h > recommendedEyeTargetSize[1].h ? recommendedEyeTargetSize[0].h : recommendedEyeTargetSize[1].h
362         );
363
364      GFXFormat targetFormat = GFX->getActiveRenderTarget()->getFormat();
365      mRTFormat = targetFormat;
366
367      rtSize = generateRenderTarget(mStereoRT, mStereoDepthTexture, rtSize);
368
369      // Generate the swap texture we need to store the final image
370      D3D11OculusTexture* tex = new D3D11OculusTexture(GFX);
371      if (tex->Init(mDevice, rtSize.x, rtSize.y))
372      {
373         mTextureSwapSet = tex;
374      }
375
376      mRenderLayer.ColorTexture[0] = tex->TextureSet;
377      mRenderLayer.ColorTexture[1] = tex->TextureSet;
378
379      mRenderLayer.Viewport[0].Pos.x = 0;
380      mRenderLayer.Viewport[0].Pos.y = 0;
381      mRenderLayer.Viewport[1].Pos.x = (rtSize.x + 1) / 2;
382      mRenderLayer.Viewport[1].Pos.y = 0;
383
384      // Left
385      mEyeRT[0] = mStereoRT;
386      mEyeViewport[0] = RectI(Point2I(mRenderLayer.Viewport[0].Pos.x, mRenderLayer.Viewport[0].Pos.y), Point2I(mRenderLayer.Viewport[0].Size.w, mRenderLayer.Viewport[0].Size.h));
387
388      // Right
389      mEyeRT[1] = mStereoRT;
390      mEyeViewport[1] = RectI(Point2I(mRenderLayer.Viewport[1].Pos.x, mRenderLayer.Viewport[1].Pos.y), Point2I(mRenderLayer.Viewport[1].Size.w, mRenderLayer.Viewport[1].Size.h));
391
392      GFXD3D11Device* device = static_cast<GFXD3D11Device*>(GFX);
393
394      D3D11_TEXTURE2D_DESC dsDesc;
395      dsDesc.Width = rtSize.x;
396      dsDesc.Height = rtSize.y;
397      dsDesc.MipLevels = 1;
398      dsDesc.ArraySize = 1;
399      dsDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;// DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
400      dsDesc.SampleDesc.Count = 1;
401      dsDesc.SampleDesc.Quality = 0;
402      dsDesc.Usage = D3D11_USAGE_DEFAULT;
403      dsDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
404      dsDesc.CPUAccessFlags = 0;
405      dsDesc.MiscFlags = 0;
406
407      // Create typeless when we are rendering as non-sRGB since we will override the texture format in the RTV
408      bool reinterpretSrgbAsLinear = true;
409      unsigned compositorTextureFlags = 0;
410      if (reinterpretSrgbAsLinear)
411         compositorTextureFlags |= ovrSwapTextureSetD3D11_Typeless;
412
413      ovrResult result = ovr_CreateMirrorTextureD3D11(mDevice, device->mD3DDevice, &dsDesc, compositorTextureFlags, &mDebugMirrorTexture);
414      
415      if (result == ovrError_DisplayLost || !mDebugMirrorTexture)
416      {
417         AssertFatal(false, "Something went wrong");
418         return NULL;
419      }
420
421      // Create texture handle so we can render it in-game
422      ovrD3D11Texture* mirror_tex = (ovrD3D11Texture*)mDebugMirrorTexture;
423      D3D11_RENDER_TARGET_VIEW_DESC rtvd = {};
424      rtvd.Format = DXGI_FORMAT_B8G8R8A8_UNORM;// DXGI_FORMAT_R8G8B8A8_UNORM;
425      rtvd.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
426
427      GFXD3D11TextureObject* object = new GFXD3D11TextureObject(GFX, &VRTextureProfile);
428      object->registerResourceWithDevice(GFX);
429      *(object->getSRViewPtr()) = mirror_tex->D3D11.pSRView;
430      *(object->get2DTexPtr()) = mirror_tex->D3D11.pTexture;
431      device->mD3DDevice->CreateRenderTargetView(mirror_tex->D3D11.pTexture, &rtvd, object->getRTViewPtr());
432
433
434      // Add refs for texture release later on
435      if (object->getSRView()) object->getSRView()->AddRef();
436      //object->getRTView()->AddRef();
437      if (object->get2DTex()) object->get2DTex()->AddRef();
438      object->isManaged = true;
439
440      // Get the actual size of the texture...
441      D3D11_TEXTURE2D_DESC probeDesc;
442      ZeroMemory(&probeDesc, sizeof(D3D11_TEXTURE2D_DESC));
443      object->get2DTex()->GetDesc(&probeDesc);
444
445      object->mTextureSize.set(probeDesc.Width, probeDesc.Height, 0);
446      object->mBitmapSize = object->mTextureSize;
447      int fmt = probeDesc.Format;
448
449      if (fmt == DXGI_FORMAT_R8G8B8A8_TYPELESS || fmt == DXGI_FORMAT_B8G8R8A8_TYPELESS)
450      {
451         object->mFormat = GFXFormatR8G8B8A8; // usual case
452      }
453      else
454      {
455         // TODO: improve this. this can be very bad.
456         GFXREVERSE_LOOKUP(GFXD3D11TextureFormat, GFXFormat, fmt);
457         object->mFormat = (GFXFormat)fmt;
458      }
459      
460      mDebugMirrorTextureHandle = object;
461   }
462   else
463   {
464      // No rendering, abort!
465      return false;
466   }
467
468   return true;
469}
470
471String OculusVRHMDDevice::dumpMetrics()
472{
473   StringBuilder sb;
474
475   EulerF rot = mSensor->getEulerRotation();
476   Point3F pos = mSensor->getPosition();
477   FovPort eyeFov[2];
478   this->getFovPorts(eyeFov);
479
480   mSensor->getPositionTrackingAvailable();
481
482   F32 ipd = this->getIPD();
483   U32 lastStatus = mSensor->getLastTrackingStatus();
484
485   sb.format("   | OVR Sensor %i | rot: %f %f %f, pos: %f %f %f, FOV (%f %f %f %f, %f %f %f %f), IPD %f, Track:%s%s",
486             mActionCodeIndex,
487             rot.x, rot.y, rot.z,
488             pos.x, pos.y, pos.z,
489             eyeFov[0].upTan, eyeFov[0].downTan, eyeFov[0].leftTan, eyeFov[0].rightTan, eyeFov[1].upTan, eyeFov[1].downTan, eyeFov[1].leftTan, eyeFov[1].rightTan,
490             getIPD(),
491             lastStatus & ovrStatus_OrientationTracked ? " ORIENT" : "",
492             lastStatus & ovrStatus_PositionTracked ? " POS" : "");
493
494   return sb.data();
495}
496
497void OculusVRHMDDevice::updateRenderInfo()
498{
499   // Check console values first
500   if (mCurrentPixelDensity != OculusVRDevice::smDesiredPixelDensity)
501   {
502      mRenderConfigurationDirty = true;
503      mCurrentPixelDensity = OculusVRDevice::smDesiredPixelDensity;
504   }
505
506   if (!mIsValid || !mDevice || !mRenderConfigurationDirty)
507      return;
508
509   if (!mDrawCanvas)
510      return;
511   
512   PlatformWindow *window = mDrawCanvas->getPlatformWindow();
513
514   ovrHmdDesc desc = ovr_GetHmdDesc(mDevice);
515
516   // Update window size if it's incorrect
517   Point2I backbufferSize = mDrawCanvas->getBounds().extent;
518
519   // Finally setup!
520   if (!setupTargets())
521   {
522      onDeviceDestroy();
523      return;
524   }
525
526   mRenderConfigurationDirty = false;
527}
528
529Point2I OculusVRHMDDevice::generateRenderTarget(GFXTextureTargetRef &target, GFXTexHandle &depth, Point2I desiredSize)
530{
531    // Texture size that we already have might be big enough.
532    Point2I newRTSize;
533    bool newRT = false;
534    
535    if (!target.getPointer())
536    {
537       target = GFX->allocRenderToTextureTarget();
538       newRTSize = desiredSize;
539       newRT = true;
540    }
541    else
542    {
543       Point2I currentSize = target->getSize();
544       newRTSize = currentSize;
545    }
546
547    // %50 linear growth each time is a nice balance between being too greedy
548    // for a 2D surface and too slow to prevent fragmentation.
549    while ( newRTSize.x < desiredSize.x )
550    {
551        newRTSize.x += newRTSize.x/2;
552    }
553    while ( newRTSize.y < desiredSize.y )
554    {
555        newRTSize.y += newRTSize.y/2;
556    }
557
558    // Put some sane limits on it. 4k x 4k is fine for most modern video cards.
559    // Nobody should be messing around with surfaces smaller than 4k pixels these days.
560    newRTSize.setMin(Point2I(4096, 4096));
561    newRTSize.setMax(Point2I(64, 64));
562
563    // Stereo RT needs to be the same size as the recommended RT
564    /*if ( newRT || mDebugStereoTexture.getWidthHeight() != newRTSize )
565    {
566       mDebugStereoTexture.set( newRTSize.x, newRTSize.y, mRTFormat, &VRTextureProfile,  avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ) );
567       target->attachTexture( GFXTextureTarget::Color0, mDebugStereoTexture);
568       Con::printf("generateRenderTarget generated %x", mDebugStereoTexture.getPointer());
569    }*/
570
571    if ( depth.getWidthHeight() != newRTSize )
572    {
573       depth.set( newRTSize.x, newRTSize.y, GFXFormatD24S8, &VRDepthProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ) );
574       target->attachTexture( GFXTextureTarget::DepthStencil, depth );
575       Con::printf("generateRenderTarget generated depth %x", depth.getPointer());
576    }
577
578    return newRTSize;
579}
580
581void OculusVRHMDDevice::clearRenderTargets()
582{
583   mStereoRT = NULL;
584   mEyeRT[0] = NULL;
585   mEyeRT[1] = NULL;
586
587   if (mDebugMirrorTexture)
588   {
589      ovr_DestroyMirrorTexture(mDevice, mDebugMirrorTexture);
590      mDebugMirrorTexture = NULL;
591      mDebugMirrorTextureHandle = NULL;
592   }
593}
594
595void OculusVRHMDDevice::updateCaps()
596{
597   if (!mIsValid || !mDevice)
598      return;
599
600   ovr_SetEnabledCaps(mDevice, mCurrentCaps);
601}
602
603static bool sInFrame = false; // protects against recursive onStartFrame calls
604
605void OculusVRHMDDevice::onStartFrame()
606{
607   if (!mIsValid || !mDevice || !mDrawCanvas || sInFrame || mFrameReady)
608      return;
609
610   sInFrame = true;
611
612   ovrVector3f hmdToEyeViewOffset[2] = { mEyeRenderDesc[0].HmdToEyeViewOffset, mEyeRenderDesc[1].HmdToEyeViewOffset };
613   ovrTrackingState hmdState = ovr_GetTrackingState(mDevice, 0, ovrTrue);
614   ovr_CalcEyePoses(hmdState.HeadPose.ThePose, hmdToEyeViewOffset, mRenderLayer.RenderPose);
615
616   for (U32 i=0; i<2; i++)
617   {
618      mRenderLayer.RenderPose[i].Position.x *= OculusVRDevice::smPositionTrackingScale;
619      mRenderLayer.RenderPose[i].Position.y *= OculusVRDevice::smPositionTrackingScale;
620      mRenderLayer.RenderPose[i].Position.z *= OculusVRDevice::smPositionTrackingScale;
621   }
622
623   mRenderLayer.SensorSampleTime = ovr_GetTimeInSeconds();
624
625   // Set current dest texture on stereo render target
626   D3D11OculusTexture* texSwap = (D3D11OculusTexture*)mTextureSwapSet;
627   mStereoRT->attachTexture(GFXTextureTarget::Color0, texSwap->TexRtv[texSwap->TextureSet->CurrentIndex]);
628
629   sInFrame = false;
630   mFrameReady = true;
631}
632
633void OculusVRHMDDevice::onEndFrame()
634{
635   if (!mIsValid || !mDevice || !mDrawCanvas || sInFrame || !mFrameReady || !mTextureSwapSet)
636      return;
637
638   Point2I eyeSize;
639   GFXTarget *windowTarget = mDrawCanvas->getPlatformWindow()->getGFXTarget();
640
641   GFXD3D11Device *d3d11GFX = dynamic_cast<GFXD3D11Device*>(GFX);
642
643   ovrViewScaleDesc viewScaleDesc;
644   ovrVector3f hmdToEyeViewOffset[2] = { mEyeRenderDesc[0].HmdToEyeViewOffset, mEyeRenderDesc[1].HmdToEyeViewOffset };
645   viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f;
646   viewScaleDesc.HmdToEyeViewOffset[0] = hmdToEyeViewOffset[0];
647   viewScaleDesc.HmdToEyeViewOffset[1] = hmdToEyeViewOffset[1];
648
649
650   ovrLayerDirect           ld = { { ovrLayerType_Direct } };
651   mDebugRenderLayer = ld;
652
653   mDebugRenderLayer.ColorTexture[0] = mRenderLayer.ColorTexture[0];
654   mDebugRenderLayer.ColorTexture[1] = mRenderLayer.ColorTexture[1];
655   mDebugRenderLayer.Viewport[0] = mRenderLayer.Viewport[0];
656   mDebugRenderLayer.Viewport[1] = mRenderLayer.Viewport[1];
657
658   // TODO: use ovrViewScaleDesc
659   ovrLayerHeader* layers = &mRenderLayer.Header;
660   ovrResult result = ovr_SubmitFrame(mDevice, 0, &viewScaleDesc, &layers, 1);
661   mTextureSwapSet->AdvanceToNextTexture();
662
663   if (OVR_SUCCESS(result))
664   {
665      int woo = 1;
666   }
667
668   // TODO: render preview in display?
669
670   mFrameReady = false;
671}
672
673void OculusVRHMDDevice::getFrameEyePose(DisplayPose *outPose, U32 eyeId) const
674{
675   // Directly set the rotation and position from the eye transforms
676   ovrPosef pose = mRenderLayer.RenderPose[eyeId];
677   OVR::Quatf orientation = pose.Orientation;
678   const OVR::Vector3f position = pose.Position;
679
680   MatrixF torqueMat(1);
681   OVR::Matrix4f mat(orientation);
682   OculusVRUtil::convertRotation(mat.M, torqueMat);
683
684   outPose->orientation = QuatF(torqueMat);
685   outPose->position = Point3F(-position.x, position.z, -position.y);
686}
687
688void OculusVRHMDDevice::onDeviceDestroy()
689{
690   if (!mIsValid || !mDevice)
691      return;
692
693   if (mStereoRT.getPointer())
694   {
695      mStereoRT->zombify();
696   }
697
698   if (mEyeRT[1].getPointer() && mEyeRT[1] != mStereoRT)
699   {
700      mEyeRT[0]->zombify();
701      mEyeRT[1]->zombify();
702   }
703
704   if (mTextureSwapSet)
705   {
706      delete mTextureSwapSet;
707      mTextureSwapSet = NULL;
708   }
709
710   mStereoRT = NULL;
711   mStereoDepthTexture = NULL;
712
713   mEyeRT[0] = NULL;
714   mEyeRT[1] = NULL;
715
716   mRenderConfigurationDirty = true;
717}
718