Exemple #1
0
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;
}