//---------------------------------------------------------------------
	BOOL D3D11VideoModeList::enumerate()
	{
		//		int pD3D = mDriver->getD3D();
		UINT adapter = mDriver->getAdapterNumber();
		HRESULT hr;
		IDXGIOutput *pOutput;
		for( int iOutput = 0; ; ++iOutput )
		{
			//AIZTODO: one output for a single monitor ,to be handled for mulimon	    
			hr = mDriver->getDeviceAdapter()->EnumOutputs( iOutput, &pOutput );
			if( DXGI_ERROR_NOT_FOUND == hr )
			{
				return false;
			}
			else if (FAILED(hr))
			{
				return false;	//Something bad happened.
			}
			else //Success!
			{
				DXGI_OUTPUT_DESC OutputDesc;
				pOutput->GetDesc(&OutputDesc);

				UINT NumModes = 0;
                hr = pOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM,
                    0,
                    &NumModes,
                    NULL );

                DXGI_MODE_DESC *pDesc = new DXGI_MODE_DESC[ NumModes ];
                ZeroMemory(pDesc, sizeof(DXGI_MODE_DESC) * NumModes);
				hr = pOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM,
					0,
					&NumModes,
					pDesc );
				
				SAFE_RELEASE(pOutput);

				// display mode list can not be obtained when working over terminal session
				if(FAILED(hr))
				{
					NumModes = 0;

					if(hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
					{
						pDesc[0].Width = 800;
						pDesc[0].Height = 600;
						pDesc[0].RefreshRate.Numerator = 60;
						pDesc[0].RefreshRate.Denominator = 1;
						pDesc[0].Format = DXGI_FORMAT_R8G8B8A8_UNORM;
						pDesc[0].ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
						pDesc[0].Scaling = DXGI_MODE_SCALING_UNSPECIFIED;

						NumModes = 1;
					}
				}

				for( UINT m=0; m<NumModes; m++ )
				{
					DXGI_MODE_DESC displayMode=pDesc[m];
					// Filter out low-resolutions
					if( displayMode.Width < 640 || displayMode.Height < 400 )
						continue;

					// Check to see if it is already in the list (to filter out refresh rates)
					BOOL found = FALSE;
					vector<D3D11VideoMode>::type::iterator it;
					for( it = mModeList.begin(); it != mModeList.end(); it++ )
					{
						DXGI_OUTPUT_DESC oldOutput= it->getDisplayMode();
						DXGI_MODE_DESC oldDisp = it->getModeDesc();
						if(//oldOutput.Monitor==OutputDesc.Monitor &&
							oldDisp.Width == displayMode.Width &&
							oldDisp.Height == displayMode.Height// &&
							//oldDisp.Format == displayMode.Format
							)
						{
							// Check refresh rate and favour higher if poss
							//if (oldDisp.RefreshRate < displayMode.RefreshRate)
							//	it->increaseRefreshRate(displayMode.RefreshRate);
							found = TRUE;
							break;
						}
					}

					if( !found )
						mModeList.push_back( D3D11VideoMode( OutputDesc,displayMode ) );

				}
                delete [] pDesc;
			}
		}
		/*	
		UINT iMode;
		for( iMode=0; iMode < pD3D->GetAdapterModeCount( adapter, D3DFMT_R5G6B5 ); iMode++ )
		{
		DXGI_OUTPUT_DESC displayMode;
		pD3D->EnumAdapterModes( adapter, D3DFMT_R5G6B5, iMode, &displayMode );

		// Filter out low-resolutions
		if( displayMode.Width < 640 || displayMode.Height < 400 )
		continue;

		// Check to see if it is already in the list (to filter out refresh rates)
		BOOL found = FALSE;
		vector<D3D11VideoMode>::type::iterator it;
		for( it = mModeList.begin(); it != mModeList.end(); it++ )
		{
		DXGI_OUTPUT_DESC oldDisp = it->getDisplayMode();
		if( oldDisp.Width == displayMode.Width &&
		oldDisp.Height == displayMode.Height &&
		oldDisp.Format == displayMode.Format )
		{
		// Check refresh rate and favour higher if poss
		if (oldDisp.RefreshRate < displayMode.RefreshRate)
		it->increaseRefreshRate(displayMode.RefreshRate);
		found = TRUE;
		break;
		}
		}

		if( !found )
		mModeList.push_back( D3D11VideoMode( displayMode ) );
		}

		for( iMode=0; iMode < pD3D->GetAdapterModeCount( adapter, D3DFMT_X8R8G8B8 ); iMode++ )
		{
		DXGI_OUTPUT_DESC displayMode;
		pD3D->EnumAdapterModes( adapter, D3DFMT_X8R8G8B8, iMode, &displayMode );

		// Filter out low-resolutions
		if( displayMode.Width < 640 || displayMode.Height < 400 )
		continue;

		// Check to see if it is already in the list (to filter out refresh rates)
		BOOL found = FALSE;
		vector<D3D11VideoMode>::type::iterator it;
		for( it = mModeList.begin(); it != mModeList.end(); it++ )
		{
		DXGI_OUTPUT_DESC oldDisp = it->getDisplayMode();
		if( oldDisp.Width == displayMode.Width &&
		oldDisp.Height == displayMode.Height &&
		oldDisp.Format == displayMode.Format )
		{
		// Check refresh rate and favour higher if poss
		if (oldDisp.RefreshRate < displayMode.RefreshRate)
		it->increaseRefreshRate(displayMode.RefreshRate);
		found = TRUE;
		break;
		}
		}

		if( !found )
		mModeList.push_back( D3D11VideoMode( displayMode ) );
		}
		*/
		return TRUE;
	}
Example #2
0
void GetDisplayDevices(DeviceOutputs &deviceList)
{
    HRESULT err;

    deviceList.ClearData();

#ifdef USE_DXGI1_2
    REFIID iidVal = OSGetVersion() >= 8 ? __uuidof(IDXGIFactory2) : __uuidof(IDXGIFactory1);
#else
    REFIIF iidVal = __uuidof(IDXGIFactory1);
#endif

    IDXGIFactory1 *factory;
    if(SUCCEEDED(err = CreateDXGIFactory1(iidVal, (void**)&factory)))
    {
        UINT i=0;
        IDXGIAdapter1 *giAdapter;

        while(factory->EnumAdapters1(i++, &giAdapter) == S_OK)
        {
            Log(TEXT("------------------------------------------"));

            DXGI_ADAPTER_DESC adapterDesc;
            if(SUCCEEDED(err = giAdapter->GetDesc(&adapterDesc)))
            {
                if (adapterDesc.DedicatedVideoMemory != 0) {
                    DeviceOutputData &deviceData = *deviceList.devices.CreateNew();
                    deviceData.strDevice = adapterDesc.Description;

                    UINT j=0;
                    IDXGIOutput *giOutput;
                    while(giAdapter->EnumOutputs(j++, &giOutput) == S_OK)
                    {
                        DXGI_OUTPUT_DESC outputDesc;
                        if(SUCCEEDED(giOutput->GetDesc(&outputDesc)))
                        {
                            if(outputDesc.AttachedToDesktop)
                            {
                                deviceData.monitorNameList << outputDesc.DeviceName;

                                MonitorInfo &monitorInfo = *deviceData.monitors.CreateNew();
                                monitorInfo.hMonitor = outputDesc.Monitor;
                                mcpy(&monitorInfo.rect, &outputDesc.DesktopCoordinates, sizeof(RECT));
                            }
                        }

                        giOutput->Release();
                    }
                }
            }
            else
                AppWarning(TEXT("Could not query adapter %u"), i);

            giAdapter->Release();
        }

        factory->Release();
    }
}
Example #3
0
void LogVideoCardStats()
{
    HRESULT err;

#ifdef USE_DXGI1_2
    REFIID iidVal = OSGetVersion() >= 8 ? __uuidof(IDXGIFactory2) : __uuidof(IDXGIFactory1);
#else
    REFIIF iidVal = __uuidof(IDXGIFactory1);
#endif

    IDXGIFactory1 *factory;
    if(SUCCEEDED(err = CreateDXGIFactory1(iidVal, (void**)&factory)))
    {
        UINT i=0;
        IDXGIAdapter1 *giAdapter;

        while(factory->EnumAdapters1(i++, &giAdapter) == S_OK)
        {
            DXGI_ADAPTER_DESC adapterDesc;
            if(SUCCEEDED(err = giAdapter->GetDesc(&adapterDesc)))
            {
                if (!(adapterDesc.VendorId == 0x1414 && adapterDesc.DeviceId == 0x8c)) { // Ignore Microsoft Basic Render Driver
                    Log(TEXT("------------------------------------------"));
                    Log(TEXT("Adapter %u"), i);
                    Log(TEXT("  Video Adapter: %s"), adapterDesc.Description);
                    Log(TEXT("  Video Adapter Dedicated Video Memory: %u"), adapterDesc.DedicatedVideoMemory);
                    Log(TEXT("  Video Adapter Shared System Memory: %u"), adapterDesc.SharedSystemMemory);

                    UINT j = 0;
                    IDXGIOutput *output;
                    while(SUCCEEDED(giAdapter->EnumOutputs(j++, &output)))
                    {
                        DXGI_OUTPUT_DESC desc;
                        if(SUCCEEDED(output->GetDesc(&desc)))
                            Log(TEXT("  Video Adapter Output %u: pos={%d, %d}, size={%d, %d}, attached=%s"), j,
                                desc.DesktopCoordinates.left, desc.DesktopCoordinates.top,
                                desc.DesktopCoordinates.right-desc.DesktopCoordinates.left, desc.DesktopCoordinates.bottom-desc.DesktopCoordinates.top,
                                desc.AttachedToDesktop ? L"true" : L"false");
                        output->Release();
                    }
                }
            }
            else
                AppWarning(TEXT("Could not query adapter %u"), i);

            giAdapter->Release();
        }

        factory->Release();
    }
}
Example #4
0
	DXGI_OUTPUT_DESC D3D11Driver::getOutputDesc(UINT32 adapterOutputIdx) const
	{
		DXGI_OUTPUT_DESC desc;
		
		IDXGIOutput* output = nullptr;
		if(mDXGIAdapter->EnumOutputs(adapterOutputIdx, &output) == DXGI_ERROR_NOT_FOUND)
		{
			BS_EXCEPT(InvalidParametersException, "Cannot find output with the specified index: " + toString(adapterOutputIdx));
		}

		output->GetDesc(&desc);

		SAFE_RELEASE(output);

		return desc;
	}
