From 8284c8d015d7bed862bd14dfd24c0a90cf0ecbd7 Mon Sep 17 00:00:00 2001
From: Samuel Gateau <samuel.gateau@gmail.com>
Date: Thu, 4 Jul 2019 01:55:48 -0700
Subject: [PATCH] doing the full enumeration in windows

---
 .../platform/src/platform/PlatformKeys.h      |   2 +
 .../src/platform/backend/Platform.cpp         |   2 +
 .../src/platform/backend/PlatformInstance.cpp |   2 +
 .../src/platform/backend/WINPlatform.cpp      | 104 +++++++++++++++++-
 4 files changed, 109 insertions(+), 1 deletion(-)

diff --git a/libraries/platform/src/platform/PlatformKeys.h b/libraries/platform/src/platform/PlatformKeys.h
index e6c255ce75..bb71e88f94 100644
--- a/libraries/platform/src/platform/PlatformKeys.h
+++ b/libraries/platform/src/platform/PlatformKeys.h
@@ -30,6 +30,7 @@ namespace platform { namespace keys{
         extern const char*  model;
         extern const char*  videoMemory;
         extern const char*  driver;
+        extern const char*  displays;
     }
     namespace nic {
         extern const char* mac;
@@ -42,6 +43,7 @@ namespace platform { namespace keys{
         extern const char*  coordsRight;
         extern const char*  coordsTop;
         extern const char*  coordsBottom;
+        extern const char*  gpu;
     }
     namespace memory {
         extern const char*  memTotal;
diff --git a/libraries/platform/src/platform/backend/Platform.cpp b/libraries/platform/src/platform/backend/Platform.cpp
index 9284e0b3a0..a8c0f1b111 100644
--- a/libraries/platform/src/platform/backend/Platform.cpp
+++ b/libraries/platform/src/platform/backend/Platform.cpp
@@ -31,6 +31,7 @@ namespace platform { namespace keys {
         const char*  model = "model";
         const char*  videoMemory = "videoMemory";
         const char*  driver = "driver";
+        const char*  displays = "displays";
     }
     namespace nic {
         const char* mac = "mac";
@@ -43,6 +44,7 @@ namespace platform { namespace keys {
         const char*  coordsRight = "coordinatesright";
         const char*  coordsTop = "coordinatestop";
         const char*  coordsBottom = "coordinatesbottom";
+        const char*  gpu = "gpu";
     }
     namespace memory {
         const char*  memTotal = "memTotal";
diff --git a/libraries/platform/src/platform/backend/PlatformInstance.cpp b/libraries/platform/src/platform/backend/PlatformInstance.cpp
index 33b19cd012..69825cbfa5 100644
--- a/libraries/platform/src/platform/backend/PlatformInstance.cpp
+++ b/libraries/platform/src/platform/backend/PlatformInstance.cpp
@@ -98,6 +98,7 @@ json Instance::listAllKeys() {
         keys::gpu::model,
         keys::gpu::videoMemory,
         keys::gpu::driver,
+        keys::gpu::displays,
 
         keys::display::description,
         keys::display::name,
@@ -105,6 +106,7 @@ json Instance::listAllKeys() {
         keys::display::coordsRight,
         keys::display::coordsTop,
         keys::display::coordsBottom,
+        keys::display::gpu,
 
         keys::memory::memTotal,
 
diff --git a/libraries/platform/src/platform/backend/WINPlatform.cpp b/libraries/platform/src/platform/backend/WINPlatform.cpp
index d07bb83510..0c09ae2de6 100644
--- a/libraries/platform/src/platform/backend/WINPlatform.cpp
+++ b/libraries/platform/src/platform/backend/WINPlatform.cpp
@@ -19,6 +19,8 @@
 #include <iphlpapi.h>
 #include <stdio.h>
 #include <QSysInfo>
+#include <dxgi1_3.h>
+#pragma comment(lib, "dxgi.lib")
 #endif
 
 using namespace platform;
@@ -34,6 +36,106 @@ void WINInstance::enumerateCpus() {
 }
 
 void WINInstance::enumerateGpus() {
+#ifdef Q_OS_WIN
+    struct ConvertLargeIntegerToQString {
+        QString convert(const LARGE_INTEGER& version) {
+            QString value;
+            value.append(QString::number(uint32_t(((version.HighPart & 0xFFFF0000) >> 16) & 0x0000FFFF)));
+            value.append(".");
+            value.append(QString::number(uint32_t((version.HighPart) & 0x0000FFFF)));
+            value.append(".");
+            value.append(QString::number(uint32_t(((version.LowPart & 0xFFFF0000) >> 16) & 0x0000FFFF)));
+            value.append(".");
+            value.append(QString::number(uint32_t((version.LowPart) & 0x0000FFFF)));
+            return value;
+        }
+    } convertDriverVersionToString;
+
+    // Create the DXGI factory
+    // Let s get into DXGI land:
+    HRESULT hr = S_OK;
+
+    IDXGIFactory1* pFactory = nullptr;
+    hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&pFactory));
+    if (hr != S_OK || pFactory == nullptr) {
+//        qCDebug(shared) << "Unable to create DXGI";
+        return;
+    }
+
+    std::vector<int> validAdapterList;
+    using AdapterEntry = std::pair<std::pair<DXGI_ADAPTER_DESC1, LARGE_INTEGER>, std::vector<DXGI_OUTPUT_DESC>>;
+    std::vector<AdapterEntry> adapterToOutputs;
+    // Enumerate adapters and outputs
+    {
+        UINT adapterNum = 0;
+        IDXGIAdapter1* pAdapter = nullptr;
+        while (pFactory->EnumAdapters1(adapterNum, &pAdapter) != DXGI_ERROR_NOT_FOUND) {
+            // Found an adapter, get descriptor
+            DXGI_ADAPTER_DESC1 adapterDesc;
+            pAdapter->GetDesc1(&adapterDesc);
+
+            LARGE_INTEGER version;
+            hr = pAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &version);
+
+            std::wstring wDescription(adapterDesc.Description);
+            std::string description(wDescription.begin(), wDescription.end());
+
+            json gpu = {};
+            gpu[keys::gpu::model] = description;
+            gpu[keys::gpu::vendor] = findGPUVendorInDescription(gpu[keys::gpu::model].get<std::string>());
+            const SIZE_T BYTES_PER_MEGABYTE = 1024 * 1024;
+            gpu[keys::gpu::videoMemory] = (uint32_t)(adapterDesc.DedicatedVideoMemory / BYTES_PER_MEGABYTE);
+            gpu[keys::gpu::driver] = convertDriverVersionToString.convert(version).toStdString();
+
+
+            std::vector<int> displayIndices;
+
+            UINT outputNum = 0;
+            IDXGIOutput* pOutput;
+            bool hasOutputConnectedToDesktop = false;
+            while (pAdapter->EnumOutputs(outputNum, &pOutput) != DXGI_ERROR_NOT_FOUND) {
+                // FOund an output attached to the adapter, get descriptor
+                DXGI_OUTPUT_DESC outputDesc;
+                pOutput->GetDesc(&outputDesc);
+
+                // Grab the Monitor desc
+                // MONITOR_DESC
+
+                json display = {};
+
+                // Desiplay name
+                std::wstring wDeviceName(outputDesc.DeviceName);
+                std::string deviceName(wDeviceName.begin(), wDeviceName.end());
+                display[keys::display::name] = deviceName;
+                display[keys::display::description] = "";
+
+                // Rect region of the desktop in desktop units
+                display["desktopRect"] = (outputDesc.AttachedToDesktop ? true : false);
+                display[keys::display::coordsLeft] = outputDesc.DesktopCoordinates.left;
+                display[keys::display::coordsRight] = outputDesc.DesktopCoordinates.right;
+                display[keys::display::coordsBottom] = outputDesc.DesktopCoordinates.bottom;
+                display[keys::display::coordsTop] = outputDesc.DesktopCoordinates.top;
+
+                // Add the display index to the list of displays of the gpu
+                displayIndices.push_back(_displays.size());
+                
+                // And set the gpu index to the display description
+                display[keys::display::gpu] = _gpus.size();
+
+                // One more display desc
+                _displays.push_back(display);
+                pOutput->Release();
+                outputNum++;
+            }
+            gpu[keys::gpu::displays] = displayIndices;
+
+            _gpus.push_back(gpu);
+            pAdapter->Release();
+            adapterNum++;
+        }
+    }
+    pFactory->Release();
+#endif
 
     GPUIdent* ident = GPUIdent::getInstance();
    
@@ -44,7 +146,7 @@ void WINInstance::enumerateGpus() {
     gpu[keys::gpu::driver] = ident->getDriver().toUtf8().constData();
 
     _gpus.push_back(gpu);
-    _displays = ident->getOutput();
+  //  _displays = ident->getOutput();
 }
 
 void WINInstance::enumerateMemory() {