feat(gx): add GxAdapterMonitorModes

This commit is contained in:
fallenoak 2025-11-08 22:00:39 -06:00
parent 749273e217
commit a06d989d30
12 changed files with 231 additions and 7 deletions

View File

@ -3,8 +3,10 @@
#include "console/Console.hpp" #include "console/Console.hpp"
#include "console/CVar.hpp" #include "console/CVar.hpp"
#include "event/Input.hpp" #include "event/Input.hpp"
#include "gx/Adapter.hpp"
#include "gx/Device.hpp" #include "gx/Device.hpp"
#include <cstring> #include <cstring>
#include <storm/Array.hpp>
static CGxDevice* s_device; static CGxDevice* s_device;
static CVar* s_cvGxMaximize; static CVar* s_cvGxMaximize;
@ -12,6 +14,7 @@ static CVar* s_cvGxResolution;
static CVar* s_cvGxWidescreen; static CVar* s_cvGxWidescreen;
static CVar* s_cvGxWindow; static CVar* s_cvGxWindow;
static DefaultSettings s_defaults; static DefaultSettings s_defaults;
static TSGrowableArray<CGxMonitorMode> s_gxMonitorModes;
static bool s_hwDetect; static bool s_hwDetect;
static bool s_hwChanged; static bool s_hwChanged;
static CGxFormat s_requestedFormat; static CGxFormat s_requestedFormat;
@ -158,6 +161,8 @@ void ConsoleDeviceInitialize(const char* title) {
// TODO ConsoleCommandRegister("gxRestart", &CCGxRestart, 1, nullptr); // TODO ConsoleCommandRegister("gxRestart", &CCGxRestart, 1, nullptr);
GxAdapterMonitorModes(s_gxMonitorModes);
// TODO // TODO
// TODO // TODO

6
src/gx/Adapter.cpp Normal file
View File

@ -0,0 +1,6 @@
#include "gx/Adapter.hpp"
#include "gx/CGxDevice.hpp"
int32_t GxAdapterMonitorModes(TSGrowableArray<CGxMonitorMode>& monitorModes) {
return CGxDevice::AdapterMonitorModes(monitorModes);
}

10
src/gx/Adapter.hpp Normal file
View File

@ -0,0 +1,10 @@
#ifndef GX_ADAPTER_HPP
#define GX_ADAPTER_HPP
#include "gx/CGxMonitorMode.hpp"
#include <storm/Array.hpp>
#include <cstdint>
int32_t GxAdapterMonitorModes(TSGrowableArray<CGxMonitorMode>& monitorModes);
#endif

View File

@ -1,21 +1,25 @@
#include "gx/CGxDevice.hpp" #include "gx/CGxDevice.hpp"
#include "gx/CGxMonitorMode.hpp"
#include "gx/Gx.hpp" #include "gx/Gx.hpp"
#include "gx/Shader.hpp" #include "gx/Shader.hpp"
#include "gx/texture/CGxTex.hpp" #include "gx/texture/CGxTex.hpp"
#include "util/SFile.hpp" #include "util/SFile.hpp"
#include <storm/Error.hpp>
#include <storm/Memory.hpp>
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include <limits> #include <limits>
#include <new> #include <new>
#include <storm/Error.hpp>
#include <storm/Memory.hpp>
#if defined(WHOA_SYSTEM_WIN) #if defined(WHOA_SYSTEM_WIN)
#include "gx/d3d/CGxDeviceD3d.hpp" #include "gx/d3d/CGxDeviceD3d.hpp"
#include "gx/win/Display.hpp"
#endif #endif
#if defined(WHOA_SYSTEM_MAC) #if defined(WHOA_SYSTEM_MAC)
#include "gx/gll/CGxDeviceGLL.hpp" #include "gx/gll/CGxDeviceGLL.hpp"
#include "gx/mac/Display.hpp"
#include <ApplicationServices/ApplicationServices.h>
#endif #endif
uint32_t CGxDevice::s_alphaRef[] = { uint32_t CGxDevice::s_alphaRef[] = {
@ -92,6 +96,42 @@ uint32_t CGxDevice::s_texFormatBytesPerBlock[] = {
4 // GxTex_D24X8 4 // GxTex_D24X8
}; };
int32_t CGxDevice::AdapterMonitorModes(TSGrowableArray<CGxMonitorMode>& 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<CGxMonitorMode>& monitorModes) {
// TODO
return 0;
}
#endif
void CGxDevice::Log(const char* format, ...) { void CGxDevice::Log(const char* format, ...) {
// TODO // TODO
} }
@ -100,6 +140,31 @@ void CGxDevice::Log(const CGxFormat& format) {
// TODO // TODO
} }
#if defined(WHOA_SYSTEM_MAC)
int32_t CGxDevice::MacAdapterMonitorModes(TSGrowableArray<CGxMonitorMode>& 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<CFDictionaryRef>(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) #if defined(WHOA_SYSTEM_WIN)
CGxDevice* CGxDevice::NewD3d() { CGxDevice* CGxDevice::NewD3d() {
auto m = SMemAlloc(sizeof(CGxDeviceD3d), __FILE__, __LINE__, 0x0); 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]; return count - CGxDevice::s_primVtxAdjust[primType];
} }
#if defined(WHOA_SYSTEM_WIN)
int32_t CGxDevice::WinAdapterMonitorModes(TSGrowableArray<CGxMonitorMode>& 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() { CGxDevice::CGxDevice() {
// TODO // TODO
// - implement rest of constructor // - implement rest of constructor

View File

@ -14,6 +14,7 @@
#include <tempest/Rect.hpp> #include <tempest/Rect.hpp>
class CGxBatch; class CGxBatch;
class CGxMonitorMode;
class CGxTex; class CGxTex;
class CGxTexFlags; class CGxTexFlags;
@ -48,8 +49,15 @@ class CGxDevice {
static uint32_t s_texFormatBytesPerBlock[]; static uint32_t s_texFormatBytesPerBlock[];
// Static functions // Static functions
static int32_t AdapterMonitorModes(TSGrowableArray<CGxMonitorMode>& monitorModes);
#if defined(WHOA_SYSTEM_MAC)
static int32_t GLLAdapterMonitorModes(TSGrowableArray<CGxMonitorMode>& monitorModes);
#endif
static void Log(const char* format, ...); static void Log(const char* format, ...);
static void Log(const CGxFormat& format); static void Log(const CGxFormat& format);
#if defined(WHOA_SYSTEM_MAC)
static int32_t MacAdapterMonitorModes(TSGrowableArray<CGxMonitorMode>& monitorModes);
#endif
#if defined(WHOA_SYSTEM_WIN) #if defined(WHOA_SYSTEM_WIN)
static CGxDevice* NewD3d(); static CGxDevice* NewD3d();
static CGxDevice* NewD3d9Ex(); static CGxDevice* NewD3d9Ex();
@ -59,6 +67,9 @@ class CGxDevice {
#endif #endif
static CGxDevice* NewOpenGl(); static CGxDevice* NewOpenGl();
static uint32_t PrimCalcCount(EGxPrim primType, uint32_t count); static uint32_t PrimCalcCount(EGxPrim primType, uint32_t count);
#if defined(WHOA_SYSTEM_WIN)
static int32_t WinAdapterMonitorModes(TSGrowableArray<CGxMonitorMode>& monitorModes);
#endif
// Member variables // Member variables
TSGrowableArray<CGxPushedRenderState> m_pushedStates; TSGrowableArray<CGxPushedRenderState> m_pushedStates;

View File

@ -0,0 +1,8 @@
#include "gx/CGxMonitorMode.hpp"
int32_t CGxMonitorModeSort(const void* a, const void* b) {
auto modeA = static_cast<const CGxMonitorMode*>(a);
auto modeB = static_cast<const CGxMonitorMode*>(b);
return (modeA->size.x * modeA->size.y) - (modeB->size.x * modeB->size.y);
}

16
src/gx/CGxMonitorMode.hpp Normal file
View File

@ -0,0 +1,16 @@
#ifndef GX_C_GX_MONITOR_MODE_HPP
#define GX_C_GX_MONITOR_MODE_HPP
#include <tempest/Vector.hpp>
#include <cstdint>
class CGxMonitorMode {
public:
C2iVector size;
uint32_t bpp;
uint32_t refreshRate;
};
int32_t CGxMonitorModeSort(void const* modeA, void const* modeB);
#endif

View File

@ -8,16 +8,26 @@ file(GLOB GX_SOURCES
) )
if(WHOA_SYSTEM_WIN) if(WHOA_SYSTEM_WIN)
file(GLOB D3D_SOURCES "d3d/*.cpp") file(GLOB WIN_SOURCES
list(APPEND GX_SOURCES ${D3D_SOURCES}) "d3d/*.cpp"
"win/*.cpp"
)
list(APPEND GX_SOURCES ${WIN_SOURCES})
endif() endif()
if(WHOA_SYSTEM_MAC) if(WHOA_SYSTEM_MAC)
file(GLOB GLL_SOURCES "gll/*.cpp" "gll/*.mm") file(GLOB MAC_SOURCES
set_source_files_properties(${GLL_SOURCES} "gll/*.cpp"
"gll/*.mm"
"mac/*.cpp"
)
set_source_files_properties(${MAC_SOURCES}
PROPERTIES COMPILE_FLAGS "-x objective-c++" PROPERTIES COMPILE_FLAGS "-x objective-c++"
) )
list(APPEND GX_SOURCES ${GLL_SOURCES})
list(APPEND GX_SOURCES ${MAC_SOURCES})
endif() endif()
add_library(gx STATIC ${GX_SOURCES}) add_library(gx STATIC ${GX_SOURCES})

30
src/gx/mac/Display.cpp Normal file
View File

@ -0,0 +1,30 @@
#include "gx/CGxMonitorMode.hpp"
#include <ApplicationServices/ApplicationServices.h>
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<CFNumberRef>(CFDictionaryGetValue(displayMode, kCGDisplayWidth));
CFNumberGetValue(widthValue, kCFNumberIntType, &width);
int32_t height = 0;
auto heightValue = static_cast<CFNumberRef>(CFDictionaryGetValue(displayMode, kCGDisplayHeight));
CFNumberGetValue(heightValue, kCFNumberIntType, &height);
uint32_t refreshRate = 0;
auto refreshRateValue = static_cast<CFNumberRef>(CFDictionaryGetValue(displayMode, kCGDisplayRefreshRate));
CFNumberGetValue(refreshRateValue, kCFNumberIntType, &refreshRate);
uint32_t bitsPerPixel = 0;
auto bppValue = static_cast<CFNumberRef>(CFDictionaryGetValue(displayMode, kCGDisplayBitsPerPixel));
CFNumberGetValue(bppValue, kCFNumberIntType, &bitsPerPixel);
monitorMode.size.x = width;
monitorMode.size.y = height;
monitorMode.bpp = bitsPerPixel;
monitorMode.refreshRate = refreshRate ? refreshRate : 60;
}

6
src/gx/mac/Display.hpp Normal file
View File

@ -0,0 +1,6 @@
#ifndef GX_MAC_DISPLAY_HPP
#define GX_MAC_DISPLAY_HPP
void ConvertDisplayMode(CGxMonitorMode& monitorMode, CFDictionaryRef displayMode);
#endif

14
src/gx/win/Display.cpp Normal file
View File

@ -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;
}

9
src/gx/win/Display.hpp Normal file
View File

@ -0,0 +1,9 @@
#ifndef GX_WIN_DISPLAY_HPP
#define GX_WIN_DISPLAY_HPP
#include <windows.h>
#include <cstdint>
int32_t FindDisplayDevice(PDISPLAY_DEVICE device, uint32_t flag);
#endif