Example #5
0
	unsigned short Ogre::MonitorInfo::getMonitorSequentialNumberFromSwapChain(IDXGISwapChain* swapChain, bool allowRefresh /*= false*/)
	{
		IDXGIOutput* output;
		int monitorSequencialNumber = -1;
		if(swapChain != NULL)
		{
			HRESULT hr = swapChain->GetContainingOutput(&output);
			if(hr == S_OK)
			{
				DXGI_OUTPUT_DESC desc;
				output->GetDesc(&desc);
				monitorSequencialNumber = getMonitorSequentialNumberFromHMonitor(desc.Monitor, allowRefresh);
			}
		}
		return monitorSequencialNumber;
	}
Example #6
0
//--------------------------------------------------------------------------------------
HRESULT CD3D11Enumeration::EnumerateOutputs( CD3D11EnumAdapterInfo* pAdapterInfo )
{
    HRESULT hr;
    IDXGIOutput* pOutput;

    for( int iOutput = 0; ; ++iOutput )
    {
        pOutput = NULL;
        hr = pAdapterInfo->m_pAdapter->EnumOutputs( iOutput, &pOutput );
        if( DXGI_ERROR_NOT_FOUND == hr )
        {
            return S_OK;
        }
        else if( FAILED( hr ) )
        {
            return hr;	//Something bad happened.
        }
        else //Success!
        {
            CD3D11EnumOutputInfo* pOutputInfo = new CD3D11EnumOutputInfo;
            if( !pOutputInfo )
            {
                SAFE_RELEASE( pOutput );
                return E_OUTOFMEMORY;
            }
            ZeroMemory( pOutputInfo, sizeof( CD3D11EnumOutputInfo ) );
            pOutput->GetDesc( &pOutputInfo->Desc );
            pOutputInfo->Output = iOutput;
            pOutputInfo->m_pOutput = pOutput;

            EnumerateDisplayModes( pOutputInfo );
            if( pOutputInfo->displayModeList.GetSize() <= 0 )
            {
                // If this output has no valid display mode, do not save it.
                delete pOutputInfo;
                continue;
            }

            hr = pAdapterInfo->outputInfoList.Add( pOutputInfo );
            if( FAILED( hr ) )
            {
                delete pOutputInfo;
                return hr;
            }
        }
    }
}
//-----------------------------------------------------------------------------
void EnumerateUsingDXGI( IDXGIFactory* pDXGIFactory )
{
    assert( pDXGIFactory != 0 );

    for( UINT index = 0; ; ++index )
    {
        IDXGIAdapter* pAdapter = nullptr;
        HRESULT hr = pDXGIFactory->EnumAdapters( index, &pAdapter );
        if( FAILED( hr ) ) // DXGIERR_NOT_FOUND is expected when the end of the list is hit
            break;

        DXGI_ADAPTER_DESC desc;
        memset( &desc, 0, sizeof( DXGI_ADAPTER_DESC ) );
        if( SUCCEEDED( pAdapter->GetDesc( &desc ) ) )
        {
            wprintf( L"\nDXGI Adapter: %u\nDescription: %s\n", index, desc.Description );

            for( UINT iOutput = 0; ; ++iOutput )
            {
                IDXGIOutput* pOutput = nullptr;
                hr = pAdapter->EnumOutputs( iOutput, &pOutput );
                if( FAILED( hr ) ) // DXGIERR_NOT_FOUND is expected when the end of the list is hit
                    break;

                DXGI_OUTPUT_DESC outputDesc;
                memset( &outputDesc, 0, sizeof( DXGI_OUTPUT_DESC ) );
                if( SUCCEEDED( pOutput->GetDesc( &outputDesc ) ) )
                {
                    wprintf( L"hMonitor: 0x%0.8Ix\n", ( DWORD_PTR )outputDesc.Monitor );
                    wprintf( L"hMonitor Device Name: %s\n", outputDesc.DeviceName );
                }

                SAFE_RELEASE( pOutput );
            }

            wprintf(
                L"\tGetVideoMemoryViaDXGI\n\t\tDedicatedVideoMemory: %Iu MB (%Iu)\n\t\tDedicatedSystemMemory: %Iu MB (%Iu)\n\t\tSharedSystemMemory: %Iu MB (%Iu)\n",
                desc.DedicatedVideoMemory / 1024 / 1024, desc.DedicatedVideoMemory,
                desc.DedicatedSystemMemory / 1024 / 1024, desc.DedicatedSystemMemory,
                desc.SharedSystemMemory / 1024 / 1024, desc.SharedSystemMemory );
        }

        SAFE_RELEASE( pAdapter );
    }
}
Example #8
0
void Application::LogAdapterOutputs(IDXGIAdapter* adapter)
{
    UINT i = 0;
    IDXGIOutput* output = nullptr;
    while (adapter->EnumOutputs(i, &output) != DXGI_ERROR_NOT_FOUND)
    {
        DXGI_OUTPUT_DESC desc;
        output->GetDesc(&desc);

        wstring text = L"***OUTPUT: ";
        text += desc.DeviceName;
        text += L"\n";
        OutputDebugString(text.c_str());
        LogOutputDisplayModes(output, _backBufferFormat);
        ReleaseCom(output);
        ++i;
    }
}
Example #9
0
//--------------------------------------------------------------------------------------
HRESULT CD3D11Enumeration::EnumerateOutputs( _In_ CD3D11EnumAdapterInfo* pAdapterInfo )
{
    HRESULT hr;
    IDXGIOutput* pOutput;

    for( int iOutput = 0; ; ++iOutput )
    {
        pOutput = nullptr;
        hr = pAdapterInfo->m_pAdapter->EnumOutputs( iOutput, &pOutput );
        if( DXGI_ERROR_NOT_FOUND == hr )
        {
            return S_OK;
        }
        else if( FAILED( hr ) )
        {
            return hr;	//Something bad happened.
        }
        else //Success!
        {
            CD3D11EnumOutputInfo* pOutputInfo = new (std::nothrow) CD3D11EnumOutputInfo;
            if( !pOutputInfo )
            {
                SAFE_RELEASE( pOutput );
                return E_OUTOFMEMORY;
            }
            pOutputInfo->Output = iOutput;
            pOutputInfo->m_pOutput = pOutput;
            pOutput->GetDesc( &pOutputInfo->Desc );

            EnumerateDisplayModes( pOutputInfo );
            if( pOutputInfo->displayModeList.empty() )
            {
                // If this output has no valid display mode, do not save it.
                delete pOutputInfo;
                continue;
            }

            pAdapterInfo->outputInfoList.push_back( pOutputInfo );
        }
    }
}
Example #10
0
static string getOutputName( IDXGISwapChain* pSwapChain )
{
    string sRet = "";

    if ( pSwapChain )
    {
        IDXGIOutput* pOutput = NULL;
        pSwapChain->GetContainingOutput( &pOutput );

        if ( pOutput )
        {
            DXGI_OUTPUT_DESC desc;

            if ( SUCCEEDED( pOutput->GetDesc( &desc ) ) )
            {
                sRet = PluginManager::UTF82ACP( PluginManager::UCS22UTF8( desc.DeviceName ) );
            }

            SAFE_RELEASE( pOutput );
        }
    }

    return sRet;
}
void LogAdapterOutputs(IDXGIAdapter* adapter)
{
	UINT i = 0;
	//monitors...
	IDXGIOutput* output = nullptr;
	while (adapter->EnumOutputs(i, &output) != DXGI_ERROR_NOT_FOUND)
	{
		//hey monitor tell me something about yourself
		DXGI_OUTPUT_DESC desc;
		output->GetDesc(&desc);

		std::wstring text = L"Output: ";
		text += desc.DeviceName;
		text += L"\n";

		wcout << text.c_str() << endl;
		LogOutputDisplayModes(output);

		output->Release();
		output = nullptr;

		i++;
	}
}
bool D3D12MemoryManagement::HandleMessage(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
    bool bHandled = DX12Framework::HandleMessage(hwnd, Message, wParam, lParam);
    if (bHandled)
    {
        return true;
    }

    switch (Message)
    {
    case WM_MOUSEWHEEL:
        {
            // Use mouse wheel to apply camera zoom.
            m_pCapturedCamera->OnMouseWheel(GET_WHEEL_DELTA_WPARAM(wParam));
            return true;
        }

    case WM_LBUTTONDOWN:
        {
            // Use left mouse button and movement for panning.
            m_MouseX = (int)LOWORD(lParam);
            m_MouseY = (int)HIWORD(lParam);
            m_bMouseDown = true;

            SetCapture(m_Hwnd);
            return true;
        }

    case WM_LBUTTONUP:
        {
            m_bMouseDown = false;
            ReleaseCapture();
            return true;
        }

    case WM_MOUSEMOVE:
        {
            if (m_bMouseDown)
            {
                int xPos = (int)(short)LOWORD(lParam);
                int yPos = (int)(short)HIWORD(lParam);

                float DeltaScrollX = (float)(xPos - m_MouseX);
                float DeltaScrollY = (float)(yPos - m_MouseY);

                if (m_pCapturedCamera == &m_ViewportCamera)
                {
                    m_pCapturedCamera->OnMouseMove(PointF{ DeltaScrollX, DeltaScrollY });
                }
                else
                {
                    //
                    // Move the debug camera relative to the viewport camera's coordinate space.
                    //
                    float zoom = m_pCapturedCamera->GetZoom() / m_ViewportCamera.GetZoom();
                    m_pCapturedCamera->OnMouseMove(PointF{ -DeltaScrollX * zoom, -DeltaScrollY * zoom });
                }

                m_MouseX = xPos;
                m_MouseY = yPos;
            }

            return true;
        }

    //
    // On window resize, adjust the camera perspective to match the new window size.
    //
    case WM_SIZE:
        {
            RectF NewProjection =
            {
                -m_WindowWidth / 2.0f,
                -m_WindowHeight / 2.0f,
                m_WindowWidth / 2.0f,
                m_WindowHeight / 2.0f,
            };
            m_pCapturedCamera->SetOrthographicProjection(NewProjection);
            return true;
        }

    case WM_KEYDOWN:
        {
            if (wParam == GetVirtualKeyFromCharacter('s')) // Toggle 's'tats.
            {
                m_bRenderStats = !m_bRenderStats;
            }
            else if (wParam == GetVirtualKeyFromCharacter('m')) // View 'm'ip coloring.
            {
                m_bDrawMipColors = !m_bDrawMipColors;
            }
            else if (wParam == GetVirtualKeyFromCharacter('v')) // Toggle 'v'sync.
            {
                m_bPresentOnVsync = !m_bPresentOnVsync;
            }
    #if(_DEBUG)
            //
            // In debug builds, allow simulated device removed errors for testing purposes.
            //
            else if (wParam == GetVirtualKeyFromCharacter('r')) // Simulate 'r'emove device.
            {
                m_SimulatedRenderResult = DXGI_ERROR_DEVICE_REMOVED;
                if (m_NewAdapterIndex == 0xFFFFFFFF)
                {
                    m_NewAdapterIndex = 0;
                }
                else
                {
                    // Toggle adapters 0 and 1.
                    m_NewAdapterIndex = !m_NewAdapterIndex;
                }
            }
            else if (wParam == GetVirtualKeyFromCharacter('e')) //  Simulate remove device without adapter toggle.
            {
                m_SimulatedRenderResult = DXGI_ERROR_DEVICE_REMOVED;
            }
    #endif
            else if (wParam == GetVirtualKeyFromCharacter('c')) // Toggle 'c'amera.
            {
                //
                // Toggle captured viewport - switched which viewport the mouse controls.
                //
                if (m_pCapturedCamera == &m_ViewportCamera)
                {
                    m_pCapturedCamera = &m_DebugCamera;
                }
                else
                {
                    m_pCapturedCamera = &m_ViewportCamera;
                }
            }
            else if (wParam == GetVirtualKeyFromCharacter('d')) // 'D'etach camera.
            {
                //
                // Toggle scene viewport - switches which camera is used as the scene camera
                // which determines prefetching and display behavior.
                //
                if (m_pSceneCamera == &m_ViewportCamera)
                {
                    m_pSceneCamera = &m_DebugCamera;
                }
                else
                {
                    m_pSceneCamera = &m_ViewportCamera;
                    m_pCapturedCamera = &m_ViewportCamera;
                }
            }
            else if (wParam == GetVirtualKeyFromCharacter('f')) // Toggle 'f'ullscreen mode.
            {
                HRESULT hr = S_OK;
                if (m_bFullscreen)
                {
                    SetWindowLongPtr(m_Hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
                    SetWindowPos(
                        m_Hwnd,
                        nullptr,
                        m_WindowRect.left,
                        m_WindowRect.top,
                        m_WindowRect.right - m_WindowRect.left,
                        m_WindowRect.bottom - m_WindowRect.top,
                        0);
                }
                else
                {
                    IDXGIOutput* pDXGIOutput;
                    hr = m_pDXGISwapChain->GetContainingOutput(&pDXGIOutput);
                    if (SUCCEEDED(hr))
                    {
                        DXGI_OUTPUT_DESC Desc;
                        pDXGIOutput->GetDesc(&Desc);

                        GetWindowRect(m_Hwnd, &m_WindowRect);
                        SetWindowLongPtr(m_Hwnd, GWL_STYLE, WS_POPUP);
                        SetWindowPos(
                            m_Hwnd,
                            HWND_TOP,
                            Desc.DesktopCoordinates.left,
                            Desc.DesktopCoordinates.top,
                            Desc.DesktopCoordinates.right - Desc.DesktopCoordinates.left,
                            Desc.DesktopCoordinates.bottom - Desc.DesktopCoordinates.top,
                            SWP_FRAMECHANGED | SWP_SHOWWINDOW);

                        pDXGIOutput->Release();
                    }
                }

                if (SUCCEEDED(hr))
                {
                    ShowWindow(m_Hwnd, SW_SHOWNORMAL);
                    m_bFullscreen = !m_bFullscreen;
                }

            }
            //
            // Budget overrides in debug builds.
            //
            else if (wParam == VK_OEM_PLUS || wParam == VK_ADD) // '+' - Increase budget.
            {
                UINT64 CurrentOverride = GetLocalBudgetOverride();
                CurrentOverride += _128MB;
                SetLocalBudgetOverride(CurrentOverride);
            }
            else if (wParam == VK_OEM_MINUS || wParam == VK_SUBTRACT) // '-' - Decrease budget.
            {
                UINT64 CurrentOverride = GetLocalBudgetOverride();
                if (CurrentOverride > _128MB)
                {
                    CurrentOverride -= _128MB;
                }
                else
                {
                    CurrentOverride = 0;
                }
                SetLocalBudgetOverride(CurrentOverride);
            }
            return true;
        }
    }
    return false;
}
int main() {

  printf("\n\ntest_win_api_directx_research\n\n");

  /* Retrieve a IDXGIFactory that can enumerate the adapters. */
  IDXGIFactory1* factory = NULL;
  HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&factory));

  if (S_OK != hr) {
    printf("Error: failed to retrieve the IDXGIFactory.\n");
    exit(EXIT_FAILURE);
  }

  /* Enumerate the adapters.*/
  UINT i = 0;
  IDXGIAdapter1* adapter = NULL;
  std::vector<IDXGIAdapter1*> adapters; /* Needs to be Released(). */

  while (DXGI_ERROR_NOT_FOUND != factory->EnumAdapters1(i, &adapter)) {
    adapters.push_back(adapter);
    ++i;
  }

  /* Get some info about the adapters (GPUs). */
  for (size_t i = 0; i < adapters.size(); ++i) {
    
    DXGI_ADAPTER_DESC1 desc;
    adapter = adapters[i];
    hr = adapter->GetDesc1(&desc);
    
    if (S_OK != hr) {
      printf("Error: failed to get a description for the adapter: %lu\n", i);
      continue;
    }

    wprintf(L"Adapter: %lu, description: %s\n", i, desc.Description);
  }

  /* Check what devices/monitors are attached to the adapters. */
  UINT dx = 0;
  IDXGIOutput* output = NULL;
  std::vector<IDXGIOutput*> outputs; /* Needs to be Released(). */
  
  for (size_t i = 0; i < adapters.size(); ++i) {

    dx = 0;
    adapter = adapters[i];
    
    while (DXGI_ERROR_NOT_FOUND != adapter->EnumOutputs(dx, &output)) {
      printf("Found monitor %d on adapter: %lu\n", dx, i);
      outputs.push_back(output);
      ++dx;
    }
  }

  if (0 >= outputs.size()) {
    printf("Error: no outputs found (%lu).\n", outputs.size());
    exit(EXIT_FAILURE);
  }

  /* Print some info about the monitors. */
  for (size_t i = 0; i < outputs.size(); ++i) {
    
    DXGI_OUTPUT_DESC desc;
    output = outputs[i];
    hr = output->GetDesc(&desc);
    
    if (S_OK != hr) {
      printf("Error: failed to retrieve a DXGI_OUTPUT_DESC for output %lu.\n", i);
      continue;
    }

    wprintf(L"Monitor: %s, attached to desktop: %c\n", desc.DeviceName, (desc.AttachedToDesktop) ? 'y' : 'n');
  }

  /*

    To get access to a OutputDuplication interface we need to have a 
    Direct3D device which handles the actuall rendering and "gpu" 
    stuff. According to a gamedev stackexchange it seems we can create
    one w/o a HWND. 

   */

  ID3D11Device* d3d_device = NULL; /* Needs to be released. */
  ID3D11DeviceContext* d3d_context = NULL; /* Needs to be released. */
  IDXGIAdapter1* d3d_adapter = NULL;
  D3D_FEATURE_LEVEL d3d_feature_level; /* The selected feature level (D3D version), selected from the Feature Levels array, which is NULL here; when it's NULL the default list is used see:  https://msdn.microsoft.com/en-us/library/windows/desktop/ff476082%28v=vs.85%29.aspx ) */
  
  { /* Start creating a D3D11 device */

#if 1
    /* 
       NOTE:  Apparently the D3D11CreateDevice function returns E_INVALIDARG, when
              you pass a pointer to an adapter for the first parameter and use the 
              D3D_DRIVER_TYPE_HARDWARE. When you want to pass a valid pointer for the
              adapter, you need to set the DriverType parameter (2nd) to 
              D3D_DRIVER_TYPE_UNKNOWN.
             
              @todo figure out what would be the best solution; easiest to use is 
              probably using NULL here. 
     */
    int use_adapter = 0;
    if (use_adapter >= adapters.size()) {
      printf("Invalid adapter index: %d, we only have: %lu - 1\n", use_adapter, adapters.size());
      exit(EXIT_FAILURE);
    }

    d3d_adapter = adapters[use_adapter];
    if (NULL == d3d_adapter) {
      printf("Error: the stored adapter is NULL.\n");
      exit(EXIT_FAILURE);
    }
#endif

    hr = D3D11CreateDevice(d3d_adapter,              /* Adapter: The adapter (video card) we want to use. We may use NULL to pick the default adapter. */  
                           D3D_DRIVER_TYPE_UNKNOWN,  /* DriverType: We use the GPU as backing device. */
                           NULL,                     /* Software: we're using a D3D_DRIVER_TYPE_HARDWARE so it's not applicaple. */
                           NULL,                     /* Flags: maybe we need to use D3D11_CREATE_DEVICE_BGRA_SUPPORT because desktop duplication is using this. */
                           NULL,                     /* Feature Levels (ptr to array):  what version to use. */
                           0,                        /* Number of feature levels. */
                           D3D11_SDK_VERSION,        /* The SDK version, use D3D11_SDK_VERSION */
                           &d3d_device,              /* OUT: the ID3D11Device object. */
                           &d3d_feature_level,       /* OUT: the selected feature level. */
                           &d3d_context);            /* OUT: the ID3D11DeviceContext that represents the above features. */

    if (S_OK != hr) {
      printf("Error: failed to create the D3D11 Device.\n");
      if (E_INVALIDARG == hr) {
        printf("Got INVALID arg passed into D3D11CreateDevice. Did you pass a adapter + a driver which is not the UNKNOWN driver?.\n");
      }
      exit(EXIT_FAILURE);
    }
    
  } /* End creating a D3D11 device. */
  
  /* 
     Create a IDXGIOutputDuplication for the first monitor. 
     
     - From a IDXGIOutput which represents an monitor, we query a IDXGIOutput1
       because the IDXGIOutput1 has the DuplicateOutput feature. 
  */

  IDXGIOutput1* output1 = NULL;
  IDXGIOutputDuplication* duplication = NULL;
  
  { /* Start IDGIOutputDuplication init. */
    
    int use_monitor = 0;
    if (use_monitor >= outputs.size()) {
      printf("Invalid monitor index: %d, we only have: %lu - 1\n", use_monitor, outputs.size());
      exit(EXIT_FAILURE);
    }

    output = outputs[use_monitor];
    if (NULL == output) {
      printf("No valid output found. The output is NULL.\n");
      exit(EXIT_FAILURE);
    }
    
    hr = output->QueryInterface(__uuidof(IDXGIOutput1), (void**)&output1);
    if (S_OK != hr) {
      printf("Error: failed to query the IDXGIOutput1 interface.\n");
      exit(EXIT_FAILURE);
    }

    hr = output1->DuplicateOutput(d3d_device, &duplication);
    if (S_OK != hr) {
      printf("Error: failed to create the duplication output.\n");
      exit(EXIT_FAILURE);
    }
    printf("Queried the IDXGIOutput1.\n");
                                
  } /* End IDGIOutputDuplication init. */

  if (NULL == duplication) {
    printf("Error: okay, we shouldn't arrive here but the duplication var is NULL.\n");
    exit(EXIT_FAILURE);
  }

  /*
    To download the pixel data from the GPU we need a 
    staging texture. Therefore we need to determine the width and 
    height of the buffers that we receive. 
    
    @TODO - We could also retrieve the width/height from the texture we got 
            from through the acquired frame (see the 'tex' variable below).
            That may be a safer solution.
  */
  DXGI_OUTPUT_DESC output_desc;
  {
    hr = output->GetDesc(&output_desc);
    if (S_OK != hr) {
      printf("Error: failed to get the DXGI_OUTPUT_DESC from the output (monitor). We need this to create a staging texture when downloading the pixels from the gpu.\n");
      exit(EXIT_FAILURE);
    }

    printf("The monitor has the following dimensions: left: %d, right: %d, top: %d, bottom: %d.\n"
           ,(int)output_desc.DesktopCoordinates.left
           ,(int)output_desc.DesktopCoordinates.right
           ,(int)output_desc.DesktopCoordinates.top
           ,(int)output_desc.DesktopCoordinates.bottom
           );
  }

  if (0 == output_desc.DesktopCoordinates.right
      || 0 == output_desc.DesktopCoordinates.bottom)
    {
      printf("The output desktop coordinates are invalid.\n");
      exit(EXIT_FAILURE);
    }
    
  /* Create the staging texture that we need to download the pixels from gpu. */
  D3D11_TEXTURE2D_DESC tex_desc;
  tex_desc.Width = output_desc.DesktopCoordinates.right;
  tex_desc.Height = output_desc.DesktopCoordinates.bottom;
  tex_desc.MipLevels = 1;
  tex_desc.ArraySize = 1; /* When using a texture array. */
  tex_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; /* This is the default data when using desktop duplication, see https://msdn.microsoft.com/en-us/library/windows/desktop/hh404611(v=vs.85).aspx */
  tex_desc.SampleDesc.Count = 1; /* MultiSampling, we can use 1 as we're just downloading an existing one. */
  tex_desc.SampleDesc.Quality = 0; /* "" */
  tex_desc.Usage = D3D11_USAGE_STAGING;
  tex_desc.BindFlags = 0;
  tex_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  tex_desc.MiscFlags = 0;

  ID3D11Texture2D* staging_tex = NULL;
  hr = d3d_device->CreateTexture2D(&tex_desc, NULL, &staging_tex);
  if (E_INVALIDARG == hr) {
    printf("Error: received E_INVALIDARG when trying to create the texture.\n");
    exit(EXIT_FAILURE);
  }
  else if (S_OK != hr) {
    printf("Error: failed to create the 2D texture, error: %d.\n", hr);
    exit(EXIT_FAILURE);
  }
   
  /* 
     Get some info about the output duplication. 
     When the DesktopImageInSystemMemory is TRUE you can use 
     the MapDesktopSurface/UnMapDesktopSurface directly to retrieve the
     pixel data. If not, then you need to use a surface. 

  */
  DXGI_OUTDUPL_DESC duplication_desc;
  duplication->GetDesc(&duplication_desc);
  printf("duplication desc.DesktopImageInSystemMemory: %c\n", (duplication_desc.DesktopImageInSystemMemory) ? 'y' : 'n');
  
  /* Access a couple of frames. */
  DXGI_OUTDUPL_FRAME_INFO frame_info;
  IDXGIResource* desktop_resource = NULL;
  ID3D11Texture2D* tex = NULL;
  DXGI_MAPPED_RECT mapped_rect;
  
  for (int i = 0; i < 500; ++i) {
    //  printf("%02d - ", i);
    
    hr = duplication->AcquireNextFrame(1000, &frame_info, &desktop_resource);
    if (DXGI_ERROR_ACCESS_LOST == hr) {
      printf("Received a DXGI_ERROR_ACCESS_LOST.\n");
    }
    else if (DXGI_ERROR_WAIT_TIMEOUT == hr) {
      printf("Received a DXGI_ERROR_WAIT_TIMEOUT.\n");
    }
    else if (DXGI_ERROR_INVALID_CALL == hr) {
      printf("Received a DXGI_ERROR_INVALID_CALL.\n");
    }
    else if (S_OK == hr) {
      //printf("Yay we got a frame.\n");

      /* Print some info. */
      //printf("frame_info.TotalMetadataBufferSize: %u\n", frame_info.TotalMetadataBufferSize);
      //printf("frame_info.AccumulatedFrames: %u\n", frame_info.AccumulatedFrames);

      /* Get the texture interface .. */
#if 1      
      hr = desktop_resource->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&tex);
      if (S_OK != hr) {
        printf("Error: failed to query the ID3D11Texture2D interface on the IDXGIResource we got.\n");
        exit(EXIT_FAILURE);
      }
#endif      

      /* Map the desktop surface */
      hr = duplication->MapDesktopSurface(&mapped_rect);
      if (S_OK == hr) {
        printf("We got acess to the desktop surface\n");
        hr = duplication->UnMapDesktopSurface();
        if (S_OK != hr) {
          printf("Error: failed to unmap the desktop surface after successfully mapping it.\n");
        }
      }
      else if (DXGI_ERROR_UNSUPPORTED == hr) {
        //printf("MapDesktopSurface returned DXGI_ERROR_UNSUPPORTED.\n");
        /* 
           According to the docs, when we receive this error we need
           to transfer the image to a staging surface and then lock the 
            image by calling IDXGISurface::Map().

           To get the data from GPU to the CPU, we do:

               - copy the frame into our staging texture
               - map the texture 
               - ... do something 
               - unmap.

           @TODO figure out what solution is faster:

           There are multiple solutions to copy a texture. I have 
           to look into what solution is better. 
           -  d3d_context->CopySubresourceRegion();
           -  d3d_context->CopyResource(dest, src)

           @TODO we need to make sure that the width/height are valid. 
 
        */

        d3d_context->CopyResource(staging_tex, tex);

        D3D11_MAPPED_SUBRESOURCE map;
        HRESULT map_result = d3d_context->Map(staging_tex,          /* Resource */
                                              0,                    /* Subresource */ 
                                              D3D11_MAP_READ,       /* Map type. */
                                              0,                    /* Map flags. */
                                              &map);

        if (S_OK == map_result) {
          unsigned char* data = (unsigned char*)map.pData;
          //printf("Mapped the staging tex; we can access the data now.\n");
          printf("RowPitch: %u, DepthPitch: %u, %02X, %02X, %02X\n", map.RowPitch, map.DepthPitch, data[0], data[1], data[2]);
#if 0
          if (i < 25) {
            char fname[512];

            /* We have to make the image opaque. */

            for (int k = 0; k < tex_desc.Width; ++k) {
              for (int l = 0; l < tex_desc.Height; ++l) {
                int dx = l * tex_desc.Width * 4 + k * 4;
                data[dx + 3] = 0xFF;
              }
            }
            sprintf(fname, "capture_%03d.png", i);
            save_png(fname,
                     tex_desc.Width, tex_desc.Height, 8, PNG_COLOR_TYPE_RGBA,
                     (unsigned char*)map.pData, map.RowPitch, PNG_TRANSFORM_BGR);
          }
#endif
        }
        else {
          printf("Error: failed to map the staging tex. Cannot access the pixels.\n");
        }

        d3d_context->Unmap(staging_tex, 0);
      }
      else if (DXGI_ERROR_INVALID_CALL == hr) {
        printf("MapDesktopSurface returned DXGI_ERROR_INVALID_CALL.\n");
      }
      else if (DXGI_ERROR_ACCESS_LOST == hr) {
        printf("MapDesktopSurface returned DXGI_ERROR_ACCESS_LOST.\n");
      }
      else if (E_INVALIDARG == hr) {
        printf("MapDesktopSurface returned E_INVALIDARG.\n");
      }
      else {
        printf("MapDesktopSurface returned an unknown error.\n");
      }
    }

    /* Clean up */
    {

      if (NULL != tex) {
        tex->Release();
        tex = NULL;
      }
      
      if (NULL != desktop_resource) {
        desktop_resource->Release();
        desktop_resource = NULL;
      }

      /* We must release the frame. */
      hr = duplication->ReleaseFrame();
      if (S_OK != hr) {
        printf("Failed to release the duplication frame.\n");
      }
    }
  }
  
  //printf("Monitors connected to adapter: %lu\n", i);

  /* Cleanup */
  {

    if (NULL != staging_tex) {
      staging_tex->Release();
      staging_tex = NULL;
    }
    
    if (NULL != d3d_device) {
      d3d_device->Release();
      d3d_device = NULL;
    }

    if (NULL != d3d_context) {
      d3d_context->Release();
      d3d_context = NULL;
    }

    if (NULL != duplication) {
      duplication->Release();
      duplication = NULL;
    }
    
    for (size_t i = 0; i < adapters.size(); ++i) {
      if (NULL != adapters[i]) {
        adapters[i]->Release();
        adapters[i] = NULL;
      }
    }

    for (size_t i = 0; i < outputs.size(); ++i) {
      if (NULL != outputs[i]) {
        outputs[i]->Release();
        outputs[i] = NULL;
      }
    }

    if (NULL != output1) {
      output1->Release();
      output1 = NULL;
    }

    if (NULL != factory) {
      factory->Release();
      factory = NULL;
    }
  }
  
  return 0;
}
//
// Initialize duplication interfaces
//
DUPL_RETURN DUPLICATIONMANAGER::InitDupl(_In_ ID3D11Device* Device, UINT Output)
{
    m_OutputNumber = Output;

    // Take a reference on the device
    m_Device = Device;
    m_Device->AddRef();

    // Get DXGI device
    IDXGIDevice* DxgiDevice = nullptr;
    HRESULT hr = m_Device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&DxgiDevice));
    if (FAILED(hr))
    {
        return ProcessFailure(nullptr, L"Failed to QI for DXGI Device", L"Error", hr);
    }

    // Get DXGI adapter
    IDXGIAdapter* DxgiAdapter = nullptr;
    hr = DxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&DxgiAdapter));
    DxgiDevice->Release();
    DxgiDevice = nullptr;
    if (FAILED(hr))
    {
        return ProcessFailure(m_Device, L"Failed to get parent DXGI Adapter", L"Error", hr, SystemTransitionsExpectedErrors);
    }

    // Get output
    IDXGIOutput* DxgiOutput = nullptr;
    hr = DxgiAdapter->EnumOutputs(Output, &DxgiOutput);
    DxgiAdapter->Release();
    DxgiAdapter = nullptr;
    if (FAILED(hr))
    {
        return ProcessFailure(m_Device, L"Failed to get specified output in DUPLICATIONMANAGER", L"Error", hr, EnumOutputsExpectedErrors);
    }

    DxgiOutput->GetDesc(&m_OutputDesc);

    // QI for Output 1
    IDXGIOutput1* DxgiOutput1 = nullptr;
    hr = DxgiOutput->QueryInterface(__uuidof(DxgiOutput1), reinterpret_cast<void**>(&DxgiOutput1));
    DxgiOutput->Release();
    DxgiOutput = nullptr;
    if (FAILED(hr))
    {
        return ProcessFailure(nullptr, L"Failed to QI for DxgiOutput1 in DUPLICATIONMANAGER", L"Error", hr);
    }

    // Create desktop duplication
    hr = DxgiOutput1->DuplicateOutput(m_Device, &m_DeskDupl);
    DxgiOutput1->Release();
    DxgiOutput1 = nullptr;
    if (FAILED(hr))
    {
        if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
        {
            MessageBoxW(nullptr, L"There is already the maximum number of applications using the Desktop Duplication API running, please close one of those applications and then try again.", L"Error", MB_OK);
            return DUPL_RETURN_ERROR_UNEXPECTED;
        }
        return ProcessFailure(m_Device, L"Failed to get duplicate output in DUPLICATIONMANAGER", L"Error", hr, CreateDuplicationExpectedErrors);
    }

    return DUPL_RETURN_SUCCESS;
}
Example #15
0
bool D3D11App::initAPI(const API_Revision api_revision, const DXGI_FORMAT backBufferFmt, const DXGI_FORMAT depthBufferFmt, const int samples, const uint flags)
{
	backBufferFormat = backBufferFmt;
	depthBufferFormat = depthBufferFmt;
	msaaSamples = samples;

	const bool sampleBackBuffer = (flags & SAMPLE_BACKBUFFER) != 0;

//	if (screen >= GetSystemMetrics(SM_CMONITORS)) screen = 0;

	IDXGIFactory1 *dxgiFactory;
	if (FAILED(CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void **) &dxgiFactory)))
	{
		ErrorMsg("Couldn't create DXGIFactory");
		return false;
	}

	IDXGIAdapter1 *dxgiAdapter;
	if (dxgiFactory->EnumAdapters1(0, &dxgiAdapter) == DXGI_ERROR_NOT_FOUND)
	{
		ErrorMsg("No adapters found");
		return false;
	}

