bool D3D9Device::validateDeviceState(const D3D9RenderWindowCore* renderWindow)
	{
		RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);		
		RenderWindowResources* renderWindowResources =  it->second;
		HRESULT hr;

		hr = mpDevice->TestCooperativeLevel();	

		// Case device is not valid for rendering. 
		if (FAILED(hr))
		{					
			// device lost, and we can't reset
			// can't do anything about it here, wait until we get 
			// D3DERR_DEVICENOTRESET; rendering calls will silently fail until 
			// then (except Present, but we ignore device lost there too)
			if (hr == D3DERR_DEVICELOST)
			{						
				releaseRenderWindowResources(renderWindowResources);
				notifyDeviceLost();							
				return false;
			}

			// device lost, and we can reset
			else if (hr == D3DERR_DEVICENOTRESET)
			{					
				bool deviceRestored = reset();

				// Device was not restored yet.
				if (deviceRestored == false)
				{
					// Wait a while
					Sleep(50);					
					return false;
				}																								
			}						
		}

		// Render window resources explicitly invalidated. (Resize or window mode switch) 
		if (renderWindowResources->acquired == false)
		{
			if (getPrimaryWindow() == renderWindow)
			{
				bool deviceRestored = reset();

				// Device was not restored yet.
				if (deviceRestored == false)
				{
					// Wait a while
					Sleep(50);					
					return false;
				}	
			}
			else
			{
				acquire(renderWindow);
			}
		}

		return true;
	}
