Skip to content

Instantly share code, notes, and snippets.

@rossy
Created December 26, 2017 12:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rossy/fb7b476d272ae166d635156f07d20264 to your computer and use it in GitHub Desktop.
Save rossy/fb7b476d272ae166d635156f07d20264 to your computer and use it in GitHub Desktop.
// 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