//	DXGI_ADAPTER_DESC1 adapterDesc;
//	dxgiAdapter->GetDesc1(&adapterDesc);

	IDXGIOutput *dxgiOutput;
	if (dxgiAdapter->EnumOutputs(0, &dxgiOutput) == DXGI_ERROR_NOT_FOUND)
	{
		ErrorMsg("No outputs found");
		return false;
	}

	DXGI_OUTPUT_DESC oDesc;
	dxgiOutput->GetDesc(&oDesc);


	// Find a suitable fullscreen format
	int targetHz = 85;
	DXGI_RATIONAL fullScreenRefresh;
	int fsRefresh = 60;
	fullScreenRefresh.Numerator = fsRefresh;
	fullScreenRefresh.Denominator = 1;
	char str[128];

	uint nModes = 0;
	dxgiOutput->GetDisplayModeList(backBufferFormat, 0, &nModes, NULL);
	DXGI_MODE_DESC *modes = new DXGI_MODE_DESC[nModes];
	dxgiOutput->GetDisplayModeList(backBufferFormat, 0, &nModes, modes);

	resolution->clear();
	for (uint i = 0; i < nModes; i++)
	{
		if (modes[i].Width >= 640 && modes[i].Height >= 480)
		{
			sprintf(str, "%dx%d", modes[i].Width, modes[i].Height);
			int index = resolution->addItemUnique(str);

			if (int(modes[i].Width) == fullscreenWidth && int(modes[i].Height) == fullscreenHeight)
			{
				int refresh = modes[i].RefreshRate.Numerator / modes[i].RefreshRate.Denominator;
				if (abs(refresh - targetHz) < abs(fsRefresh - targetHz))
				{
					fsRefresh = refresh;
					fullScreenRefresh = modes[i].RefreshRate;
				}
				resolution->selectItem(index);
			}
		}
	}
	delete [] modes;

	sprintf(str, "%s (%dx%d)", getTitle(), width, height);

	DWORD wndFlags = 0;
	int x, y, w, h;
	if (fullscreen)
	{
		wndFlags |= WS_POPUP;
		x = y = 0;
		w = width;
		h = height;
	}
	else
	{
		wndFlags |= WS_OVERLAPPEDWINDOW;

		RECT wRect;
		wRect.left = 0;
		wRect.right = width;
		wRect.top = 0;
		wRect.bottom = height;
		AdjustWindowRect(&wRect, wndFlags, FALSE);

		MONITORINFO monInfo;
		monInfo.cbSize = sizeof(monInfo);
		GetMonitorInfo(oDesc.Monitor, &monInfo);

		w = min(wRect.right  - wRect.left, monInfo.rcWork.right  - monInfo.rcWork.left);
		h = min(wRect.bottom - wRect.top,  monInfo.rcWork.bottom - monInfo.rcWork.top);
		x = (monInfo.rcWork.left + monInfo.rcWork.right  - w) / 2;
		y = (monInfo.rcWork.top  + monInfo.rcWork.bottom - h) / 2;
	}


	hwnd = CreateWindow("Game", str, wndFlags, x, y, w, h, HWND_DESKTOP, NULL, hInstance, NULL);

	RECT rect;
	GetClientRect(hwnd, &rect);

	// Create device and swap chain
	DWORD deviceFlags = D3D11_CREATE_DEVICE_SINGLETHREADED;
#ifdef _DEBUG
    deviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

	D3D_FEATURE_LEVEL requested_feature_level = (api_revision == D3D11)? D3D_FEATURE_LEVEL_11_0 : (api_revision == D3D11_1)? D3D_FEATURE_LEVEL_10_1 : D3D_FEATURE_LEVEL_10_0;
	D3D_FEATURE_LEVEL feature_level;
	if (FAILED(D3D11CreateDevice(dxgiAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, deviceFlags, &requested_feature_level, 1, D3D11_SDK_VERSION, &device, &feature_level, &context)))
	{
		ErrorMsg("Couldn't create D3D11 device");
		return false;
	}

	while (msaaSamples > 0)
	{
		UINT nQuality;
		if (SUCCEEDED(device->CheckMultisampleQualityLevels(backBufferFormat, msaaSamples, &nQuality)) && nQuality > 0)
		{
			if ((flags & NO_SETTING_CHANGE) == 0) antiAliasSamples = msaaSamples;
			break;
		}
		else
		{
			msaaSamples -= 2;
		}
	}
	DXGI_SWAP_CHAIN_DESC sd;
	memset(&sd, 0, sizeof(sd));
	sd.BufferDesc.Width  = rect.right;
	sd.BufferDesc.Height = rect.bottom;
	sd.BufferDesc.Format = backBufferFormat;
	sd.BufferDesc.RefreshRate = fullScreenRefresh;
	sd.BufferUsage = /*DXGI_USAGE_BACK_BUFFER | */DXGI_USAGE_RENDER_TARGET_OUTPUT | (sampleBackBuffer? DXGI_USAGE_SHADER_INPUT : 0);
	sd.BufferCount = 1;
	sd.OutputWindow = hwnd;
	sd.Windowed = (BOOL) (!fullscreen);
	sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
	sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
	sd.SampleDesc.Count = msaaSamples;
	sd.SampleDesc.Quality = 0;

	if (FAILED(dxgiFactory->CreateSwapChain(device, &sd, &swapChain)))
	{
		ErrorMsg("Couldn't create swapchain");
		return false;
	}

	// We'll handle Alt-Enter ourselves thank you very much ...
	dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER);

	dxgiOutput->Release();
	dxgiAdapter->Release();
	dxgiFactory->Release();

	if (fullscreen)
	{
		captureMouse(!configDialog->isVisible());
	}

	renderer = new Direct3D11Renderer(device, context);

	if (!createBuffers(sampleBackBuffer))
	{
		delete renderer;
		return false;
	}
	antiAlias->selectItem(antiAliasSamples / 2);

	linearClamp = renderer->addSamplerState(LINEAR, CLAMP, CLAMP, CLAMP);
	defaultFont = renderer->addFont("../Textures/Fonts/Future.dds", "../Textures/Fonts/Future.font", linearClamp);
	blendSrcAlpha = renderer->addBlendState(SRC_ALPHA, ONE_MINUS_SRC_ALPHA);
	noDepthTest  = renderer->addDepthState(false, false);
	noDepthWrite = renderer->addDepthState(true,  false);
	cullNone  = renderer->addRasterizerState(CULL_NONE);
	cullBack  = renderer->addRasterizerState(CULL_BACK);
	cullFront = renderer->addRasterizerState(CULL_FRONT);

	return true;
}
Example #16
0
static int
WINRT_AddDisplaysForOutput (_THIS, IDXGIAdapter1 * dxgiAdapter1, int outputIndex)
{
    HRESULT hr;
    IDXGIOutput * dxgiOutput = NULL;
    DXGI_OUTPUT_DESC dxgiOutputDesc;
    SDL_VideoDisplay display;
    char * displayName = NULL;
    UINT numModes;
    DXGI_MODE_DESC * dxgiModes = NULL;
    int functionResult = -1;        /* -1 for failure, 0 for success */
    DXGI_MODE_DESC modeToMatch, closestMatch;

    SDL_zero(display);

    hr = dxgiAdapter1->EnumOutputs(outputIndex, &dxgiOutput);
    if (FAILED(hr)) {
        if (hr != DXGI_ERROR_NOT_FOUND) {
            WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIAdapter1::EnumOutputs failed", hr);
        }
        goto done;
    }

    hr = dxgiOutput->GetDesc(&dxgiOutputDesc);
    if (FAILED(hr)) {
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDesc failed", hr);
        goto done;
    }

    SDL_zero(modeToMatch);
    modeToMatch.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    modeToMatch.Width = (dxgiOutputDesc.DesktopCoordinates.right - dxgiOutputDesc.DesktopCoordinates.left);
    modeToMatch.Height = (dxgiOutputDesc.DesktopCoordinates.bottom - dxgiOutputDesc.DesktopCoordinates.top);
    hr = dxgiOutput->FindClosestMatchingMode(&modeToMatch, &closestMatch, NULL);
    if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
        /* DXGI_ERROR_NOT_CURRENTLY_AVAILABLE gets returned by IDXGIOutput::FindClosestMatchingMode
           when running under the Windows Simulator, which uses Remote Desktop (formerly known as Terminal
           Services) under the hood.  According to the MSDN docs for the similar function,
           IDXGIOutput::GetDisplayModeList, DXGI_ERROR_NOT_CURRENTLY_AVAILABLE is returned if and
           when an app is run under a Terminal Services session, hence the assumption.

           In this case, just add an SDL display mode, with approximated values.
        */
        SDL_DisplayMode mode;
        SDL_zero(mode);
        display.name = "Windows Simulator / Terminal Services Display";
        mode.w = (dxgiOutputDesc.DesktopCoordinates.right - dxgiOutputDesc.DesktopCoordinates.left);
        mode.h = (dxgiOutputDesc.DesktopCoordinates.bottom - dxgiOutputDesc.DesktopCoordinates.top);
        mode.format = DXGI_FORMAT_B8G8R8A8_UNORM;
        mode.refresh_rate = 0;  /* Display mode is unknown, so just fill in zero, as specified by SDL's header files */
        display.desktop_mode = mode;
        display.current_mode = mode;
        if ( ! SDL_AddDisplayMode(&display, &mode)) {
            goto done;
        }
    } else if (FAILED(hr)) {
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::FindClosestMatchingMode failed", hr);
        goto done;
    } else {
        displayName = WIN_StringToUTF8(dxgiOutputDesc.DeviceName);
        display.name = displayName;
        WINRT_DXGIModeToSDLDisplayMode(&closestMatch, &display.desktop_mode);
        display.current_mode = display.desktop_mode;

        hr = dxgiOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &numModes, NULL);
        if (FAILED(hr)) {
            if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
                // TODO, WinRT: make sure display mode(s) are added when using Terminal Services / Windows Simulator
            }
            WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDisplayModeList [get mode list size] failed", hr);
            goto done;
        }

        dxgiModes = (DXGI_MODE_DESC *)SDL_calloc(numModes, sizeof(DXGI_MODE_DESC));
        if ( ! dxgiModes) {
            SDL_OutOfMemory();
            goto done;
        }

        hr = dxgiOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &numModes, dxgiModes);
        if (FAILED(hr)) {
            WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDisplayModeList [get mode contents] failed", hr);
            goto done;
        }

        for (UINT i = 0; i < numModes; ++i) {
            SDL_DisplayMode sdlMode;
            WINRT_DXGIModeToSDLDisplayMode(&dxgiModes[i], &sdlMode);
            SDL_AddDisplayMode(&display, &sdlMode);
        }
    }

    if (SDL_AddVideoDisplay(&display) < 0) {
        goto done;
    }

    functionResult = 0;     /* 0 for Success! */