Exemple #2
0
	void Application::onStartUp()
	{
		CoreApplication::onStartUp();

		PlainTextImporter* importer = bs_new<PlainTextImporter>();
		Importer::instance()._registerAssetImporter(importer);

		VirtualInput::startUp();
		BuiltinResources::startUp();
		RendererMaterialManager::startUp();
		RendererManager::instance().initialize();
		SpriteManager::startUp();
		GUIManager::startUp();
		ShortcutManager::startUp();

		Cursor::startUp();
		Cursor::instance().setCursor(CursorType::Arrow);
		Platform::setIcon(BuiltinResources::instance().getFrameworkIcon());

		SceneManager::instance().setMainRenderTarget(getPrimaryWindow());
		DebugDraw::startUp();

		ScriptManager::startUp();

		if(mStartUpDesc.scripting)
			loadScriptSystem();
	}
	void EditorApplication::onStartUp()
	{
		// Find the path to data files
		//// First, look for EditorData folder in the direct descendant of the working directory 
		if (FileSystem::exists("EditorData"))
		{
			mBuiltinDataPath = FileSystem::getWorkingDirectoryPath();
			mBuiltinDataPath.append("EditorData/");
		}
		else
		{
			// Then check the source distribution itself, in case we're running directly from the build directory
			mBuiltinDataPath = Path(RAW_APP_ROOT) + Path("Data/");

			if (!FileSystem::exists(mBuiltinDataPath))
				LOGERR("Cannot find builtin assets for the editor at path '" + mBuiltinDataPath.toString() + "'.");
		}

		Application::onStartUp();

		// In editor we render game on a separate surface, handled in Game window
		SceneManager::instance().setMainRenderTarget(nullptr);

		loadEditorSettings();
		mProjectSettings = bs_shared_ptr_new<ProjectSettings>();

		ScriptCodeImporter* scriptCodeImporter = bs_new<ScriptCodeImporter>();
		Importer::instance()._registerAssetImporter(scriptCodeImporter);

		// Hidden dependency: Needs to be done before BuiltinEditorResources import as shader include lookup requires it
		ProjectLibrary::startUp();

		BuiltinEditorResources::startUp();

		{
			auto inputConfig = VirtualInput::instance().getConfiguration();

			inputConfig->registerButton("Copy", BC_C, ButtonModifier::Ctrl);
			inputConfig->registerButton("Cut", BC_X, ButtonModifier::Ctrl);
			inputConfig->registerButton("Paste", BC_V, ButtonModifier::Ctrl);
		}

		UndoRedo::startUp();
		EditorWindowManager::startUp();
		EditorWidgetManager::startUp();
		DropDownWindowManager::startUp();

		ScenePicking::startUp();
		Selection::startUp();
		GizmoManager::startUp();
		BuildManager::startUp();
		CodeEditorManager::startUp();

		MainEditorWindow::create(getPrimaryWindow());
		ScriptManager::startUp();
	}
	void D3D9Device::validateFocusWindow()
	{
		// Focus window changed -> device should be re-acquired.
		if ((msSharedFocusWindow != NULL && mCreationParams.hFocusWindow != msSharedFocusWindow) ||
			(msSharedFocusWindow == NULL && mCreationParams.hFocusWindow != getPrimaryWindow()->_getWindowHandle()))
		{
			// Lock access to rendering device.
			D3D9RenderAPI::getResourceManager()->lockDeviceAccess();

			release();
			acquire();

			// UnLock access to rendering device.
			D3D9RenderAPI::getResourceManager()->unlockDeviceAccess();
		}
	}
	void D3D9Device::present(const D3D9RenderWindowCore* renderWindow)
	{		
		RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);
		RenderWindowResources*	renderWindowResources = it->second;				

		// Skip present while current device state is invalid.
		if (mDeviceLost || 
			renderWindowResources->acquired == false || 
			isDeviceLost())		
			return;		


		HRESULT hr;

		if (isMultihead())
		{
			// Only the master will call present method results in synchronized
			// buffer swap for the rest of the implicit swap chain.
			if (getPrimaryWindow() == renderWindow)
				hr = mpDevice->Present( NULL, NULL, NULL, NULL );
			else
				hr = S_OK;
		}
		else
		{
			hr = renderWindowResources->swapChain->Present(NULL, NULL, NULL, NULL, 0);			
		}


		if(D3DERR_DEVICELOST == hr)
		{
			releaseRenderWindowResources(renderWindowResources);
			notifyDeviceLost();
		}
		else if( FAILED(hr) )
		{
			BS_EXCEPT(RenderingAPIException, "Error Presenting surfaces");
		}
	}
	bool D3D9Device::acquire()
	{	
		updatePresentationParameters();

		bool resetDevice = false;
			
		// Create device if need to.
		if (mpDevice == nullptr)
		{			
			createD3D9Device();
		}
		else
		{
			RenderWindowToResorucesIterator itPrimary = getRenderWindowIterator(getPrimaryWindow());

			if (itPrimary->second->swapChain != nullptr)
			{
				D3DPRESENT_PARAMETERS currentPresentParams;
				HRESULT hr;

				hr = itPrimary->second->swapChain->GetPresentParameters(&currentPresentParams);
				if (FAILED(hr))
				{
					BS_EXCEPT(RenderingAPIException, "GetPresentParameters failed");
				}
				
				// Desired parameters are different then current parameters.
				// Possible scenario is that primary window resized and in the mean while another
				// window attached to this device.
				if (memcmp(&currentPresentParams, &mPresentationParams[0], sizeof(D3DPRESENT_PARAMETERS)) != 0)
				{
					resetDevice = true;					
				}				
			}

			// Make sure depth stencil is set to valid surface. It is going to be
			// grabbed by the primary window using the GetDepthStencilSurface method.
			if (resetDevice == false)
			{
				mpDevice->SetDepthStencilSurface(itPrimary->second->depthBuffer);
			}
			
		}

		// Reset device will update all render window resources.
		if (resetDevice)
		{
			reset();
		}
		else // No need to reset -> just acquire resources.
		{
			// Update resources of each window.
			RenderWindowToResorucesIterator it = mMapRenderWindowToResoruces.begin();

			while (it != mMapRenderWindowToResoruces.end())
			{
				acquireRenderWindowResources(it);
				++it;
			}
		}
									
		return true;
	}
	void D3D9Device::createD3D9Device()
	{		
		// Update focus window.
		const D3D9RenderWindowCore* primaryRenderWindow = getPrimaryWindow();

		// Case we have to share the same focus window.
		if (msSharedFocusWindow != NULL)
			mFocusWindow = msSharedFocusWindow;
		else
			mFocusWindow = primaryRenderWindow->_getWindowHandle();		

		IDirect3D9* pD3D9 = D3D9RenderAPI::getDirect3D9();
		HRESULT hr;

		if (isMultihead())
		{
			mBehaviorFlags |= D3DCREATE_ADAPTERGROUP_DEVICE;
		}		
		else
		{
			mBehaviorFlags &= ~D3DCREATE_ADAPTERGROUP_DEVICE;
		}

		// Try to create the device with hardware vertex processing. 
		mBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
		hr = pD3D9->CreateDevice(mAdapterNumber, mDeviceType, mFocusWindow,
			mBehaviorFlags, mPresentationParams, &mpDevice);

		if (FAILED(hr))
		{
			// Try a second time, may fail the first time due to back buffer count,
			// which will be corrected down to 1 by the runtime
			hr = pD3D9->CreateDevice(mAdapterNumber, mDeviceType, mFocusWindow,
				mBehaviorFlags, mPresentationParams, &mpDevice);
		}

		// Case hardware vertex processing failed.
		if (FAILED(hr))
		{
			// Try to create the device with mixed vertex processing.
			mBehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;
			mBehaviorFlags |= D3DCREATE_MIXED_VERTEXPROCESSING;

			hr = pD3D9->CreateDevice(mAdapterNumber, mDeviceType, mFocusWindow,
				mBehaviorFlags, mPresentationParams, &mpDevice);
		}

		if (FAILED(hr))
		{
			// Try to create the device with software vertex processing.
			mBehaviorFlags &= ~D3DCREATE_MIXED_VERTEXPROCESSING;
			mBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
			hr = pD3D9->CreateDevice(mAdapterNumber, mDeviceType, mFocusWindow,
				mBehaviorFlags, mPresentationParams, &mpDevice);
		}

		if (FAILED(hr))
		{
			// Try reference device
			mDeviceType = D3DDEVTYPE_REF;
			hr = pD3D9->CreateDevice(mAdapterNumber, mDeviceType, mFocusWindow,
				mBehaviorFlags, mPresentationParams, &mpDevice);

			if (FAILED(hr))
			{
				BS_EXCEPT(RenderingAPIException, "Cannot create device!");
			}
		}

		// Get current device caps.
		hr = mpDevice->GetDeviceCaps(&mD3D9DeviceCaps);
		if (FAILED(hr))
		{
			BS_EXCEPT(RenderingAPIException, "Cannot get device caps!");
		}

		// Get current creation parameters caps.
		hr = mpDevice->GetCreationParameters(&mCreationParams);
		if (FAILED(hr) )
		{
			BS_EXCEPT(RenderingAPIException, "Error Get Creation Parameters");
		}

		mD3D9DeviceCapsValid = true;

		// Lock access to rendering device.
		D3D9RenderAPI::getResourceManager()->lockDeviceAccess();

		D3D9Device* pCurActiveDevice = mpDeviceManager->getActiveDevice();

		mpDeviceManager->setActiveDevice(this);

		// Inform all resources that new device created.
		D3D9RenderAPI::getResourceManager()->notifyOnDeviceCreate(mpDevice);

		mpDeviceManager->setActiveDevice(pCurActiveDevice);

		// UnLock access to rendering device.
		D3D9RenderAPI::getResourceManager()->unlockDeviceAccess();
	}