oculusVRHMDDevice.cpp
Engine/source/platform/input/oculusVR/oculusVRHMDDevice.cpp
Classes:
class
class
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