Created
December 26, 2017 12:51
-
-
Save rossy/fb7b476d272ae166d635156f07d20264 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// gcc -Wall dxgiinfo.c -o dxgiinfo -ldxgi -ld3d11 | |
#define COBJMACROS | |
#include <initguid.h> | |
#include <stdbool.h> | |
#include <stdio.h> | |
#include <conio.h> | |
#include <dxgi1_5.h> | |
#include <d3d11.h> | |
typedef struct DXGI_OUTPUT_DESC1 { | |
WCHAR DeviceName[32]; | |
RECT DesktopCoordinates; | |
BOOL AttachedToDesktop; | |
DXGI_MODE_ROTATION Rotation; | |
HMONITOR Monitor; | |
UINT BitsPerColor; | |
DXGI_COLOR_SPACE_TYPE ColorSpace; | |
FLOAT RedPrimary[2]; | |
FLOAT GreenPrimary[2]; | |
FLOAT BluePrimary[2]; | |
FLOAT WhitePoint[2]; | |
FLOAT MinLuminance; | |
FLOAT MaxLuminance; | |
FLOAT MaxFullFrameLuminance; | |
} DXGI_OUTPUT_DESC1; | |
#undef INTERFACE | |
#define INTERFACE IDXGIOutput6 | |
DECLARE_INTERFACE_IID_(IDXGIOutput6, IDXGIOutput5, | |
"068346e8-aaec-4b84-add7-137f513f77a1") { | |
BEGIN_INTERFACE | |
STDMETHOD(QueryInterface)(THIS_ REFIID riid, void **ppvObject) PURE; | |
STDMETHOD_(ULONG, AddRef)(THIS) PURE; | |
STDMETHOD_(ULONG, Release)(THIS) PURE; | |
STDMETHOD(SetPrivateData)(THIS_ REFGUID guid, UINT data_size, | |
const void *data) PURE; | |
STDMETHOD(SetPrivateDataInterface)(THIS_ REFGUID guid, | |
const IUnknown *object) PURE; | |
STDMETHOD(GetPrivateData)(THIS_ REFGUID guid, UINT *data_size, | |
void *data) PURE; | |
STDMETHOD(GetParent)(THIS_ REFIID riid, void **parent) PURE; | |
STDMETHOD(GetDesc)(THIS_ DXGI_OUTPUT_DESC *desc) PURE; | |
STDMETHOD(GetDisplayModeList)(THIS_ DXGI_FORMAT format, UINT flags, | |
UINT *mode_count, DXGI_MODE_DESC *desc) PURE; | |
STDMETHOD(FindClosestMatchingMode)(THIS_ const DXGI_MODE_DESC *mode, | |
DXGI_MODE_DESC *closest_match, IUnknown *device) PURE; | |
STDMETHOD(WaitForVBlank)(THIS) PURE; | |
STDMETHOD(TakeOwnership)(THIS_ IUnknown *device, WINBOOL exclusive) PURE; | |
STDMETHOD_(void, ReleaseOwnership)(THIS) PURE; | |
STDMETHOD(GetGammaControlCapabilities)(THIS_ | |
DXGI_GAMMA_CONTROL_CAPABILITIES *gamma_caps) PURE; | |
STDMETHOD(SetGammaControl)(THIS_ | |
const DXGI_GAMMA_CONTROL *gamma_control) PURE; | |
STDMETHOD(GetGammaControl)(THIS_ DXGI_GAMMA_CONTROL *gamma_control) PURE; | |
STDMETHOD(SetDisplaySurface)(THIS_ IDXGISurface *surface) PURE; | |
STDMETHOD(GetDisplaySurfaceData)(THIS_ IDXGISurface *surface) PURE; | |
STDMETHOD(GetFrameStatistics)(THIS_ DXGI_FRAME_STATISTICS *stats) PURE; | |
STDMETHOD(GetDisplayModeList1)(THIS_ DXGI_FORMAT enum_format, | |
UINT flags, UINT *num_modes, DXGI_MODE_DESC1 *desc) PURE; | |
STDMETHOD(FindClosestMatchingMode1)(THIS_ | |
const DXGI_MODE_DESC1 *mode_to_match, DXGI_MODE_DESC1 *closest_match, | |
IUnknown *concerned_device) PURE; | |
STDMETHOD(GetDisplaySurfaceData1)(THIS_ IDXGIResource *destination) PURE; | |
STDMETHOD(DuplicateOutput)(THIS_ IUnknown *device, | |
IDXGIOutputDuplication **output_duplication) PURE; | |
STDMETHOD_(BOOL, SupportsOverlays)(THIS) PURE; | |
STDMETHOD(CheckOverlaySupport)(THIS_ DXGI_FORMAT enum_format, | |
IUnknown *concerned_device, UINT *flags) PURE; | |
STDMETHOD(CheckOverlayColorSpaceSupport)(THIS_ DXGI_FORMAT format, | |
DXGI_COLOR_SPACE_TYPE colour_space, IUnknown *device, | |
UINT *flags) PURE; | |
STDMETHOD(DuplicateOutput1)(THIS_ IUnknown *device, UINT flags, | |
UINT format_count, const DXGI_FORMAT *formats, | |
IDXGIOutputDuplication **duplication) PURE; | |
STDMETHOD(GetDesc1)(THIS_ DXGI_OUTPUT_DESC1 *desc) PURE; | |
STDMETHOD(CheckHardwareCompositionSupport)(THIS_ UINT* flags) PURE; | |
END_INTERFACE | |
}; | |
#ifdef COBJMACROS | |
#define IDXGIOutput6_QueryInterface(This, riid, ppvObject) ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) | |
#define IDXGIOutput6_AddRef(This) ((This)->lpVtbl->AddRef(This)) | |
#define IDXGIOutput6_Release(This) ((This)->lpVtbl->Release(This)) | |
#define IDXGIOutput6_SetPrivateData(This, guid, data_size, data) ((This)->lpVtbl->SetPrivateData(This, guid, data_size, data)) | |
#define IDXGIOutput6_SetPrivateDataInterface(This, guid, object) ((This)->lpVtbl->SetPrivateDataInterface(This, guid, object)) | |
#define IDXGIOutput6_GetPrivateData(This, guid, data_size, data) ((This)->lpVtbl->GetPrivateData(This, guid, data_size, data)) | |
#define IDXGIOutput6_GetParent(This, riid, parent) ((This)->lpVtbl->GetParent(This, riid, parent)) | |
#define IDXGIOutput6_GetDesc(This, desc) ((This)->lpVtbl->GetDesc(This, desc)) | |
#define IDXGIOutput6_GetDisplayModeList(This, format, flags, mode_count, desc) ((This)->lpVtbl->GetDisplayModeList(This, format, flags, mode_count, desc)) | |
#define IDXGIOutput6_FindClosestMatchingMode(This, mode, closest_match, device) ((This)->lpVtbl->FindClosestMatchingMode(This, mode, closest_match, device)) | |
#define IDXGIOutput6_WaitForVBlank(This) ((This)->lpVtbl->WaitForVBlank(This)) | |
#define IDXGIOutput6_TakeOwnership(This, device, exclusive) ((This)->lpVtbl->TakeOwnership(This, device, exclusive)) | |
#define IDXGIOutput6_ReleaseOwnership(This) ((This)->lpVtbl->ReleaseOwnership(This)) | |
#define IDXGIOutput6_GetGammaControlCapabilities(This, gamma_caps) ((This)->lpVtbl->GetGammaControlCapabilities(This, gamma_caps)) | |
#define IDXGIOutput6_SetGammaControl(This, gamma_control) ((This)->lpVtbl->SetGammaControl(This, gamma_control)) | |
#define IDXGIOutput6_GetGammaControl(This, gamma_control) ((This)->lpVtbl->GetGammaControl(This, gamma_control)) | |
#define IDXGIOutput6_SetDisplaySurface(This, surface) ((This)->lpVtbl->SetDisplaySurface(This, surface)) | |
#define IDXGIOutput6_GetDisplaySurfaceData(This, surface) ((This)->lpVtbl->GetDisplaySurfaceData(This, surface)) | |
#define IDXGIOutput6_GetFrameStatistics(This, stats) ((This)->lpVtbl->GetFrameStatistics(This, stats)) | |
#define IDXGIOutput6_GetDisplayModeList1(This, enum_format, flags, num_modes, desc) ((This)->lpVtbl->GetDisplayModeList1(This, enum_format, flags, num_modes, desc)) | |
#define IDXGIOutput6_FindClosestMatchingMode1(This, mode_to_match, closest_match, concerned_device) ((This)->lpVtbl->FindClosestMatchingMode1(This, mode_to_match, closest_match, concerned_device)) | |
#define IDXGIOutput6_GetDisplaySurfaceData1(This, destination) ((This)->lpVtbl->GetDisplaySurfaceData1(This, destination)) | |
#define IDXGIOutput6_DuplicateOutput(This, device, output_duplication) ((This)->lpVtbl->DuplicateOutput(This, device, output_duplication)) | |
#define IDXGIOutput6_SupportsOverlays(This) ((This)->lpVtbl->SupportsOverlays(This)) | |
#define IDXGIOutput6_CheckOverlaySupport(This, enum_format, concerned_device, flags) ((This)->lpVtbl->CheckOverlaySupport(This, enum_format, concerned_device, flags)) | |
#define IDXGIOutput6_CheckOverlayColorSpaceSupport(This, format, colour_space, device, flags) ((This)->lpVtbl->CheckOverlayColorSpaceSupport(This, format, colour_space, device, flags)) | |
#define IDXGIOutput6_DuplicateOutput1(This, device, flags, format_count, formats, duplication) ((This)->lpVtbl->DuplicateOutput1(This, device, flags, format_count, formats, duplication)) | |
#define IDXGIOutput6_GetDesc1(This, desc) ((This)->lpVtbl->GetDesc1(This, desc)) | |
#define IDXGIOutput6_CheckHardwareCompositionSupport(This, flags) ((This)->lpVtbl->CheckHardwareCompositionSupport(This, flags)) | |
#endif | |
#define DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P709 ((DXGI_COLOR_SPACE_TYPE)20) | |
#define DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P2020 ((DXGI_COLOR_SPACE_TYPE)21) | |
#define DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P709 ((DXGI_COLOR_SPACE_TYPE)22) | |
#define DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P2020 ((DXGI_COLOR_SPACE_TYPE)23) | |
#define DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_TOPLEFT_P2020 ((DXGI_COLOR_SPACE_TYPE)24) | |
DEFINE_GUID(IID_IDXGIOutput6, 0x068346e8, 0xaaec, 0x4b84, 0xad, 0xd7, 0x13, 0x7f, 0x51, 0x3f, 0x77, 0xa1); | |
#undef INTERFACE | |
#define SAFE_RELEASE(u) \ | |
do { if ((u) != NULL) (u)->lpVtbl->Release(u); (u) = NULL; } while(0) | |
static const char *format_bool(BOOL b) | |
{ | |
return b ? "TRUE" : "FALSE"; | |
} | |
static const char *format_color_space(DXGI_COLOR_SPACE_TYPE space) | |
{ | |
switch (space) { | |
case DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709: | |
return "DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709"; | |
case DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709: | |
return "DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709"; | |
case DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709: | |
return "DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709"; | |
case DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020: | |
return "DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020"; | |
case DXGI_COLOR_SPACE_RESERVED: | |
return "DXGI_COLOR_SPACE_RESERVED"; | |
case DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601: | |
return "DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601"; | |
case DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601: | |
return "DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601"; | |
case DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601: | |
return "DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601"; | |
case DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709: | |
return "DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709"; | |
case DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709: | |
return "DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709"; | |
case DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020: | |
return "DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020"; | |
case DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020: | |
return "DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020"; | |
case DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020: | |
return "DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020"; | |
case DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020: | |
return "DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020"; | |
case DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020: | |
return "DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020"; | |
case DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_TOPLEFT_P2020: | |
return "DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_TOPLEFT_P2020"; | |
case DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_TOPLEFT_P2020: | |
return "DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_TOPLEFT_P2020"; | |
case DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020: | |
return "DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020"; | |
case DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_TOPLEFT_P2020: | |
return "DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_TOPLEFT_P2020"; | |
case DXGI_COLOR_SPACE_YCBCR_FULL_GHLG_TOPLEFT_P2020: | |
return "DXGI_COLOR_SPACE_YCBCR_FULL_GHLG_TOPLEFT_P2020"; | |
case DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P709: | |
return "DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P709"; | |
case DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P2020: | |
return "DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P2020"; | |
case DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P709: | |
return "DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P709"; | |
case DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P2020: | |
return "DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P2020"; | |
case DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_TOPLEFT_P2020: | |
return "DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_TOPLEFT_P2020"; | |
case DXGI_COLOR_SPACE_CUSTOM: | |
return "DXGI_COLOR_SPACE_CUSTOM"; | |
default: | |
return "Unknown"; | |
} | |
} | |
static const char *format_dxgi_fmt(DXGI_FORMAT fmt) | |
{ | |
switch (fmt) { | |
case DXGI_FORMAT_UNKNOWN: | |
return "DXGI_FORMAT_UNKNOWN"; | |
case DXGI_FORMAT_R16G16B16A16_FLOAT: | |
return "DXGI_FORMAT_R16G16B16A16_FLOAT"; | |
case DXGI_FORMAT_R10G10B10A2_UNORM: | |
return "DXGI_FORMAT_R10G10B10A2_UNORM"; | |
case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: | |
return "DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM"; | |
case DXGI_FORMAT_R8G8B8A8_UNORM: | |
return "DXGI_FORMAT_R8G8B8A8_UNORM"; | |
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: | |
return "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB"; | |
case DXGI_FORMAT_B8G8R8A8_UNORM: | |
return "DXGI_FORMAT_B8G8R8A8_UNORM"; | |
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: | |
return "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB"; | |
default: | |
return "Unknown"; | |
} | |
} | |
static bool has_own_console(void) | |
{ | |
HWND wnd = GetConsoleWindow(); | |
if (!wnd) | |
return false; | |
DWORD con_pid = 0; | |
GetWindowThreadProcessId(wnd, &con_pid); | |
return con_pid == GetCurrentProcessId(); | |
} | |
static void maybe_pause(void) | |
{ | |
if (!has_own_console()) | |
return; | |
printf("Press any key to continue . . ."); | |
_getch(); | |
printf("\n"); | |
} | |
int main() | |
{ | |
IDXGIFactory5 *factory = NULL; | |
IDXGIAdapter1 *adapter = NULL; | |
ID3D11Device *dev = NULL; | |
IDXGIOutput *output = NULL; | |
IDXGIOutput6 *output6 = NULL; | |
bool success = false; | |
HRESULT hr; | |
hr = CreateDXGIFactory1(&IID_IDXGIFactory5, (void**)&factory); | |
if (FAILED(hr)) { | |
fprintf(stderr, "Failed to create DXGI factory: 0x%08x\n", (unsigned)hr); | |
goto done; | |
} | |
for (int i = 0;; i++) { | |
hr = IDXGIFactory5_EnumAdapters1(factory, i, &adapter); | |
if (hr == DXGI_ERROR_NOT_FOUND) | |
break; | |
if (FAILED(hr)) { | |
fprintf(stderr, "Failed get adapter: 0x%08x\n", (unsigned)hr); | |
goto done; | |
} | |
DXGI_ADAPTER_DESC1 adesc1 = { 0 }; | |
IDXGIAdapter1_GetDesc1(adapter, &adesc1); | |
printf("Adapter %d:\n" | |
" Device Name: %ls\n" | |
" Device ID: %04x:%04x (rev %02x)\n" | |
" Subsystem ID: %04x:%04x\n" | |
" LUID: %08lx%08lx\n", | |
i, | |
adesc1.Description, | |
adesc1.VendorId, adesc1.DeviceId, adesc1.Revision, | |
LOWORD(adesc1.SubSysId), HIWORD(adesc1.SubSysId), | |
adesc1.AdapterLuid.HighPart, adesc1.AdapterLuid.LowPart); | |
D3D11CreateDevice((IDXGIAdapter*)adapter, D3D_DRIVER_TYPE_UNKNOWN, | |
NULL, 0, NULL, 0, D3D11_SDK_VERSION, &dev, NULL, NULL); | |
for (int j = 0;; j++) { | |
hr = IDXGIAdapter1_EnumOutputs(adapter, j, &output); | |
if (hr == DXGI_ERROR_NOT_FOUND) | |
break; | |
if (FAILED(hr)) { | |
fprintf(stderr, "Failed get output: 0x%08x\n", (unsigned)hr); | |
goto done; | |
} | |
hr = IDXGIOutput_QueryInterface(output, &IID_IDXGIOutput6, | |
(void**)&output6); | |
if (FAILED(hr)) { | |
fprintf(stderr, "DXGI 1.6 not supported: 0x%08x\n", (unsigned)hr); | |
goto done; | |
} | |
DXGI_OUTPUT_DESC1 odesc1 = { 0 }; | |
IDXGIOutput6_GetDesc1(output6, &odesc1); | |
printf(" Output %d:\n" | |
" Device Name: %ls\n" | |
" Coordinates: %ldx%ld%+ld%+ld\n" | |
" Attached to desktop: %s\n" | |
" Bits-per-color: %u\n" | |
" Color space: %s (%u)\n" | |
" Red primary: %.3f, %.3f\n" | |
" Green primary: %.3f, %.3f\n" | |
" Blue primary: %.3f, %.3f\n" | |
" White point: %.3f, %.3f\n" | |
" Min luminance: %g nits\n" | |
" Max luminance: %g nits\n" | |
" Max full-frame luminance: %g nits\n", | |
j, | |
odesc1.DeviceName, | |
odesc1.DesktopCoordinates.right - odesc1.DesktopCoordinates.left, | |
odesc1.DesktopCoordinates.bottom - odesc1.DesktopCoordinates.top, | |
odesc1.DesktopCoordinates.top, odesc1.DesktopCoordinates.left, | |
format_bool(odesc1.AttachedToDesktop), | |
odesc1.BitsPerColor, | |
format_color_space(odesc1.ColorSpace), | |
(unsigned)odesc1.ColorSpace, | |
odesc1.RedPrimary[0], odesc1.RedPrimary[1], | |
odesc1.GreenPrimary[0], odesc1.GreenPrimary[1], | |
odesc1.BluePrimary[0], odesc1.BluePrimary[1], | |
odesc1.WhitePoint[0], odesc1.WhitePoint[1], | |
odesc1.MinLuminance, | |
odesc1.MaxLuminance, | |
odesc1.MaxFullFrameLuminance); | |
if (dev) { | |
DXGI_MODE_DESC1 mode = { 0 }; | |
IDXGIOutput6_FindClosestMatchingMode1(output6, | |
&(DXGI_MODE_DESC1){ 0 }, &mode, (IUnknown*)dev); | |
printf(" Desktop mode: %s (%u)\n", | |
format_dxgi_fmt(mode.Format), (unsigned)mode.Format); | |
} | |
SAFE_RELEASE(output); | |
SAFE_RELEASE(output6); | |
} | |
SAFE_RELEASE(adapter); | |
SAFE_RELEASE(dev); | |
} | |
success = true; | |
done: | |
SAFE_RELEASE(factory); | |
SAFE_RELEASE(adapter); | |
SAFE_RELEASE(dev); | |
SAFE_RELEASE(output); | |
SAFE_RELEASE(output6); | |
maybe_pause(); | |
return success ? 0 : 1; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment