//--------------------------------------------------------------------- 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; }
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(); } }
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(); } }
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; }
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; }
//-------------------------------------------------------------------------------------- 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 ); } }
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; } }
//-------------------------------------------------------------------------------------- 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 ); } } }
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; }
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; }
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; }
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; }
// // 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; }
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; }