Changed: Implement CSystemUtils::getTotalVideoMemory() for Windows
This commit is contained in:
parent
c25320a998
commit
d8f79ed761
2 changed files with 239 additions and 0 deletions
|
@ -81,6 +81,7 @@ public:
|
|||
/// Detect whether the current process is a windowed application. Return true if definitely yes, false if unknown
|
||||
static bool detectWindowedApplication();
|
||||
|
||||
static sint getTotalVideoMemory();
|
||||
};
|
||||
|
||||
} // NLMISC
|
||||
|
|
|
@ -18,6 +18,14 @@
|
|||
#include "nel/misc/system_utils.h"
|
||||
|
||||
#ifdef NL_OS_WINDOWS
|
||||
#define INITGUID
|
||||
#include <ddraw.h>
|
||||
#include <windows.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <dxgi.h>
|
||||
#include <initguid.h>
|
||||
#include <CGuid.h>
|
||||
# include <ObjBase.h>
|
||||
# ifdef _WIN32_WINNT_WIN7
|
||||
// only supported by Windows 7 Platform SDK
|
||||
|
@ -365,4 +373,234 @@ bool CSystemUtils::detectWindowedApplication()
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef NL_OS_WINDOWS
|
||||
#ifndef SAFE_RELEASE
|
||||
#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p) = NULL; } }
|
||||
#endif
|
||||
|
||||
typedef HRESULT (WINAPI* LPDIRECTDRAWCREATE)(GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter);
|
||||
typedef HRESULT (WINAPI* LPCREATEDXGIFACTORY)(REFIID, void**);
|
||||
|
||||
static std::string FormatError(HRESULT hr)
|
||||
{
|
||||
std::string res;
|
||||
|
||||
LPTSTR errorText = NULL;
|
||||
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errorText, 0, NULL);
|
||||
|
||||
if (errorText)
|
||||
{
|
||||
res = NLMISC::toString("%s (0x%x)", errorText, hr);
|
||||
LocalFree(errorText);
|
||||
errorText = NULL;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct SAdapter
|
||||
{
|
||||
uint id;
|
||||
std::string name;
|
||||
sint memory;
|
||||
GUID guid;
|
||||
HMONITOR hMonitor;
|
||||
bool found;
|
||||
|
||||
SAdapter()
|
||||
{
|
||||
id = 0;
|
||||
memory = -1;
|
||||
guid = GUID_NULL;
|
||||
hMonitor = NULL;
|
||||
found = false;
|
||||
}
|
||||
};
|
||||
|
||||
static std::list<SAdapter> s_dxgiAdapters;
|
||||
|
||||
static void EnumerateUsingDXGI(IDXGIFactory *pDXGIFactory)
|
||||
{
|
||||
nlassert(pDXGIFactory != NULL);
|
||||
|
||||
for(uint index = 0; ; ++index)
|
||||
{
|
||||
IDXGIAdapter *pAdapter = NULL;
|
||||
HRESULT hr = pDXGIFactory->EnumAdapters(index, &pAdapter);
|
||||
// DXGIERR_NOT_FOUND is expected when the end of the list is hit
|
||||
if (FAILED(hr)) break;
|
||||
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
memset(&desc, 0, sizeof(DXGI_ADAPTER_DESC));
|
||||
|
||||
if (SUCCEEDED(pAdapter->GetDesc(&desc)))
|
||||
{
|
||||
SAdapter adapter;
|
||||
adapter.id = index;
|
||||
adapter.name = ucstring((ucchar*)desc.Description).toUtf8();
|
||||
adapter.memory = desc.DedicatedVideoMemory / 1024;
|
||||
adapter.found = true;
|
||||
|
||||
nldebug("DXGI Adapter: %u - %s - DedicatedVideoMemory: %d KiB", index, adapter.name.c_str(), adapter.memory);
|
||||
|
||||
s_dxgiAdapters.push_back(adapter);
|
||||
}
|
||||
|
||||
SAFE_RELEASE(pAdapter);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL WINAPI DDEnumCallbackEx(GUID FAR* lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName, LPVOID lpContext, HMONITOR hm)
|
||||
{
|
||||
SAdapter * pAdapter = (SAdapter*)lpContext;
|
||||
|
||||
if (pAdapter->hMonitor == hm)
|
||||
{
|
||||
pAdapter->name = lpDriverDescription;
|
||||
pAdapter->guid = *lpGUID;
|
||||
pAdapter->found = true;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
sint CSystemUtils::getTotalVideoMemory()
|
||||
{
|
||||
sint res = -1;
|
||||
|
||||
#ifdef NL_OS_WINDOWS
|
||||
// using DXGI
|
||||
HINSTANCE hDXGI = LoadLibraryA("dxgi.dll");
|
||||
|
||||
if (hDXGI)
|
||||
{
|
||||
|
||||
// We prefer the use of DXGI 1.1
|
||||
LPCREATEDXGIFACTORY pCreateDXGIFactory = (LPCREATEDXGIFACTORY)GetProcAddress(hDXGI, "CreateDXGIFactory1");
|
||||
|
||||
if (!pCreateDXGIFactory)
|
||||
{
|
||||
pCreateDXGIFactory = (LPCREATEDXGIFACTORY)GetProcAddress(hDXGI, "CreateDXGIFactory");
|
||||
}
|
||||
|
||||
if (pCreateDXGIFactory)
|
||||
{
|
||||
IDXGIFactory *pDXGIFactory = NULL;
|
||||
HRESULT hr = pCreateDXGIFactory(__uuidof(IDXGIFactory), (LPVOID*)&pDXGIFactory);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
EnumerateUsingDXGI(pDXGIFactory);
|
||||
|
||||
SAFE_RELEASE(pDXGIFactory);
|
||||
|
||||
if (!s_dxgiAdapters.empty())
|
||||
{
|
||||
// TODO: determine what adapter is used by NeL
|
||||
res = s_dxgiAdapters.front().memory;
|
||||
}
|
||||
else
|
||||
{
|
||||
nlwarning("Unable to find an DXGI adapter");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nlwarning("Unable to create DXGI factory");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nlwarning("dxgi.dll missing entry-point");
|
||||
}
|
||||
|
||||
FreeLibrary(hDXGI);
|
||||
}
|
||||
|
||||
if (res == -1)
|
||||
{
|
||||
// using DirectDraw
|
||||
HMODULE hInstDDraw = LoadLibraryA("ddraw.dll");
|
||||
|
||||
if (hInstDDraw)
|
||||
{
|
||||
SAdapter adapter;
|
||||
adapter.hMonitor = MonitorFromWindow(s_window, MONITOR_DEFAULTTONULL);
|
||||
|
||||
LPDIRECTDRAWENUMERATEEXA pDirectDrawEnumerateEx = (LPDIRECTDRAWENUMERATEEXA)GetProcAddress(hInstDDraw, "DirectDrawEnumerateExA");
|
||||
LPDIRECTDRAWCREATE pDDCreate = (LPDIRECTDRAWCREATE)GetProcAddress(hInstDDraw, "DirectDrawCreate");
|
||||
|
||||
if (pDirectDrawEnumerateEx && pDDCreate)
|
||||
{
|
||||
HRESULT hr = pDirectDrawEnumerateEx(DDEnumCallbackEx, (VOID*)&adapter, DDENUM_ATTACHEDSECONDARYDEVICES);
|
||||
|
||||
if (SUCCEEDED(hr) && adapter.found)
|
||||
{
|
||||
LPDIRECTDRAW pDDraw = NULL;
|
||||
hr = pDDCreate(&adapter.guid, &pDDraw, NULL);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
LPDIRECTDRAW7 pDDraw7 = NULL;
|
||||
hr = pDDraw->QueryInterface(IID_IDirectDraw7, (VOID**)&pDDraw7);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
DDSCAPS2 ddscaps;
|
||||
memset(&ddscaps, 0, sizeof(DDSCAPS2));
|
||||
ddscaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
|
||||
|
||||
DWORD pdwAvailableVidMem;
|
||||
hr = pDDraw7->GetAvailableVidMem(&ddscaps, &pdwAvailableVidMem, NULL);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
res = (sint)pdwAvailableVidMem / 1024;
|
||||
nlinfo("DirectDraw Adapter: %s - DedicatedVideoMemory: %d KiB", adapter.name.c_str(), adapter.memory);
|
||||
}
|
||||
else
|
||||
{
|
||||
nlwarning("Unable to get DirectDraw available video memory: %s", FormatError(hr).c_str());
|
||||
}
|
||||
|
||||
SAFE_RELEASE(pDDraw7);
|
||||
}
|
||||
else
|
||||
{
|
||||
nlwarning("Unable to query IDirectDraw7 interface: %s", FormatError(hr).c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nlwarning("Unable to call DirectDrawCreate: %s", FormatError(hr).c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nlwarning("Unable to enumerate DirectDraw adapters (%s): %s", (adapter.found ? "found":"not found"), FormatError(hr).c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nlwarning("Unable to get pointer on DirectDraw functions (DirectDrawEnumerateExA %p, DirectDrawCreate %p)", pDirectDrawEnumerateEx, pDDCreate);
|
||||
}
|
||||
|
||||
FreeLibrary(hInstDDraw);
|
||||
}
|
||||
else
|
||||
{
|
||||
nlwarning("Unable to load ddraw.dll");
|
||||
}
|
||||
}
|
||||
#else
|
||||
// TODO: implement for other systems
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // NLMISC
|
||||
|
|
Loading…
Reference in a new issue