Commit c52c91056bc366ef5491830be49f64d178fa1563

Sam Lantinga 2014-02-13T11:05:30

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

diff --git a/include/SDL_system.h b/include/SDL_system.h
index 7913ddf..99ef822 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 e6234cb..5ae7927 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 362bb83..260bf13 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 b2b87a1..c03da03 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 9ad5613..dde2622 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 <DXGI.h>
+
+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: */