diff --git a/src/console/Device.cpp b/src/console/Device.cpp index fd3dd0b..fe529d6 100644 --- a/src/console/Device.cpp +++ b/src/console/Device.cpp @@ -3,8 +3,10 @@ #include "console/Console.hpp" #include "console/CVar.hpp" #include "event/Input.hpp" +#include "gx/Adapter.hpp" #include "gx/Device.hpp" #include +#include static CGxDevice* s_device; static CVar* s_cvGxMaximize; @@ -12,6 +14,7 @@ static CVar* s_cvGxResolution; static CVar* s_cvGxWidescreen; static CVar* s_cvGxWindow; static DefaultSettings s_defaults; +static TSGrowableArray s_gxMonitorModes; static bool s_hwDetect; static bool s_hwChanged; static CGxFormat s_requestedFormat; @@ -158,6 +161,8 @@ void ConsoleDeviceInitialize(const char* title) { // TODO ConsoleCommandRegister("gxRestart", &CCGxRestart, 1, nullptr); + GxAdapterMonitorModes(s_gxMonitorModes); + // TODO // TODO diff --git a/src/gx/Adapter.cpp b/src/gx/Adapter.cpp new file mode 100644 index 0000000..447e909 --- /dev/null +++ b/src/gx/Adapter.cpp @@ -0,0 +1,6 @@ +#include "gx/Adapter.hpp" +#include "gx/CGxDevice.hpp" + +int32_t GxAdapterMonitorModes(TSGrowableArray& monitorModes) { + return CGxDevice::AdapterMonitorModes(monitorModes); +} diff --git a/src/gx/Adapter.hpp b/src/gx/Adapter.hpp new file mode 100644 index 0000000..8293c94 --- /dev/null +++ b/src/gx/Adapter.hpp @@ -0,0 +1,10 @@ +#ifndef GX_ADAPTER_HPP +#define GX_ADAPTER_HPP + +#include "gx/CGxMonitorMode.hpp" +#include +#include + +int32_t GxAdapterMonitorModes(TSGrowableArray& monitorModes); + +#endif diff --git a/src/gx/CGxDevice.cpp b/src/gx/CGxDevice.cpp index 16387a9..0091937 100644 --- a/src/gx/CGxDevice.cpp +++ b/src/gx/CGxDevice.cpp @@ -1,21 +1,25 @@ #include "gx/CGxDevice.hpp" +#include "gx/CGxMonitorMode.hpp" #include "gx/Gx.hpp" #include "gx/Shader.hpp" #include "gx/texture/CGxTex.hpp" #include "util/SFile.hpp" +#include +#include #include #include #include #include -#include -#include #if defined(WHOA_SYSTEM_WIN) #include "gx/d3d/CGxDeviceD3d.hpp" + #include "gx/win/Display.hpp" #endif #if defined(WHOA_SYSTEM_MAC) #include "gx/gll/CGxDeviceGLL.hpp" + #include "gx/mac/Display.hpp" + #include #endif uint32_t CGxDevice::s_alphaRef[] = { @@ -92,6 +96,42 @@ uint32_t CGxDevice::s_texFormatBytesPerBlock[] = { 4 // GxTex_D24X8 }; +int32_t CGxDevice::AdapterMonitorModes(TSGrowableArray& monitorModes) { +#if defined(WHOA_SYSTEM_WIN) + + return CGxDevice::WinAdapterMonitorModes(monitorModes); + +#elif defined(WHOA_SYSTEM_MAC) + + // TODO conditional check on s_cvGxApi + auto api = GxApi_OpenGl; // avoiding GLLAdapterMonitorModes for now + + if (api == GxApi_OpenGl) { + return CGxDevice::MacAdapterMonitorModes(monitorModes); + } + + if (api == GxApi_GLL) { + return CGxDevice::GLLAdapterMonitorModes(monitorModes); + } + +#elif defined(WHOA_SYSTEM_LINUX) + + // TODO + +#else + + return 0; + +#endif +} + +#if defined(WHOA_SYSTEM_MAC) +int32_t CGxDevice::GLLAdapterMonitorModes(TSGrowableArray& monitorModes) { + // TODO + return 0; +} +#endif + void CGxDevice::Log(const char* format, ...) { // TODO } @@ -100,6 +140,31 @@ void CGxDevice::Log(const CGxFormat& format) { // TODO } +#if defined(WHOA_SYSTEM_MAC) +int32_t CGxDevice::MacAdapterMonitorModes(TSGrowableArray& monitorModes) { + monitorModes.SetCount(0); + + // TODO this should use display global var, which is set somewhere in the Mac OpenGL init path + auto displayModes = CGDisplayAvailableModes(CGMainDisplayID()); + + if (displayModes) { + auto count = CFArrayGetCount(displayModes); + + for (int32_t i = 0; i < count; i++) { + auto displayMode = static_cast(CFArrayGetValueAtIndex(displayModes, i)); + + if (displayMode) { + ConvertDisplayMode(*monitorModes.New(), displayMode); + } + } + } + + qsort(monitorModes.Ptr(), monitorModes.Count(), sizeof(CGxMonitorMode), CGxMonitorModeSort); + + return monitorModes.Count() != 0; +} +#endif + #if defined(WHOA_SYSTEM_WIN) CGxDevice* CGxDevice::NewD3d() { auto m = SMemAlloc(sizeof(CGxDeviceD3d), __FILE__, __LINE__, 0x0); @@ -136,6 +201,40 @@ uint32_t CGxDevice::PrimCalcCount(EGxPrim primType, uint32_t count) { return count - CGxDevice::s_primVtxAdjust[primType]; } +#if defined(WHOA_SYSTEM_WIN) +int32_t CGxDevice::WinAdapterMonitorModes(TSGrowableArray& monitorModes) { + monitorModes.SetCount(0); + + DISPLAY_DEVICE device; + if (!FindDisplayDevice(&device, DISPLAY_DEVICE_PRIMARY_DEVICE)) { + return 0; + } + + DEVMODE deviceMode; + deviceMode.dmSize = sizeof(DEVMODE); + + DWORD deviceNum = 0; + while (EnumDisplaySettings(device.DeviceName, deviceNum++, &deviceMode)) { + if ( + deviceMode.dmPelsWidth >= 640 + && deviceMode.dmPelsHeight >= 480 + && deviceMode.dmBitsPerPel >= 16 + ) { + auto monitorMode = monitorModes.New(); + + monitorMode->size.x = deviceMode.dmPelsWidth; + monitorMode->size.y = deviceMode.dmPelsHeight; + monitorMode->bpp = deviceMode.dmBitsPerPel; + monitorMode->refreshRate = deviceMode.dmDisplayFrequency; + } + } + + qsort(monitorModes.Ptr(), monitorModes.Count(), sizeof(CGxMonitorMode), CGxMonitorModeSort); + + return monitorModes.Count() != 0; +} +#endif + CGxDevice::CGxDevice() { // TODO // - implement rest of constructor diff --git a/src/gx/CGxDevice.hpp b/src/gx/CGxDevice.hpp index 16a7216..aaa7842 100644 --- a/src/gx/CGxDevice.hpp +++ b/src/gx/CGxDevice.hpp @@ -14,6 +14,7 @@ #include class CGxBatch; +class CGxMonitorMode; class CGxTex; class CGxTexFlags; @@ -48,8 +49,15 @@ class CGxDevice { static uint32_t s_texFormatBytesPerBlock[]; // Static functions + static int32_t AdapterMonitorModes(TSGrowableArray& monitorModes); +#if defined(WHOA_SYSTEM_MAC) + static int32_t GLLAdapterMonitorModes(TSGrowableArray& monitorModes); +#endif static void Log(const char* format, ...); static void Log(const CGxFormat& format); +#if defined(WHOA_SYSTEM_MAC) + static int32_t MacAdapterMonitorModes(TSGrowableArray& monitorModes); +#endif #if defined(WHOA_SYSTEM_WIN) static CGxDevice* NewD3d(); static CGxDevice* NewD3d9Ex(); @@ -59,6 +67,9 @@ class CGxDevice { #endif static CGxDevice* NewOpenGl(); static uint32_t PrimCalcCount(EGxPrim primType, uint32_t count); +#if defined(WHOA_SYSTEM_WIN) + static int32_t WinAdapterMonitorModes(TSGrowableArray& monitorModes); +#endif // Member variables TSGrowableArray m_pushedStates; diff --git a/src/gx/CGxMonitorMode.cpp b/src/gx/CGxMonitorMode.cpp new file mode 100644 index 0000000..6850334 --- /dev/null +++ b/src/gx/CGxMonitorMode.cpp @@ -0,0 +1,8 @@ +#include "gx/CGxMonitorMode.hpp" + +int32_t CGxMonitorModeSort(const void* a, const void* b) { + auto modeA = static_cast(a); + auto modeB = static_cast(b); + + return (modeA->size.x * modeA->size.y) - (modeB->size.x * modeB->size.y); +} diff --git a/src/gx/CGxMonitorMode.hpp b/src/gx/CGxMonitorMode.hpp new file mode 100644 index 0000000..4f2f926 --- /dev/null +++ b/src/gx/CGxMonitorMode.hpp @@ -0,0 +1,16 @@ +#ifndef GX_C_GX_MONITOR_MODE_HPP +#define GX_C_GX_MONITOR_MODE_HPP + +#include +#include + +class CGxMonitorMode { + public: + C2iVector size; + uint32_t bpp; + uint32_t refreshRate; +}; + +int32_t CGxMonitorModeSort(void const* modeA, void const* modeB); + +#endif diff --git a/src/gx/CMakeLists.txt b/src/gx/CMakeLists.txt index 482d699..308fd9c 100644 --- a/src/gx/CMakeLists.txt +++ b/src/gx/CMakeLists.txt @@ -8,16 +8,26 @@ file(GLOB GX_SOURCES ) if(WHOA_SYSTEM_WIN) - file(GLOB D3D_SOURCES "d3d/*.cpp") - list(APPEND GX_SOURCES ${D3D_SOURCES}) + file(GLOB WIN_SOURCES + "d3d/*.cpp" + "win/*.cpp" + ) + + list(APPEND GX_SOURCES ${WIN_SOURCES}) endif() if(WHOA_SYSTEM_MAC) - file(GLOB GLL_SOURCES "gll/*.cpp" "gll/*.mm") - set_source_files_properties(${GLL_SOURCES} + file(GLOB MAC_SOURCES + "gll/*.cpp" + "gll/*.mm" + "mac/*.cpp" + ) + + set_source_files_properties(${MAC_SOURCES} PROPERTIES COMPILE_FLAGS "-x objective-c++" ) - list(APPEND GX_SOURCES ${GLL_SOURCES}) + + list(APPEND GX_SOURCES ${MAC_SOURCES}) endif() add_library(gx STATIC ${GX_SOURCES}) diff --git a/src/gx/mac/Display.cpp b/src/gx/mac/Display.cpp new file mode 100644 index 0000000..896500c --- /dev/null +++ b/src/gx/mac/Display.cpp @@ -0,0 +1,30 @@ +#include "gx/CGxMonitorMode.hpp" +#include + +void ConvertDisplayMode(CGxMonitorMode& monitorMode, CFDictionaryRef displayMode) { + monitorMode.size.x = 0; + monitorMode.size.y = 0; + monitorMode.bpp = 0; + monitorMode.refreshRate = 0; + + int32_t width = 0; + auto widthValue = static_cast(CFDictionaryGetValue(displayMode, kCGDisplayWidth)); + CFNumberGetValue(widthValue, kCFNumberIntType, &width); + + int32_t height = 0; + auto heightValue = static_cast(CFDictionaryGetValue(displayMode, kCGDisplayHeight)); + CFNumberGetValue(heightValue, kCFNumberIntType, &height); + + uint32_t refreshRate = 0; + auto refreshRateValue = static_cast(CFDictionaryGetValue(displayMode, kCGDisplayRefreshRate)); + CFNumberGetValue(refreshRateValue, kCFNumberIntType, &refreshRate); + + uint32_t bitsPerPixel = 0; + auto bppValue = static_cast(CFDictionaryGetValue(displayMode, kCGDisplayBitsPerPixel)); + CFNumberGetValue(bppValue, kCFNumberIntType, &bitsPerPixel); + + monitorMode.size.x = width; + monitorMode.size.y = height; + monitorMode.bpp = bitsPerPixel; + monitorMode.refreshRate = refreshRate ? refreshRate : 60; +} diff --git a/src/gx/mac/Display.hpp b/src/gx/mac/Display.hpp new file mode 100644 index 0000000..6ccd5a4 --- /dev/null +++ b/src/gx/mac/Display.hpp @@ -0,0 +1,6 @@ +#ifndef GX_MAC_DISPLAY_HPP +#define GX_MAC_DISPLAY_HPP + +void ConvertDisplayMode(CGxMonitorMode& monitorMode, CFDictionaryRef displayMode); + +#endif diff --git a/src/gx/win/Display.cpp b/src/gx/win/Display.cpp new file mode 100644 index 0000000..85331a7 --- /dev/null +++ b/src/gx/win/Display.cpp @@ -0,0 +1,14 @@ +#include "gx/win/Display.hpp" + +int32_t FindDisplayDevice(PDISPLAY_DEVICE device, uint32_t flag) { + device->cb = sizeof(DISPLAY_DEVICE); + + DWORD deviceNum = 0; + while (EnumDisplayDevices(nullptr, deviceNum++, device, 0)) { + if ((device->StateFlags & flag) == flag) { + return 1; + } + } + + return 0; +} diff --git a/src/gx/win/Display.hpp b/src/gx/win/Display.hpp new file mode 100644 index 0000000..286fdbb --- /dev/null +++ b/src/gx/win/Display.hpp @@ -0,0 +1,9 @@ +#ifndef GX_WIN_DISPLAY_HPP +#define GX_WIN_DISPLAY_HPP + +#include +#include + +int32_t FindDisplayDevice(PDISPLAY_DEVICE device, uint32_t flag); + +#endif