boost::optional<osvr::common::elements::AliasElement> getAliasElement(osvr::clientkit::ClientContext &ctx, std::string const &path) { osvr::common::PathNode const *node = nullptr; try { node = &(ctx.get()->getPathTree().getNodeByPath(path)); } catch (std::exception &e) { cerr << "Could not get node at path '" << path << "' - exception: " << e.what() << endl; return boost::none; } auto elt = boost::get<osvr::common::elements::AliasElement>(&node->value()); if (!elt) { return boost::none; } return *elt; }
/** * Handle OSVR direct mode. ***/ void* OSVR_DirectMode::Provoke(void* pThis, int eD3D, int eD3DInterface, int eD3DMethod, DWORD dwNumberConnected, int& nProvokerIndex) { if (eD3DInterface != INTERFACE_IDXGISWAPCHAIN) return nullptr; if (eD3DMethod != METHOD_IDXGISWAPCHAIN_PRESENT) return nullptr; if (!m_bHotkeySwitch) { if (GetAsyncKeyState(VK_F11)) { m_bHotkeySwitch = true; } return nullptr; } // Get an OSVR client context to use to access the devices // that we need. static osvr::clientkit::ClientContext m_pcClientContext = osvr::clientkit::ClientContext("com.mtbs3d.vireio.osvr.directmode"); if (m_pcRenderManager == nullptr) { // get device and context ID3D11Device* pcDevice = nullptr; ID3D11DeviceContext* pcContext = nullptr; switch (m_eMethod) { case OSVR_undefined: // TODO !! determine method by used DX version return nullptr; case OSVR_D3D11_use_Game_Device: if (FAILED(GetDeviceAndContext((IDXGISwapChain*)pThis, &pcDevice, &pcContext))) { OutputDebugString(L"OSVR-DirectMode: Failed to get d3d11 device + context"); return nullptr; } break; case OSVR_D3D11_own_Device: case OSVR_D3D10_own_Device: case OSVR_D3D9_own_Device: { // get game device + context if (m_eMethod == OSVR_DirectModeMethods::OSVR_D3D11_own_Device) { if (FAILED(GetDeviceAndContext((IDXGISwapChain*)pThis, &m_pcGameDevice, &m_pcGameDeviceContext))) { OutputDebugString(L"OSVR-DirectMode: Failed to get d3d11 device + context"); return nullptr; } m_pcGameDevice->Release(); m_pcGameDeviceContext->Release(); } // Be sure to get D3D11 and have set // D3D11_CREATE_DEVICE_BGRA_SUPPORT in the device/context D3D_FEATURE_LEVEL acceptibleAPI = D3D_FEATURE_LEVEL_11_0; D3D_FEATURE_LEVEL foundAPI; auto hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_BGRA_SUPPORT, &acceptibleAPI, 1, D3D11_SDK_VERSION, &m_pcDevice, &foundAPI, &m_pcDeviceContext); if (FAILED(hr)) { OutputDebugString(L"Could not create D3D11 device and context"); return nullptr; } pcDevice = m_pcDevice; pcContext = m_pcDeviceContext; } break; default: break; } // Put the device and context into a structure to let RenderManager // know to use this one rather than creating its own. osvr::renderkit::GraphicsLibrary cLibrary; cLibrary.D3D11 = new osvr::renderkit::GraphicsLibraryD3D11; cLibrary.D3D11->device = pcDevice; cLibrary.D3D11->context = pcContext; if (m_eMethod == OSVR_DirectModeMethods::OSVR_D3D11_use_Game_Device) { if (pcDevice) { pcDevice->Release(); pcDevice = nullptr; } if (pcContext) { pcContext->Release(); pcContext = nullptr; } } // Open Direct3D and set up the context for rendering to // an HMD. Do this using the OSVR RenderManager interface, // which maps to the nVidia or other vendor direct mode // to reduce the latency. m_pcRenderManager = osvr::renderkit::createRenderManager(m_pcClientContext.get(), "Direct3D11", cLibrary); if ((m_pcRenderManager == nullptr) || (!m_pcRenderManager->doingOkay())) { // Error OutputDebugString(L"OSVR-DirectMode: [Error] No Render Manager available !"); } else { // Set callback to handle setting up rendering in a display m_pcRenderManager->SetDisplayCallback((osvr::renderkit::DisplayCallback)&OSVR_DirectMode::SetupDisplay); // Register callback to render things in world space. m_pcRenderManager->AddRenderCallback("/", (osvr::renderkit::RenderCallback)&OSVR_DirectMode::DrawWorld); // Open the display and make sure this worked. osvr::renderkit::RenderManager::OpenResults ret = m_pcRenderManager->OpenDisplay(); if (ret.status == osvr::renderkit::RenderManager::OpenStatus::FAILURE) { OutputDebugString(L"Could not open display"); } if (ret.library.D3D11 == nullptr) { OutputDebugString(L"Attempted to run a Direct3D11 program with a config file that specified a different renderling library."); } // Do a call to get the information we need to construct our // color and depth render-to-texture buffers. std::vector<osvr::renderkit::RenderInfo> asRenderInfo; m_pcClientContext.update(); asRenderInfo = m_pcRenderManager->GetRenderInfo(); // Create the sampler state D3D11_SAMPLER_DESC sSampDesc; ZeroMemory(&sSampDesc, sizeof(sSampDesc)); sSampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; sSampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; sSampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; sSampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; sSampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; sSampDesc.MinLOD = 0; sSampDesc.MaxLOD = D3D11_FLOAT32_MAX; if (FAILED(asRenderInfo[0].library.D3D11->device->CreateSamplerState(&sSampDesc, &m_pcSamplerState))) OutputDebugString(L"Failed to create Sampler State."); } } else { // get device and context ID3D11Device* pcDevice = nullptr; ID3D11DeviceContext* pcContext = nullptr; switch (m_eMethod) { case OSVR_undefined: return nullptr; case OSVR_D3D11_use_Game_Device: if (FAILED(GetDeviceAndContext((IDXGISwapChain*)pThis, &pcDevice, &pcContext))) { OutputDebugString(L"OSVR-DirectMode: Failed to get d3d11 device + context"); // release frame texture+view if (pcDevice) { pcDevice->Release(); pcDevice = nullptr; } if (pcContext) { pcContext->Release(); pcContext = nullptr; } return nullptr; } break; case OSVR_D3D11_own_Device: case OSVR_D3D10_own_Device: case OSVR_D3D9_own_Device: pcDevice = m_pcDevice; pcContext = m_pcDeviceContext; break; default: break; } // backup device states, if game device is used D3DX11_STATE_BLOCK sStateBlock; if (m_eMethod == OSVR_DirectModeMethods::OSVR_D3D11_use_Game_Device) { // backup all states CreateStateblock(pcContext, &sStateBlock); // clear all states pcContext->ClearState(); } // Update the context so we get our callbacks called and // update tracker state. m_pcClientContext.update(); if (!m_pcRenderManager->Render()) { OutputDebugString(L"Render() returned false, maybe because it was asked to quit"); } // apply state block, if game device is used if (m_eMethod == OSVR_DirectModeMethods::OSVR_D3D11_use_Game_Device) { // set back device ApplyStateblock(pcContext, &sStateBlock); if (pcDevice) { pcDevice->Release(); pcDevice = nullptr; } if (pcContext) { pcContext->Release(); pcContext = nullptr; } } } return nullptr; }