From c52c91056bc366ef5491830be49f64d178fa1563 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 13 Feb 2014 11:05:30 -0800 Subject: [PATCH] Added SDL_DXGIGetOutputInfo which returns the adapter and output indices that are used to create DX10 and DX11 devices and swap chains on a particular display. CR: SamL --- include/SDL_system.h | 6 ++ src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 1 + src/test/SDL_test_common.c | 9 ++- src/video/windows/SDL_windowsvideo.c | 85 ++++++++++++++++++++++++++++ 5 files changed, 100 insertions(+), 2 deletions(-) diff --git a/include/SDL_system.h b/include/SDL_system.h index 7913ddf19c2e6..99ef8223eba3f 100644 --- a/include/SDL_system.h +++ b/include/SDL_system.h @@ -55,6 +55,12 @@ extern DECLSPEC int SDLCALL SDL_Direct3D9GetAdapterIndex( int displayIndex ); typedef struct IDirect3DDevice9 IDirect3DDevice9; extern DECLSPEC IDirect3DDevice9* SDLCALL SDL_RenderGetD3D9Device(SDL_Renderer * renderer); +/* Returns the DXGI Adapter and Output indices for the specified display index. + These can be passed to EnumAdapters and EnumOutputs respectively to get the objects + required to create a DX10 or DX11 device and swap chain. + */ +extern DECLSPEC void SDLCALL SDL_DXGIGetOutputInfo( int displayIndex, int *adapterIndex, int *outputIndex ); + #endif /* __WIN32__ */ diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index e6234cb3698c4..5ae7927f2d8cd 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -574,3 +574,4 @@ #define SDL_HasAVX SDL_HasAVX_REAL #define SDL_GetDefaultAssertionHandler SDL_GetDefaultAssertionHandler_REAL #define SDL_GetAssertionHandler SDL_GetAssertionHandler_REAL +#define SDL_DXGIGetOutputInfo SDL_DXGIGetOutputInfo_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 362bb83d1777e..260bf13ac0337 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -70,6 +70,7 @@ SDL_DYNAPI_PROC(void,SDL_MemoryBarrierAcquire,(void),(),) SDL_DYNAPI_PROC(int,SDL_RegisterApp,(char *a, Uint32 b, void *c),(a,b,c),return) SDL_DYNAPI_PROC(void,SDL_UnregisterApp,(void),(),) SDL_DYNAPI_PROC(int,SDL_Direct3D9GetAdapterIndex,(int a),(a),return) +SDL_DYNAPI_PROC(void,SDL_DXGIGetOutputInfo,(int a,int *b, int *c),(a,b,c),) SDL_DYNAPI_PROC(IDirect3DDevice9*,SDL_RenderGetD3D9Device,(SDL_Renderer *a),(a),return) #endif diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index b2b87a1b20b8e..c03da03ab9e27 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -706,6 +706,7 @@ SDLTest_CommonInit(SDLTest_CommonState * state) Uint32 Rmask, Gmask, Bmask, Amask; #if SDL_VIDEO_DRIVER_WINDOWS int adapterIndex = 0; + int outputIndex = 0; #endif n = SDL_GetNumVideoDisplays(); fprintf(stderr, "Number of displays: %d\n", n); @@ -761,9 +762,13 @@ SDLTest_CommonInit(SDLTest_CommonState * state) } #if SDL_VIDEO_DRIVER_WINDOWS - /* Print the adapter index */ + /* Print the D3D9 adapter index */ adapterIndex = SDL_Direct3D9GetAdapterIndex( i ); - fprintf( stderr, "Adapter Index: %d", adapterIndex ); + fprintf( stderr, "D3D9 Adapter Index: %d", adapterIndex ); + + /* Print the DXGI adapter and output indices */ + SDL_DXGIGetOutputInfo(i, &adapterIndex, &outputIndex); + fprintf( stderr, "DXGI Adapter Index: %d Output Index: %d", adapterIndex, outputIndex ); #endif } } diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c index 9ad5613e0b518..dde262268af47 100644 --- a/src/video/windows/SDL_windowsvideo.c +++ b/src/video/windows/SDL_windowsvideo.c @@ -245,6 +245,91 @@ SDL_Direct3D9GetAdapterIndex( int displayIndex ) } } +#define CINTERFACE +#define COBJMACROS +#include + +SDL_bool +DXGI_LoadDLL( void **pDXGIDLL , IDXGIFactory **pDXGIFactory ) +{ + *pDXGIDLL = SDL_LoadObject("DXGI.DLL"); + if (*pDXGIDLL ) { + HRESULT (WINAPI *CreateDXGI)( REFIID riid, void **ppFactory ); + + CreateDXGI = + (HRESULT (WINAPI *) (REFIID, void**)) SDL_LoadFunction(*pDXGIDLL, + "CreateDXGIFactory"); + if (CreateDXGI) { + GUID dxgiGUID = {0x7b7166ec,0x21c7,0x44ae,{0xb2,0x1a,0xc9,0xae,0x32,0x1a,0xe3,0x69}}; + if( !SUCCEEDED( CreateDXGI( &dxgiGUID, pDXGIFactory ))) { + *pDXGIFactory = NULL; + } + } + if (!*pDXGIFactory) { + SDL_UnloadObject(*pDXGIDLL); + *pDXGIDLL = NULL; + return SDL_FALSE; + } + + return SDL_TRUE; + } else { + *pDXGIFactory = NULL; + return SDL_FALSE; + } +} + + +void +SDL_DXGIGetOutputInfo( int displayIndex, int *adapterIndex, int *outputIndex ) +{ + void *pDXGIDLL; + IDXGIFactory *pDXGIFactory; + + *adapterIndex = -1; + *outputIndex = -1; + + if (!DXGI_LoadDLL(&pDXGIDLL, &pDXGIFactory)) { + SDL_SetError("Unable to create DXGI interface"); + } else { + SDL_DisplayData *pData = (SDL_DisplayData *)SDL_GetDisplayDriverData(displayIndex); + + if (!pData) { + SDL_SetError("Invalid display index"); + } else { + char *displayName = WIN_StringToUTF8(pData->DeviceName); + int nAdapter = 0, nOutput = 0; + IDXGIAdapter* pDXGIAdapter; + while ( *adapterIndex == -1 && IDXGIFactory_EnumAdapters(pDXGIFactory, nAdapter, &pDXGIAdapter) != DXGI_ERROR_NOT_FOUND ) { + IDXGIOutput* pDXGIOutput; + while ( *adapterIndex == -1 && IDXGIAdapter_EnumOutputs(pDXGIAdapter, nOutput, &pDXGIOutput) != DXGI_ERROR_NOT_FOUND ) { + DXGI_OUTPUT_DESC outputDesc; + if (SUCCEEDED(IDXGIOutput_GetDesc(pDXGIOutput, &outputDesc))) { + char *outputName = WIN_StringToUTF8(outputDesc.DeviceName); + + if(!SDL_strcmp(outputName, displayName)) { + *adapterIndex = nAdapter; + *outputIndex = nOutput; + } + + SDL_free( outputName ); + } + + IDXGIOutput_Release( pDXGIOutput ); + nOutput++; + } + + IDXGIAdapter_Release( pDXGIAdapter ); + nAdapter++; + } + SDL_free(displayName); + } + + /* free up the D3D stuff we inited */ + IDXGIFactory_AddRef( pDXGIFactory ); + SDL_UnloadObject(pDXGIDLL); + } +} + #endif /* SDL_VIDEO_DRIVER_WINDOWS */ /* vim: set ts=4 sw=4 expandtab: */