done:
    if (dxgiModes) {
        SDL_free(dxgiModes);
    }
    if (dxgiOutput) {
        dxgiOutput->Release();
    }
    if (displayName) {
        SDL_free(displayName);
    }
    return functionResult;
}
Example #17
0
HRESULT Create(HWND wnd)
{
	hWnd = wnd;
	HRESULT hr;

	RECT client;
	GetClientRect(hWnd, &client);
	xres = client.right - client.left;
	yres = client.bottom - client.top;

	hr = LoadDXGI();
	if (SUCCEEDED(hr)) hr = LoadD3D();
	if (SUCCEEDED(hr)) hr = LoadD3DCompiler();
	if (FAILED(hr))
	{
		UnloadDXGI();
		UnloadD3D();
		UnloadD3DCompiler();
		return hr;
	}

	IDXGIFactory* factory;
	IDXGIAdapter* adapter;
	IDXGIOutput* output;
	hr = PCreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory);
	if (FAILED(hr)) MessageBox(wnd, _T("Failed to create IDXGIFactory object"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR);

	hr = factory->EnumAdapters(g_ActiveConfig.iAdapter, &adapter);
	if (FAILED(hr))
	{
		// try using the first one
		hr = factory->EnumAdapters(0, &adapter);
		if (FAILED(hr)) MessageBox(wnd, _T("Failed to enumerate adapters"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR);
	}

	// TODO: Make this configurable
	hr = adapter->EnumOutputs(0, &output);
	if (FAILED(hr))
	{
		// try using the first one
		hr = adapter->EnumOutputs(0, &output);
		if (FAILED(hr)) MessageBox(wnd, _T("Failed to enumerate outputs!\n")
		                                _T("This usually happens when you've set your video adapter to the Nvidia GPU in an Optimus-equipped system.\n")
		                                _T("Set Dolphin to use the high-performance graphics in Nvidia's drivers instead and leave Dolphin's video adapter set to the Intel GPU."),
		                                _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR);
	}

	// get supported AA modes
	aa_modes = EnumAAModes(adapter);
	if (g_Config.iMultisampleMode >= (int)aa_modes.size())
	{
		g_Config.iMultisampleMode = 0;
		UpdateActiveConfig();
	}

	DXGI_SWAP_CHAIN_DESC swap_chain_desc;
	memset(&swap_chain_desc, 0, sizeof(swap_chain_desc));
	swap_chain_desc.BufferCount = 1;
	swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
	swap_chain_desc.OutputWindow = wnd;
	swap_chain_desc.SampleDesc.Count = 1;
	swap_chain_desc.SampleDesc.Quality = 0;
	swap_chain_desc.Windowed = !g_ActiveConfig.bFullscreen;

	DXGI_OUTPUT_DESC out_desc;
	memset(&out_desc, 0, sizeof(out_desc));
	output->GetDesc(&out_desc);

	DXGI_MODE_DESC mode_desc;
	memset(&mode_desc, 0, sizeof(mode_desc));
	mode_desc.Width = out_desc.DesktopCoordinates.right - out_desc.DesktopCoordinates.left;
	mode_desc.Height = out_desc.DesktopCoordinates.bottom - out_desc.DesktopCoordinates.top;
	mode_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	mode_desc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
	hr = output->FindClosestMatchingMode(&mode_desc, &swap_chain_desc.BufferDesc, nullptr);
	if (FAILED(hr)) MessageBox(wnd, _T("Failed to find a supported video mode"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR);

	if (swap_chain_desc.Windowed)
	{
		// forcing buffer resolution to xres and yres..
		// this is not a problem as long as we're in windowed mode
		swap_chain_desc.BufferDesc.Width = xres;
		swap_chain_desc.BufferDesc.Height = yres;
	}

#if defined(_DEBUG) || defined(DEBUGFAST)
	// Creating debug devices can sometimes fail if the user doesn't have the correct
	// version of the DirectX SDK. If it does, simply fallback to a non-debug device.
	{
		hr = PD3D11CreateDeviceAndSwapChain(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
											D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_DEBUG,
											supported_feature_levels, NUM_SUPPORTED_FEATURE_LEVELS,
											D3D11_SDK_VERSION, &swap_chain_desc, &swapchain, &device,
											&featlevel, &context);
	}

	if (FAILED(hr))
#endif
	{
		hr = PD3D11CreateDeviceAndSwapChain(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
											D3D11_CREATE_DEVICE_SINGLETHREADED,
											supported_feature_levels, NUM_SUPPORTED_FEATURE_LEVELS,
											D3D11_SDK_VERSION, &swap_chain_desc, &swapchain, &device,
											&featlevel, &context);
	}

	if (FAILED(hr))
	{
		MessageBox(wnd, _T("Failed to initialize Direct3D.\nMake sure your video card supports at least D3D 10.0"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR);
		SAFE_RELEASE(device);
		SAFE_RELEASE(context);
		SAFE_RELEASE(swapchain);
		return E_FAIL;
	}

	// prevent DXGI from responding to Alt+Enter, unfortunately DXGI_MWA_NO_ALT_ENTER
	// does not work so we disable all monitoring of window messages. However this
	// may make it more difficult for DXGI to handle display mode changes.
	hr = factory->MakeWindowAssociation(wnd, DXGI_MWA_NO_WINDOW_CHANGES);
	if (FAILED(hr)) MessageBox(wnd, _T("Failed to associate the window"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR);

	SetDebugObjectName((ID3D11DeviceChild*)context, "device context");
	SAFE_RELEASE(factory);
	SAFE_RELEASE(output);
	SAFE_RELEASE(adapter);

	ID3D11Texture2D* buf;
	hr = swapchain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&buf);
	if (FAILED(hr))
	{
		MessageBox(wnd, _T("Failed to get swapchain buffer"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR);
		SAFE_RELEASE(device);
		SAFE_RELEASE(context);
		SAFE_RELEASE(swapchain);
		return E_FAIL;
	}
	backbuf = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
	SAFE_RELEASE(buf);
	CHECK(backbuf!=nullptr, "Create back buffer texture");
	SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetTex(), "backbuffer texture");
	SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetRTV(), "backbuffer render target view");

	context->OMSetRenderTargets(1, &backbuf->GetRTV(), nullptr);

	// BGRA textures are easier to deal with in TextureCache, but might not be supported by the hardware
	UINT format_support;
	device->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &format_support);
	bgra_textures_supported = (format_support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0;

	stateman = new StateManager;
	return S_OK;
}
HRESULT GetVideoMemoryViaDXGI( HMONITOR hMonitor,
                               SIZE_T* pDedicatedVideoMemory,
                               SIZE_T* pDedicatedSystemMemory,
                               SIZE_T* pSharedSystemMemory )
{
    HRESULT hr;
    bool bGotMemory = false;
    *pDedicatedVideoMemory = 0;
    *pDedicatedSystemMemory = 0;
    *pSharedSystemMemory = 0;

    if( DynamicDX::IsInitialized() )
    {
        IDXGIFactory* pDXGIFactory = NULL;
        DynamicDX::CreateDXGIFactory( __uuidof( IDXGIFactory ), ( LPVOID* )&pDXGIFactory );

        for( int index = 0; ; ++index )
        {
            bool bFoundMatchingAdapter = false;
            IDXGIAdapter* pAdapter = NULL;
            hr = pDXGIFactory->EnumAdapters( index, &pAdapter );
            if( FAILED( hr ) ) // DXGIERR_NOT_FOUND is expected when the end of the list is hit
                break;

            for( int iOutput = 0; ; ++iOutput )
            {
                IDXGIOutput* pOutput = NULL;
                hr = pAdapter->EnumOutputs( iOutput, &pOutput );
                if( FAILED( hr ) ) // DXGIERR_NOT_FOUND is expected when the end of the list is hit
                    break;

                DXGI_OUTPUT_DESC outputDesc;
                ZeroMemory( &outputDesc, sizeof( DXGI_OUTPUT_DESC ) );
                if( SUCCEEDED( pOutput->GetDesc( &outputDesc ) ) )
                {
                    if( hMonitor == outputDesc.Monitor )
                        bFoundMatchingAdapter = true;

                }
                SAFE_RELEASE( pOutput );
            }

            if( bFoundMatchingAdapter )
            {
                DXGI_ADAPTER_DESC desc;
                ZeroMemory( &desc, sizeof( DXGI_ADAPTER_DESC ) );
                if( SUCCEEDED( pAdapter->GetDesc( &desc ) ) )
                {
                    bGotMemory = true;
                    *pDedicatedVideoMemory = desc.DedicatedVideoMemory;
                    *pDedicatedSystemMemory = desc.DedicatedSystemMemory;
                    *pSharedSystemMemory = desc.SharedSystemMemory;
                }
                break;
            }
        }
    }

    if( bGotMemory )
        return S_OK;
    else
        return E_FAIL;
}
	//---------------------------------------------------------------------
	BOOL D3D10VideoModeList::enumerate()
	{
		//		int pD3D = mpDriver->getD3D();
		UINT adapter = mpDriver->getAdapterNumber();
		HRESULT hr;
		IDXGIOutput *pOutput;
		for( int iOutput = 0; ; ++iOutput )
		{
			//AIZTODO: one output for a single monitor ,to be handled for mulimon	    
			hr = mpDriver->getDeviceAdapter()->EnumOutputs( iOutput, &pOutput );
			if( DXGI_ERROR_NOT_FOUND == hr )
			{
				return false;
			}
			else if (FAILED(hr))
			{
				return false;	//Something bad happened.
			}
			else //Success!
			{
				const DXGI_FORMAT allowedAdapterFormatArray[] = 
				{
					DXGI_FORMAT_R8G8B8A8_UNORM,			//This is DXUT's preferred mode

					//DXGI_FORMAT_R16G16B16A16_FLOAT,
					//DXGI_FORMAT_R10G10B10A2_UNORM,
					//DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
				};
				int allowedAdapterFormatArrayCount  = sizeof(allowedAdapterFormatArray) / sizeof(allowedAdapterFormatArray[0]);

				UINT NumModes = 512;
				DXGI_MODE_DESC *pDesc = new DXGI_MODE_DESC[ NumModes ];
				hr = pOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM,//allowedAdapterFormatArray[f],
					0,
					&NumModes,
					pDesc );
				DXGI_OUTPUT_DESC OutputDesc;
				pOutput->GetDesc(&OutputDesc);
				for( UINT m=0; m<NumModes; m++ )
				{
					DXGI_MODE_DESC displayMode=pDesc[m];
					// Filter out low-resolutions
					if( displayMode.Width < 640 || displayMode.Height < 400 )
						continue;

					// Check to see if it is already in the list (to filter out refresh rates)
					BOOL found = FALSE;
					vector<D3D10VideoMode>::type::iterator it;
					for( it = mModeList.begin(); it != mModeList.end(); it++ )
					{
						DXGI_OUTPUT_DESC oldOutput= it->getDisplayMode();
						DXGI_MODE_DESC oldDisp = it->getModeDesc();
						if(//oldOutput.Monitor==OutputDesc.Monitor &&
							oldDisp.Width == displayMode.Width &&
							oldDisp.Height == displayMode.Height// &&
							//oldDisp.Format == displayMode.Format
							)
						{
							// Check refresh rate and favour higher if poss
							//if (oldDisp.RefreshRate < displayMode.RefreshRate)
							//	it->increaseRefreshRate(displayMode.RefreshRate);
							found = TRUE;
							break;
						}
					}

					if( !found )
						mModeList.push_back( D3D10VideoMode( OutputDesc,displayMode ) );

				}

			}
		}
		/*	
		UINT iMode;
		for( iMode=0; iMode < pD3D->GetAdapterModeCount( adapter, D3DFMT_R5G6B5 ); iMode++ )
		{
		DXGI_OUTPUT_DESC displayMode;
		pD3D->EnumAdapterModes( adapter, D3DFMT_R5G6B5, iMode, &displayMode );

		// Filter out low-resolutions
		if( displayMode.Width < 640 || displayMode.Height < 400 )
		continue;

		// Check to see if it is already in the list (to filter out refresh rates)
		BOOL found = FALSE;
		vector<D3D10VideoMode>::type::iterator it;
		for( it = mModeList.begin(); it != mModeList.end(); it++ )
		{
		DXGI_OUTPUT_DESC oldDisp = it->getDisplayMode();
		if( oldDisp.Width == displayMode.Width &&
		oldDisp.Height == displayMode.Height &&
		oldDisp.Format == displayMode.Format )
		{
		// Check refresh rate and favour higher if poss
		if (oldDisp.RefreshRate < displayMode.RefreshRate)
		it->increaseRefreshRate(displayMode.RefreshRate);
		found = TRUE;
		break;
		}
		}

		if( !found )
		mModeList.push_back( D3D10VideoMode( displayMode ) );
		}

		for( iMode=0; iMode < pD3D->GetAdapterModeCount( adapter, D3DFMT_X8R8G8B8 ); iMode++ )
		{
		DXGI_OUTPUT_DESC displayMode;
		pD3D->EnumAdapterModes( adapter, D3DFMT_X8R8G8B8, iMode, &displayMode );

		// Filter out low-resolutions
		if( displayMode.Width < 640 || displayMode.Height < 400 )
		continue;

		// Check to see if it is already in the list (to filter out refresh rates)
		BOOL found = FALSE;
		vector<D3D10VideoMode>::type::iterator it;
		for( it = mModeList.begin(); it != mModeList.end(); it++ )
		{
		DXGI_OUTPUT_DESC oldDisp = it->getDisplayMode();
		if( oldDisp.Width == displayMode.Width &&
		oldDisp.Height == displayMode.Height &&
		oldDisp.Format == displayMode.Format )
		{
		// Check refresh rate and favour higher if poss
		if (oldDisp.RefreshRate < displayMode.RefreshRate)
		it->increaseRefreshRate(displayMode.RefreshRate);
		found = TRUE;
		break;
		}
		}

		if( !found )
		mModeList.push_back( D3D10VideoMode( displayMode ) );
		}
		*/
		return TRUE;
	}
Example #20
0
//
// Recreate shared texture
//
DUPL_RETURN OUTPUTMANAGER::CreateSharedSurf(INT SingleOutput, _Out_ UINT* OutCount, _Out_ RECT* DeskBounds)
{
    HRESULT hr;

    // Get DXGI resources
    IDXGIDevice* DxgiDevice = nullptr;
    hr = m_Device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&DxgiDevice));
    if (FAILED(hr))
    {
        return ProcessFailure(nullptr, L"Failed to QI for DXGI Device", L"Error", hr);
    }

    IDXGIAdapter* DxgiAdapter = nullptr;
    hr = DxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&DxgiAdapter));
    DxgiDevice->Release();
    DxgiDevice = nullptr;
    if (FAILED(hr))
    {
        return ProcessFailure(m_Device, L"Failed to get parent DXGI Adapter", L"Error", hr, SystemTransitionsExpectedErrors);
    }

    // Set initial values so that we always catch the right coordinates
    DeskBounds->left = INT_MAX;
    DeskBounds->right = INT_MIN;
    DeskBounds->top = INT_MAX;
    DeskBounds->bottom = INT_MIN;

    IDXGIOutput* DxgiOutput = nullptr;

    // Figure out right dimensions for full size desktop texture and # of outputs to duplicate
    UINT OutputCount;
    if (SingleOutput < 0)
    {
        hr = S_OK;
        for (OutputCount = 0; SUCCEEDED(hr); ++OutputCount) 
		// for (OutputCount = 0; OutputCount<1; ++OutputCount)
        {
            if (DxgiOutput)
            {
                DxgiOutput->Release();
                DxgiOutput = nullptr;
            }
            hr = DxgiAdapter->EnumOutputs(OutputCount, &DxgiOutput);
            if (DxgiOutput && (hr != DXGI_ERROR_NOT_FOUND))
            {
                DXGI_OUTPUT_DESC DesktopDesc;
                DxgiOutput->GetDesc(&DesktopDesc);

                DeskBounds->left = min(DesktopDesc.DesktopCoordinates.left, DeskBounds->left);
                DeskBounds->top = min(DesktopDesc.DesktopCoordinates.top, DeskBounds->top);
                DeskBounds->right = max(DesktopDesc.DesktopCoordinates.right, DeskBounds->right);
                DeskBounds->bottom = max(DesktopDesc.DesktopCoordinates.bottom, DeskBounds->bottom);
            }
        }

        --OutputCount;
    }
    else
    {
        hr = DxgiAdapter->EnumOutputs(SingleOutput, &DxgiOutput);
        if (FAILED(hr))
        {
            DxgiAdapter->Release();
            DxgiAdapter = nullptr;
            return ProcessFailure(m_Device, L"Output specified to be duplicated does not exist", L"Error", hr);
        }
        DXGI_OUTPUT_DESC DesktopDesc;
        DxgiOutput->GetDesc(&DesktopDesc);
        *DeskBounds = DesktopDesc.DesktopCoordinates;

        DxgiOutput->Release();
        DxgiOutput = nullptr;

        OutputCount = 1;
    }

    DxgiAdapter->Release();
    DxgiAdapter = nullptr;

    // Set passed in output count variable
    *OutCount = OutputCount;

    if (OutputCount == 0)
    {
        // We could not find any outputs, the system must be in a transition so return expected error
        // so we will attempt to recreate
        return DUPL_RETURN_ERROR_EXPECTED;
    }

    // Create shared texture for all duplication threads to draw into
    D3D11_TEXTURE2D_DESC DeskTexD;
    RtlZeroMemory(&DeskTexD, sizeof(D3D11_TEXTURE2D_DESC));
    DeskTexD.Width = DeskBounds->right - DeskBounds->left;
    DeskTexD.Height = DeskBounds->bottom - DeskBounds->top;
    DeskTexD.MipLevels = 1;
    DeskTexD.ArraySize = 1;
    DeskTexD.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    DeskTexD.SampleDesc.Count = 1;
    DeskTexD.Usage = D3D11_USAGE_DEFAULT;
    DeskTexD.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
    DeskTexD.CPUAccessFlags = 0;
    DeskTexD.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;

    hr = m_Device->CreateTexture2D(&DeskTexD, nullptr, &m_SharedSurf);
    if (FAILED(hr))
    {
        if (OutputCount != 1)
        {
            // If we are duplicating the complete desktop we try to create a single texture to hold the
            // complete desktop image and blit updates from the per output DDA interface.  The GPU can
            // always support a texture size of the maximum resolution of any single output but there is no
            // guarantee that it can support a texture size of the desktop.
            // The sample only use this large texture to display the desktop image in a single window using DX
            // we could revert back to using GDI to update the window in this failure case.
            return ProcessFailure(m_Device, L"Failed to create DirectX shared texture - we are attempting to create a texture the size of the complete desktop and this may be larger than the maximum texture size of your GPU.  Please try again using the -output command line parameter to duplicate only 1 monitor or configure your computer to a single monitor configuration", L"Error", hr, SystemTransitionsExpectedErrors);
        }
        else
        {
            return ProcessFailure(m_Device, L"Failed to create shared texture", L"Error", hr, SystemTransitionsExpectedErrors);
        }
    }

    // Get keyed mutex
    hr = m_SharedSurf->QueryInterface(__uuidof(IDXGIKeyedMutex), reinterpret_cast<void**>(&m_KeyMutex));
    if (FAILED(hr))
    {
        return ProcessFailure(m_Device, L"Failed to query for keyed mutex in OUTPUTMANAGER", L"Error", hr);
    }

    return DUPL_RETURN_SUCCESS;
}
Example #21
0
bool xGL2RenderApi::__createD10Device()
{
      HRESULT hr = S_OK;;

      UINT width  = m_Width;
      UINT height = m_Height;

      if(width == 0 || height == 0)
      {
            RECT rc;
            GetClientRect( m_hMainWnd, &rc );
            width = rc.right - rc.left;
            height = rc.bottom - rc.top;
            m_Width  = width;
            m_Height = height;

      }
      UINT createDeviceFlags = 0;
#ifdef _DEBUG
      createDeviceFlags |= GL2_CREATE_DEVICE_DEBUG;
#endif

      GL2_DRIVER_TYPE driverTypes[] = 
      {
            GL2_DRIVER_TYPE_HARDWARE,            
            GL2_DRIVER_TYPE_REFERENCE,
            GL2_DRIVER_TYPE_REFERENCE,
            GL2_DRIVER_TYPE_REFERENCE,
            GL2_DRIVER_TYPE_REFERENCE,
            GL2_DRIVER_TYPE_REFERENCE,
      };
      HMODULE hDriverModule[]=
      {
            NULL,
            LoadLibraryA( "GL2WARP_beta.DLL" ),
            LoadLibraryW( _XEVOL_ABSPATH_(L"GL2WARP_beta.DLL") ),
            LoadLibraryA( "GL2WARP.DLL" ),
            LoadLibraryW( _XEVOL_ABSPATH_(L"GL2WARP.DLL" ) ),
            NULL,
      };

      UINT numDriverTypes = sizeof(driverTypes) / sizeof(driverTypes[0]);


      m_Width   = width;
      m_Height  = height;
      ZeroMemory( &m_swapChainDesc, sizeof(m_swapChainDesc) );
      m_swapChainDesc.BufferCount = 1;
      m_swapChainDesc.BufferDesc.Width = width;
      m_swapChainDesc.BufferDesc.Height = height;
      m_swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
      m_swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
      m_swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
      m_swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
      m_swapChainDesc.OutputWindow = m_hMainWnd;
      m_swapChainDesc.SampleDesc.Count = 1;
      m_swapChainDesc.SampleDesc.Quality = 0;
      m_swapChainDesc.Windowed = TRUE;

      //Find all Adapter
      IDXGIAdapter * pAdapter;
      std::vector<IDXGIAdapter*> vAdapters;
      IDXGIFactory* pDXGIFactory = NULL;
       hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)(&pDXGIFactory) );

      while(pDXGIFactory->EnumAdapters(vAdapters.size(), &pAdapter) != DXGI_ERROR_NOT_FOUND)
      {
            vAdapters.push_back(pAdapter);
      }


      for(int i = 0 ; i < vAdapters.size() ; i ++)
      {
            IDXGIAdapter* pAdapter = vAdapters[i];
            DXGI_ADAPTER_DESC desc;
            pAdapter->GetDesc(&desc);

            std::vector<IDXGIOutput*> vOutputers;
            IDXGIOutput* pOutputer = NULL;
            while(pAdapter->EnumOutputs(vOutputers.size(), &pOutputer) != DXGI_ERROR_NOT_FOUND)
            {
                  vOutputers.push_back(pOutputer);
                  DXGI_OUTPUT_DESC odesc;
                  pOutputer->GetDesc(&odesc);
                  continue;
            }

            for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )
            {
                  m_driverType = driverTypes[driverTypeIndex];
                  HMODULE hModule = hDriverModule[driverTypeIndex];
                  hr = GL2CreateDeviceAndSwapChain( pAdapter, m_driverType, hModule , createDeviceFlags, GL2_SDK_VERSION, &m_swapChainDesc, &m_pSwapChain, &m_pGL2Device );
                  if( SUCCEEDED( hr ) )
                        break;
            }
            if(m_pGL2Device && m_pSwapChain)
            {
                  break;
            }
      }
   


      if( FAILED(hr) )
            return false;


      m_RenderWindow = new xGL2RenderWindow(m_hMainWnd , this);
      m_RenderWindow->create(m_pSwapChain , width , height);
      __resetViewPort();
      setRenderView(m_RenderWindow);

      GL2_BLEND_DESC BlendState;
      ZeroMemory(&BlendState, sizeof(GL2_BLEND_DESC));
      BlendState.BlendEnable[0] = FALSE;
      BlendState.RenderTargetWriteMask[0] = GL2_COLOR_WRITE_ENABLE_ALL;

      ID3D10BlendState*       g_pBlendStateNoBlend = NULL;
      ID3D10RasterizerState*	g_pRasterizerStateNoCull = NULL;
      m_pGL2Device->CreateBlendState(&BlendState, &g_pBlendStateNoBlend) ;

      // Create a rasterizer state to disable culling
      GL2_RASTERIZER_DESC RSDesc;
      RSDesc.FillMode = GL2_FILL_SOLID;
      RSDesc.CullMode = GL2_CULL_NONE;
      RSDesc.FrontCounterClockwise = TRUE;
      RSDesc.DepthBias = 0;
      RSDesc.DepthBiasClamp = 0;
      RSDesc.SlopeScaledDepthBias = 0;
      RSDesc.ScissorEnable = FALSE;
      RSDesc.MultisampleEnable = TRUE;
      RSDesc.AntialiasedLineEnable = FALSE;
      m_pGL2Device->CreateRasterizerState(&RSDesc, &g_pRasterizerStateNoCull) ;

      m_pGL2Device->OMSetBlendState(g_pBlendStateNoBlend, 0, 0xffffffff);
      m_pGL2Device->RSSetState(g_pRasterizerStateNoCull);
      return true;
}