mirror of
https://github.com/thunderbrewhq/thunderbrew
synced 2025-12-12 19:22:30 +00:00
feat(console): hardware detection et cetera
This commit is contained in:
parent
97bbe2ea66
commit
31f215ea14
118 changed files with 4059 additions and 1931 deletions
|
|
@ -22,7 +22,7 @@ class CGxCaps {
|
|||
int32_t m_texFilterAnisotropic = 0;
|
||||
uint32_t m_maxTexAnisotropy = 0;
|
||||
int32_t m_depthBias = 0;
|
||||
int32_t m_hardwareCursor = 0;
|
||||
int32_t m_hwCursor = 0;
|
||||
int32_t int130 = 1;
|
||||
int32_t int134 = 0;
|
||||
int32_t int138 = 0;
|
||||
|
|
|
|||
|
|
@ -8,27 +8,36 @@
|
|||
#include "gx/Transform.hpp"
|
||||
#include "gx/Draw.hpp"
|
||||
#include "util/SFile.hpp"
|
||||
#include "event/Input.hpp"
|
||||
#include "os/Input.hpp"
|
||||
#include <storm/Error.hpp>
|
||||
#include <bc/Memory.hpp>
|
||||
#include <bc/os/File.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <storm/Error.hpp>
|
||||
#include <bc/Memory.hpp>
|
||||
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
#include "gx/d3d/CGxDeviceD3d.hpp"
|
||||
|
||||
#include "gx/d3d/CGxDeviceD3d.hpp"
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_BUILD_GLSDL)
|
||||
#include "gx/glsdl/CGxDeviceGLSDL.hpp"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include "gx/glsdl/CGxDeviceGLSDL.hpp"
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC)
|
||||
#include "gx/gll/CGxDeviceGLL.hpp"
|
||||
#endif
|
||||
|
||||
HSLOG CGxDevice::m_log;
|
||||
uint32_t CGxDevice::m_logBytes;
|
||||
|
||||
uint32_t CGxDevice::s_alphaRef[] = {
|
||||
0, // GxBlend_Opaque
|
||||
224, // GxBlend_AlphaKey
|
||||
|
|
@ -106,23 +115,331 @@ uint32_t CGxDevice::s_texFormatBytesPerBlock[] = {
|
|||
CGxShader* CGxDevice::s_uiVertexShader = nullptr;
|
||||
CGxShader* CGxDevice::s_uiPixelShader = nullptr;
|
||||
|
||||
void CGxDevice::LogOpen() {
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
|
||||
uint16_t HToI(const char* h, uint32_t count) {
|
||||
uint32_t i = 0;
|
||||
while (count) {
|
||||
auto cur = *h;
|
||||
--count;
|
||||
i *= 16;
|
||||
++h;
|
||||
if (isxdigit(cur)) {
|
||||
if (isdigit(cur)) {
|
||||
i += cur - '0';
|
||||
} else {
|
||||
i += toupper(cur) - '7';
|
||||
}
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int32_t CGxDevice::AdapterID(uint16_t& vendorID, uint16_t& deviceID, uint32_t& driverVersionHi, uint32_t& driverVersionLow) {
|
||||
int32_t result = 0;
|
||||
vendorID = 0xFFFF;
|
||||
deviceID = 0xFFFF;
|
||||
|
||||
driverVersionHi = 0;
|
||||
driverVersionLow = 0;
|
||||
|
||||
DISPLAY_DEVICE dd;
|
||||
memset(&dd, 0, sizeof(dd));
|
||||
dd.cb = sizeof(DISPLAY_DEVICE);
|
||||
|
||||
DWORD device = 0;
|
||||
|
||||
while (EnumDisplayDevices(0, device, &dd, 0)) {
|
||||
if (dd.StateFlags & 4) {
|
||||
break;
|
||||
}
|
||||
|
||||
device++;
|
||||
}
|
||||
|
||||
uint16_t vI;
|
||||
uint16_t dI;
|
||||
if (strlen(dd.DeviceID) > 20 && (vI = HToI(&dd.DeviceID[8], 4)) && (dI = HToI(&dd.DeviceID[17], 4))) {
|
||||
vendorID = vI;
|
||||
deviceID = dI;
|
||||
result = true;
|
||||
} else {
|
||||
HINSTANCE d3dLib = nullptr;
|
||||
LPDIRECT3D9 d3d = nullptr;
|
||||
|
||||
if (CGxDeviceD3d::ILoadD3dLib(d3dLib, d3d)) {
|
||||
D3DADAPTER_IDENTIFIER9 d3dadapterid;
|
||||
if (d3d->GetAdapterIdentifier(0, 0, &d3dadapterid) >= D3D_OK) {
|
||||
vendorID = d3dadapterid.VendorId;
|
||||
deviceID = d3dadapterid.DeviceId;
|
||||
driverVersionLow = d3dadapterid.DriverVersion.LowPart;
|
||||
driverVersionHi = d3dadapterid.DriverVersion.HighPart;
|
||||
result = true;
|
||||
}
|
||||
CGxDeviceD3d::IUnloadD3dLib(d3dLib, d3d);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: this doesn't appear to be a typo on our part
|
||||
Log("CGxDevice::DeviceAdapterID(): RET: %d, VID: %x, DID: %x, DVER: %x.%x", result, vendorID, deviceID, driverVersionHi, driverVersionLow);
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t CGxDevice::AdapterInfer(uint16_t& deviceID) {
|
||||
HINSTANCE d3dLib;
|
||||
LPDIRECT3D9 d3d;
|
||||
D3DCAPS9 d3dcaps;
|
||||
|
||||
int32_t result = 0;
|
||||
|
||||
if (!CGxDeviceD3d::ILoadD3dLib(d3dLib, d3d)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (d3d->GetDeviceCaps(0, D3DDEVTYPE_HAL, &d3dcaps) == D3D_OK) {
|
||||
if ((d3dcaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0 && d3dcaps.MaxSimultaneousTextures > 2 && d3dcaps.PixelShaderVersion >= 0x200) {
|
||||
deviceID = 3;
|
||||
result = 1;
|
||||
} else if ((d3dcaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0) {
|
||||
if (d3dcaps.MaxSimultaneousTextures > 2 && d3dcaps.PixelShaderVersion >= 0x101) {
|
||||
deviceID = 2;
|
||||
result = 1;
|
||||
} else if (d3dcaps.MaxSimultaneousTextures >= 2) {
|
||||
deviceID = 1;
|
||||
result = 1;
|
||||
}
|
||||
} else {
|
||||
deviceID = 0;
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
CGxDeviceD3d::IUnloadD3dLib(d3dLib, d3d);
|
||||
Log("CGxDevice::DeviceAdapterInfer(): RET: %d, DID: %x", result, deviceID);
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO: replace this invented name
|
||||
int32_t FindDisplayDevice(PDISPLAY_DEVICE device, uint32_t flag) {
|
||||
DWORD i = 0;
|
||||
device->cb = sizeof(DISPLAY_DEVICE);
|
||||
while (EnumDisplayDevices(nullptr, i, device, 0)) {
|
||||
if ((device->StateFlags & flag) == flag) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t CGxDevice::AdapterMonitorModes(TSGrowableArray<CGxMonitorMode>& modes) {
|
||||
modes.SetCount(0);
|
||||
|
||||
DISPLAY_DEVICE device;
|
||||
if (!FindDisplayDevice(&device, DISPLAY_DEVICE_PRIMARY_DEVICE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEVMODE dm;
|
||||
dm.dmSize = sizeof(DEVMODE);
|
||||
|
||||
DWORD i = 0;
|
||||
while (EnumDisplaySettings(device.DeviceName, i, &dm)) {
|
||||
if ((dm.dmPelsWidth >= 640 && dm.dmPelsHeight >= 480)
|
||||
&& dm.dmBitsPerPel >= 16) {
|
||||
auto mode = modes.New();
|
||||
|
||||
mode->size.x = dm.dmPelsWidth;
|
||||
mode->size.y = dm.dmPelsHeight;
|
||||
mode->bpp = dm.dmBitsPerPel;
|
||||
mode->refreshRate = dm.dmDisplayFrequency;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
qsort(modes.Ptr(), modes.Count(), sizeof(CGxMonitorMode), CGxMonitorModeSort);
|
||||
|
||||
return modes.Count() != 0;
|
||||
}
|
||||
|
||||
int32_t CGxDevice::AdapterDesktopMode(CGxMonitorMode& mode) {
|
||||
DISPLAY_DEVICE device;
|
||||
if (!FindDisplayDevice(&device, DISPLAY_DEVICE_ACTIVE|DISPLAY_DEVICE_PRIMARY_DEVICE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEVMODE dm;
|
||||
dm.dmSize = sizeof(DEVMODE);
|
||||
if (!EnumDisplaySettings(device.DeviceName, ENUM_CURRENT_SETTINGS, &dm)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
mode.size.x = dm.dmPelsWidth;
|
||||
mode.size.y = dm.dmPelsHeight;
|
||||
mode.refreshRate = dm.dmDisplayFrequency;
|
||||
mode.bpp = dm.dmBitsPerPel;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#elif (WHOA_SYSTEM_MAC)
|
||||
|
||||
int32_t CGxDevice::AdapterID(uint16_t& vendorID, uint16_t& deviceID, uint32_t& driverVersionHi, uint32_t& driverVersionLow) {
|
||||
// TODO: proper implementation
|
||||
vendorID = 0xFFFF;
|
||||
deviceID = 3;
|
||||
driverVersionHi = 0;
|
||||
driverVersionLow = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t CGxDevice::AdapterInfer(uint16_t& deviceID) {
|
||||
// TODO
|
||||
deviceID = 3;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t CGxDevice::AdapterMonitorModes(TSGrowableArray<CGxMonitorMode>& modes) {
|
||||
// TODO: Mac support
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t CGxDevice::AdapterDesktopMode(CGxMonitorMode& mode) {
|
||||
// TODO: Mac support
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif (WHOA_BUILD_GLSDL)
|
||||
|
||||
int32_t CGxDevice::AdapterID(uint16_t& vendorID, uint16_t& deviceID, uint32_t& driverVersionHi, uint32_t& driverVersionLow) {
|
||||
// TODO
|
||||
vendorID = 0xFFFF;
|
||||
deviceID = 3;
|
||||
driverVersionHi = 0;
|
||||
driverVersionLow = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t CGxDevice::AdapterInfer(uint16_t& deviceID) {
|
||||
// TODO
|
||||
deviceID = 3;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t CGxDevice::AdapterMonitorModes(TSGrowableArray<CGxMonitorMode>& modes) {
|
||||
auto primaryDisplay = SDL_GetPrimaryDisplay();
|
||||
if (!primaryDisplay) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t displayModeCount;
|
||||
auto displayModes = SDL_GetFullscreenDisplayModes(primaryDisplay, &displayModeCount);
|
||||
if (displayModes == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
modes.SetCount(displayModeCount);
|
||||
for (auto i = 0; i < displayModeCount; i++) {
|
||||
auto displayMode = displayModes[i];
|
||||
CGxMonitorMode& mode = modes[i];
|
||||
mode.size.x = displayMode->w;
|
||||
mode.size.y = displayMode->h;
|
||||
mode.bpp = SDL_BITSPERPIXEL(displayMode->format);
|
||||
mode.refreshRate = static_cast<uint32_t>(displayMode->refresh_rate_numerator / displayMode->refresh_rate_denominator);
|
||||
}
|
||||
|
||||
SDL_free(displayModes);
|
||||
|
||||
qsort(modes.Ptr(), modes.Count(), sizeof(CGxMonitorMode), CGxMonitorModeSort);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t CGxDevice::AdapterDesktopMode(CGxMonitorMode& mode) {
|
||||
auto primaryDisplay = SDL_GetPrimaryDisplay();
|
||||
if (!primaryDisplay) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto displayMode = SDL_GetDesktopDisplayMode(primaryDisplay);
|
||||
if (!displayMode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
mode.size.x = displayMode->w;
|
||||
mode.size.y = displayMode->h;
|
||||
mode.bpp = SDL_BITSPERPIXEL(displayMode->format);
|
||||
mode.refreshRate = static_cast<uint32_t>(displayMode->refresh_rate_numerator / displayMode->refresh_rate_denominator);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void CGxDevice::LogOpen() {
|
||||
if (!m_log) {
|
||||
OsCreateDirectory("Logs", 0);
|
||||
SLogCreate("Logs\\gx.log", 0, &m_log);
|
||||
m_logBytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CGxDevice::LogClose() {
|
||||
// TODO
|
||||
if (m_log) {
|
||||
SLogClose(m_log);
|
||||
m_log = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void CGxDevice::VLog(const char* format, va_list args) {
|
||||
char buffer[2048];
|
||||
if (m_log) {
|
||||
vsnprintf(buffer, sizeof(buffer), format, args);
|
||||
if (m_logBytes < 0x200000) {
|
||||
SLogWrite(m_log, "%s", buffer);
|
||||
m_logBytes += strlen(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CGxDevice::Log(const char* format, ...) {
|
||||
// TODO
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
if (m_log) {
|
||||
VLog(format, args);
|
||||
}
|
||||
}
|
||||
|
||||
void CGxDevice::Log(const CGxFormat& format) {
|
||||
// TODO
|
||||
static const char* s_formatToString[] = {
|
||||
"Rgb565",
|
||||
"ArgbX888",
|
||||
"Argb2101010",
|
||||
"Ds160",
|
||||
"Ds24X",
|
||||
"Ds248",
|
||||
"Ds320"
|
||||
};
|
||||
|
||||
if (format.window) {
|
||||
Log("\tFormat: %d x %d Window, %s, multisample %d",
|
||||
format.size.x,
|
||||
format.size.y,
|
||||
s_formatToString[format.depthFormat],
|
||||
format.sampleCount);
|
||||
} else {
|
||||
Log("\tFormat %d x %d @ %d Fullscreen, %s, %s, multisample %d",
|
||||
format.size.x,
|
||||
format.size.y,
|
||||
format.refreshRate,
|
||||
s_formatToString[format.colorFormat],
|
||||
s_formatToString[format.depthFormat],
|
||||
format.sampleCount);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
|
||||
CGxDevice* CGxDevice::NewD3d() {
|
||||
return NEW(CGxDeviceD3d);
|
||||
}
|
||||
|
|
@ -131,12 +448,15 @@ CGxDevice* CGxDevice::NewD3d9Ex() {
|
|||
// TODO
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC)
|
||||
|
||||
CGxDevice* CGxDevice::NewGLL() {
|
||||
return NEW(CGxDeviceGLL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
CGxDevice* CGxDevice::NewOpenGl() {
|
||||
|
|
@ -144,9 +464,11 @@ CGxDevice* CGxDevice::NewOpenGl() {
|
|||
}
|
||||
|
||||
#if defined(WHOA_BUILD_GLSDL)
|
||||
|
||||
CGxDevice* CGxDevice::NewGLSDL() {
|
||||
return NEW(CGxDeviceGLSDL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
uint32_t CGxDevice::PrimCalcCount(EGxPrim primType, uint32_t count) {
|
||||
|
|
@ -168,93 +490,6 @@ void CGxDevice::ICursorUpdate(EGxTexCommand command, uint32_t width, uint32_t he
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
|
||||
// TODO: replace this invented name
|
||||
int32_t FindDisplayDevice(PDISPLAY_DEVICE device, uint32_t flag) {
|
||||
DWORD i = 0;
|
||||
device->cb = sizeof(DISPLAY_DEVICE);
|
||||
while (EnumDisplayDevices(nullptr, i, device, 0)) {
|
||||
if ((device->StateFlags & flag) == flag) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CGxDevice::AdapterMonitorModes(TSGrowableArray<CGxMonitorMode>& modes) {
|
||||
modes.SetCount(0);
|
||||
|
||||
DISPLAY_DEVICE device;
|
||||
if (!FindDisplayDevice(&device, DISPLAY_DEVICE_PRIMARY_DEVICE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DEVMODE dm;
|
||||
dm.dmSize = sizeof(DEVMODE);
|
||||
|
||||
DWORD i = 0;
|
||||
while (EnumDisplaySettings(&device, i, &dm)) {
|
||||
if ((dm.dmPelsWidth >= 640 && dm.dmPelsHeight >= 480)
|
||||
&& dm.dmBitsPerPel >= 16) {
|
||||
auto mode = modes.New();
|
||||
|
||||
mode->size.x = dm.dmPelsWidth;
|
||||
mode->size.y = dm.dmPelsHeight;
|
||||
mode->bpp = dm.dmBitsPerPel;
|
||||
mode->refreshRate = dm.dmDisplayFrequency;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
qsort(modes.Ptr(), modes.Count(), sizeof(CGxMonitorMode), CGxMonitorModeSort);
|
||||
|
||||
return modes.Count() != 0;
|
||||
}
|
||||
|
||||
#elif (WHOA_SYSTEM_MAC)
|
||||
|
||||
bool CGxDevice::AdapterMonitorModes(TSGrowableArray<CGxMonitorMode>& modes) {
|
||||
// TODO: Mac support
|
||||
return false;
|
||||
}
|
||||
|
||||
#elif (WHOA_BUILD_GLSDL)
|
||||
|
||||
bool CGxDevice::AdapterMonitorModes(TSGrowableArray<CGxMonitorMode>& modes) {
|
||||
auto primaryDisplay = SDL_GetPrimaryDisplay();
|
||||
if (!primaryDisplay) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t displayModeCount;
|
||||
auto displayModes = SDL_GetFullscreenDisplayModes(primaryDisplay, &displayModeCount);
|
||||
if (displayModes == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
modes.SetCount(displayModeCount);
|
||||
for (auto i = 0; i < displayModeCount; i++) {
|
||||
auto displayMode = displayModes[i];
|
||||
CGxMonitorMode& mode = modes[i];
|
||||
mode.size.x = displayMode->w;
|
||||
mode.size.y = displayMode->h;
|
||||
mode.bpp = displayMode->format.BitsPerPixel;
|
||||
mode.refreshRate = static_cast<uint32_t>(displayMode->format.refresh_rate);
|
||||
}
|
||||
|
||||
SDL_free(displayModes);
|
||||
|
||||
qsort(modes.Ptr(), modes.Count(), sizeof(CGxMonitorMode), CGxMonitorModeSort);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
CGxDevice::CGxDevice() {
|
||||
// TODO
|
||||
// - implement rest of constructor
|
||||
|
|
@ -321,6 +556,10 @@ const CGxCaps& CGxDevice::Caps() const {
|
|||
return this->m_caps;
|
||||
}
|
||||
|
||||
EGxApi CGxDevice::DeviceApi() {
|
||||
return this->m_api;
|
||||
}
|
||||
|
||||
int32_t CGxDevice::DeviceCreate(int32_t (*windowProc)(void* window, uint32_t message, uintptr_t wparam, intptr_t lparam), const CGxFormat& format) {
|
||||
this->m_windowProc = windowProc;
|
||||
|
||||
|
|
@ -1366,7 +1605,7 @@ void CGxDevice::XformSetViewport(float minX, float maxX, float minY, float maxY,
|
|||
return;
|
||||
}
|
||||
|
||||
this->intF6C = 1;
|
||||
this->m_needsReset = 1;
|
||||
|
||||
this->m_viewport.x.l = minX;
|
||||
this->m_viewport.x.h = maxX;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@
|
|||
#include "gx/Shader.hpp"
|
||||
#include "cursor/Cursor.hpp"
|
||||
#include <cstdint>
|
||||
#include <cstdarg>
|
||||
#include <storm/Hash.hpp>
|
||||
#include <storm/Log.hpp>
|
||||
#include <tempest/Box.hpp>
|
||||
#include <tempest/Rect.hpp>
|
||||
|
||||
|
|
@ -39,6 +41,14 @@ struct ShaderConstants {
|
|||
|
||||
class CGxDevice {
|
||||
public:
|
||||
// Types
|
||||
typedef void (*DEVICE_RESTORED_CALLBACK)();
|
||||
typedef void (*TEXTURE_RECREATION_CALLBACK)();
|
||||
typedef void (*STEREO_CHANGED_CALLBACK)();
|
||||
|
||||
static HSLOG m_log;
|
||||
static uint32_t m_logBytes;
|
||||
|
||||
// Static variables
|
||||
static uint32_t s_alphaRef[];
|
||||
static C3Vector s_pointScaleIdentity;
|
||||
|
|
@ -52,13 +62,19 @@ class CGxDevice {
|
|||
static CGxShader* s_uiPixelShader;
|
||||
|
||||
// Static functions
|
||||
static bool AdapterMonitorModes(TSGrowableArray<CGxMonitorMode>& modes);
|
||||
static int32_t AdapterID(uint16_t& vendorID, uint16_t& deviceID, uint32_t& driverVersionHi, uint32_t& driverVersionLow);
|
||||
static int32_t AdapterInfer(uint16_t& deviceID);
|
||||
static int32_t AdapterDesktopMode(CGxMonitorMode& mode);
|
||||
static int32_t AdapterMonitorModes(TSGrowableArray<CGxMonitorMode>& modes);
|
||||
static void ICursorUpdate(EGxTexCommand, uint32_t, uint32_t, uint32_t, uint32_t, void*, uint32_t&, const void*&);
|
||||
static void LogOpen();
|
||||
static void VLog(const char* format, va_list args);
|
||||
static void Log(const char* format, ...);
|
||||
static void Log(const CGxFormat& format);
|
||||
static void LogClose();
|
||||
static uint32_t PrimCalcCount(EGxPrim primType, uint32_t count);
|
||||
|
||||
// graphics api factory
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
static CGxDevice* NewD3d();
|
||||
static CGxDevice* NewD3d9Ex();
|
||||
|
|
@ -111,7 +127,7 @@ class CGxDevice {
|
|||
TSFixedArray<CGxStateBom> m_hwRenderStates;
|
||||
uint32_t m_baseMipLevel = 0; // TODO placeholder
|
||||
int32_t m_cursorVisible = 0;
|
||||
int32_t m_hardwareCursor = 0;
|
||||
int32_t m_hwCursor = 0;
|
||||
uint32_t m_cursorHotspotX = 0;
|
||||
uint32_t m_cursorHotspotY = 0;
|
||||
uint32_t m_cursor[CURSOR_IMAGE_SIZE] = { 0 };
|
||||
|
|
@ -156,6 +172,7 @@ class CGxDevice {
|
|||
const CGxCaps& Caps() const;
|
||||
CGxBuf* BufCreate(CGxPool* pool, uint32_t itemSize, uint32_t itemCount, uint32_t index);
|
||||
CGxBuf* BufStream(EGxPoolTarget target, uint32_t itemSize, uint32_t itemCount);
|
||||
EGxApi DeviceApi();
|
||||
void DeviceCreatePools();
|
||||
void DeviceCreateStreamBufs();
|
||||
const CRect& DeviceCurWindow();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#include "gx/CGxFormat.hpp"
|
||||
|
||||
const char* CGxFormat::formatToColorBitsString[Formats_Last] = { "16", "24", "24", "30", "16", "24", "24", "32" };
|
||||
|
||||
CGxFormat::CGxFormat() {
|
||||
this->size.x = 0;
|
||||
this->size.y = 0;
|
||||
|
|
@ -12,12 +10,12 @@ CGxFormat::CGxFormat() {
|
|||
this->stereoEnabled = false;
|
||||
this->sampleCount = 1;
|
||||
this->aspect = 1;
|
||||
this->unk1 = -1;
|
||||
this->unk2 = -1;
|
||||
this->unk3 = -1;
|
||||
this->unk4 = -1;
|
||||
this->unk5 = -1;
|
||||
this->unk6 = -1;
|
||||
this->unk38 = 0xFFFFFFFF;
|
||||
this->unk3C = 0xFFFFFFFF;
|
||||
this->unk40 = 0xFFFFFFFF;
|
||||
this->unk44 = 0xFFFFFFFF;
|
||||
this->unk48 = 0xFFFFFFFF;
|
||||
this->unk4C = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
CGxFormat::CGxFormat(bool p_window, const C2iVector& p_size, Format p_colorFormat, Format p_depthFormat, uint32_t p_refreshRate, uint32_t p_vsync, bool p_hwTnl, bool p_fixLag, bool p_hwCursor, bool p_aspect, bool p_maximize) {
|
||||
|
|
@ -41,10 +39,10 @@ CGxFormat::CGxFormat(bool p_window, const C2iVector& p_size, Format p_colorForma
|
|||
this->maximize = p_maximize;
|
||||
this->backbuffers = 1;
|
||||
this->sampleCount = 1;
|
||||
this->unk1 = -1;
|
||||
this->unk2 = -1;
|
||||
this->unk3 = -1;
|
||||
this->unk4 = -1;
|
||||
this->unk5 = -1;
|
||||
this->unk6 = -1;
|
||||
this->unk38 = 0xFFFFFFFF;
|
||||
this->unk3C = 0xFFFFFFFF;
|
||||
this->unk40 = 0xFFFFFFFF;
|
||||
this->unk44 = 0xFFFFFFFF;
|
||||
this->unk48 = 0xFFFFFFFF;
|
||||
this->unk4C = 0xFFFFFFFF;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ class CGxFormat {
|
|||
CGxFormat();
|
||||
CGxFormat(bool p_window, const C2iVector& p_size, Format p_colorFormat, Format p_depthFormat, uint32_t p_refreshRate, uint32_t p_vsync, bool p_hwTnl, bool p_fixLag, bool p_hwCursor, bool p_aspect, bool p_maximize);
|
||||
|
||||
static const char* formatToColorBitsString[Formats_Last];
|
||||
|
||||
// Member variables
|
||||
uint32_t apiSpecificModeID;
|
||||
bool hwTnL;
|
||||
|
|
@ -41,12 +39,12 @@ class CGxFormat {
|
|||
uint32_t refreshRate;
|
||||
uint32_t vsync;
|
||||
bool stereoEnabled;
|
||||
uint32_t unk1;
|
||||
uint32_t unk2;
|
||||
uint32_t unk3;
|
||||
uint32_t unk4;
|
||||
uint32_t unk5;
|
||||
uint32_t unk6;
|
||||
uint32_t unk38;
|
||||
uint32_t unk3C;
|
||||
uint32_t unk40;
|
||||
uint32_t unk44;
|
||||
uint32_t unk48;
|
||||
uint32_t unk4C;
|
||||
C2iVector pos;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,6 @@ class CGxMonitorMode {
|
|||
uint32_t refreshRate;
|
||||
};
|
||||
|
||||
int32_t CGxMonitorModeSort(const void* i, const void* j);
|
||||
int32_t CGxMonitorModeSort(const void* a, const void* b);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -61,11 +61,11 @@ if (WHOA_SYSTEM_WIN)
|
|||
endif ()
|
||||
endif ()
|
||||
|
||||
# Link SDL2 and GLEW for GLSDL
|
||||
# Link SDL3 and GLEW for GLSDL
|
||||
if (WHOA_BUILD_GLSDL)
|
||||
target_link_libraries(gx
|
||||
PRIVATE
|
||||
SDL2::SDL2-static
|
||||
SDL3::SDL3-static
|
||||
libglew_static
|
||||
)
|
||||
endif ()
|
||||
|
|
|
|||
|
|
@ -59,8 +59,7 @@ CGxDevice* GxDevCreate(EGxApi api, int32_t (*windowProc)(void* window, uint32_t
|
|||
}
|
||||
|
||||
if (!device) {
|
||||
SErrPrepareAppFatal(__FILE__, __LINE__);
|
||||
SErrDisplayAppFatal("GxDevCreate: failed to create graphics device %d", api);
|
||||
SErrPrepareAppFatal(__FILE__, __LINE__); SErrDisplayAppFatal("GxDevCreate: failed to create graphics device %d", api);
|
||||
}
|
||||
|
||||
// STORM_ASSERT(device != nullptr);
|
||||
|
|
@ -78,15 +77,19 @@ CGxDevice* GxDevCreate(EGxApi api, int32_t (*windowProc)(void* window, uint32_t
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
int32_t GxDevExists() {
|
||||
return g_theGxDevicePtr != nullptr;
|
||||
void GxDevDestroy(CGxDevice* device) {
|
||||
// TODO
|
||||
// device->DeviceDestroy();
|
||||
}
|
||||
|
||||
EGxApi GxDevApi() {
|
||||
return g_theGxDevicePtr->m_api;
|
||||
}
|
||||
|
||||
bool GxDevExists() {
|
||||
return g_theGxDevicePtr != nullptr;
|
||||
}
|
||||
|
||||
void* GxDevWindow() {
|
||||
return g_theGxDevicePtr->DeviceWindow();
|
||||
}
|
||||
|
|
@ -95,7 +98,12 @@ int32_t GxMasterEnable(EGxMasterEnables state) {
|
|||
return g_theGxDevicePtr->MasterEnable(state);
|
||||
}
|
||||
|
||||
EGxApi GxApiDefault() {
|
||||
void GxDevOverride(EGxOverride override, uint32_t value) {
|
||||
// TODO
|
||||
// g_theGxDevicePtr->DeviceOverride(override, value);
|
||||
}
|
||||
|
||||
EGxApi GxDefaultApi() {
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
return GxApi_D3d9;
|
||||
#endif
|
||||
|
|
@ -110,13 +118,69 @@ EGxApi GxApiDefault() {
|
|||
}
|
||||
|
||||
bool GxApiSupported(EGxApi api) {
|
||||
return (g_supportedApis & static_cast<uint32_t>(api)) != 0;
|
||||
return (g_supportedApis & (1 << static_cast<uint32_t>(api))) != 0;
|
||||
}
|
||||
|
||||
bool GxAdapterMonitorModes(TSGrowableArray<CGxMonitorMode>& modes) {
|
||||
int32_t GxAdapterID(uint16_t& vendorID, uint16_t& deviceID, uint32_t& driverVersionHi, uint32_t& driverVersionLo) {
|
||||
return g_theGxDevicePtr->AdapterID(vendorID, deviceID, driverVersionHi, driverVersionLo);
|
||||
}
|
||||
|
||||
int32_t GxAdapterInfer(uint16_t& deviceID) {
|
||||
return g_theGxDevicePtr->AdapterInfer(deviceID);
|
||||
}
|
||||
|
||||
int32_t GxAdapterMonitorModes(TSGrowableArray<CGxMonitorMode>& modes) {
|
||||
return CGxDevice::AdapterMonitorModes(modes);
|
||||
}
|
||||
|
||||
int32_t GxAdapterDesktopMode(CGxMonitorMode& mode) {
|
||||
return CGxDevice::AdapterDesktopMode(mode);
|
||||
}
|
||||
|
||||
void GxLogOpen() {
|
||||
CGxDevice::LogOpen();
|
||||
}
|
||||
|
||||
void GxLog(const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
CGxDevice::VLog(format, args);
|
||||
}
|
||||
|
||||
void GxLogClose() {
|
||||
CGxDevice::LogClose();
|
||||
}
|
||||
|
||||
void GxAddStereoChangedCallback(CGxDevice::STEREO_CHANGED_CALLBACK callback) {
|
||||
// TODO
|
||||
// g_theGxDevicePtr->AddStereoChangedCallback(callback);
|
||||
}
|
||||
|
||||
int32_t GxRemoveStereoChangedCallback(CGxDevice::STEREO_CHANGED_CALLBACK callback) {
|
||||
// TODO
|
||||
// return g_theGxDevicePtr->RemoveStereoChangedCallback(callback);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void GxStereoSetConvergence(float value) {
|
||||
// TODO
|
||||
// return g_theGxDevicePtr->StereoSetConvergence(value);
|
||||
}
|
||||
|
||||
void GxStereoSetSeparation(float value) {
|
||||
// TODO
|
||||
// return g_theGxDevicePtr->StereoSetSeparation(value);
|
||||
}
|
||||
|
||||
const CGxCaps& GxCaps() {
|
||||
return g_theGxDevicePtr->Caps();
|
||||
}
|
||||
|
||||
bool GxCapsWindowHasFocus(int32_t a1) {
|
||||
// TODO
|
||||
return true;
|
||||
}
|
||||
|
||||
void GxCapsWindowSize(CRect& rect) {
|
||||
g_theGxDevicePtr->CapsWindowSize(rect);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,12 +9,51 @@ class CGxFormat;
|
|||
|
||||
extern CGxDevice* g_theGxDevicePtr;
|
||||
|
||||
|
||||
bool GxApiSupported(EGxApi api);
|
||||
|
||||
EGxApi GxDefaultApi();
|
||||
|
||||
CGxDevice* GxDevCreate(EGxApi api, int32_t (*windowProc)(void* window, uint32_t message, uintptr_t wparam, intptr_t lparam), const CGxFormat& format);
|
||||
|
||||
void GxDevDestroy(CGxDevice* device);
|
||||
|
||||
EGxApi GxDevApi(void);
|
||||
|
||||
bool GxDevExists();
|
||||
|
||||
void* GxDevWindow();
|
||||
|
||||
int32_t GxMasterEnable(EGxMasterEnables state);
|
||||
|
||||
void GxDevOverride(EGxOverride override, uint32_t value);
|
||||
|
||||
int32_t GxAdapterDesktopMode(CGxMonitorMode& mode);
|
||||
|
||||
int32_t GxAdapterMonitorModes(TSGrowableArray<CGxMonitorMode>& modes);
|
||||
|
||||
int32_t GxAdapterID(uint16_t& vendorID, uint16_t& deviceID, uint32_t& driverVersionHi, uint32_t& driverVersionLow);
|
||||
|
||||
int32_t GxAdapterInfer(uint16_t& deviceID);
|
||||
|
||||
void GxLogOpen();
|
||||
|
||||
void GxLog(const char* format, ...);
|
||||
|
||||
void GxLogClose();
|
||||
|
||||
void GxAddStereoChangedCallback(CGxDevice::STEREO_CHANGED_CALLBACK callback);
|
||||
|
||||
int32_t GxRemoveStereoChangedCallback(CGxDevice::STEREO_CHANGED_CALLBACK callback);
|
||||
|
||||
void GxStereoSetConvergence(float value);
|
||||
|
||||
void GxStereoSetSeparation(float value);
|
||||
|
||||
const CGxCaps& GxCaps();
|
||||
|
||||
bool GxCapsWindowHasFocus(int32_t);
|
||||
|
||||
void GxCapsWindowSize(CRect&);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -37,44 +37,6 @@ const char** g_gxShaderProfileNames[GxShTargets_Last] = {
|
|||
static uint32_t s_maxFPS;
|
||||
static uint32_t s_maxFPSBk;
|
||||
|
||||
const CGxCaps& GxCaps() {
|
||||
return g_theGxDevicePtr->Caps();
|
||||
}
|
||||
|
||||
bool GxCapsWindowHasFocus(int32_t a1) {
|
||||
// TODO
|
||||
return true;
|
||||
}
|
||||
|
||||
void GxCapsWindowSize(CRect& rect) {
|
||||
g_theGxDevicePtr->CapsWindowSize(rect);
|
||||
}
|
||||
|
||||
void GxFormatColor(CImVector& color) {
|
||||
if (GxCaps().m_colorFormat == GxCF_rgba) {
|
||||
CImVector formattedColor = {
|
||||
color.r,
|
||||
color.g,
|
||||
color.b,
|
||||
color.a
|
||||
};
|
||||
|
||||
color = formattedColor;
|
||||
}
|
||||
}
|
||||
|
||||
void GxLogOpen() {
|
||||
CGxDevice::LogOpen();
|
||||
}
|
||||
|
||||
void GxLogClose() {
|
||||
CGxDevice::LogClose();
|
||||
}
|
||||
|
||||
void GxLog(const char* format, ...) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void GxSetMaxFPS(uint32_t maxFPS) {
|
||||
s_maxFPS = maxFPS;
|
||||
}
|
||||
|
|
@ -90,3 +52,16 @@ uint32_t GxGetMaxFPS() {
|
|||
uint32_t GxGetMaxFPSBk() {
|
||||
return s_maxFPSBk;
|
||||
}
|
||||
|
||||
void GxFormatColor(CImVector& color) {
|
||||
if (GxCaps().m_colorFormat == GxCF_rgba) {
|
||||
CImVector formattedColor = {
|
||||
color.r,
|
||||
color.g,
|
||||
color.b,
|
||||
color.a
|
||||
};
|
||||
|
||||
color = formattedColor;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,20 +10,8 @@ class CRect;
|
|||
|
||||
extern const char** g_gxShaderProfileNames[GxShTargets_Last];
|
||||
|
||||
const CGxCaps& GxCaps();
|
||||
|
||||
bool GxCapsWindowHasFocus(int32_t);
|
||||
|
||||
void GxCapsWindowSize(CRect&);
|
||||
|
||||
void GxFormatColor(CImVector&);
|
||||
|
||||
void GxLogOpen();
|
||||
|
||||
void GxLogClose();
|
||||
|
||||
void GxLog(const char* format, ...);
|
||||
|
||||
void GxSetMaxFPS(uint32_t maxFPS);
|
||||
|
||||
void GxSetMaxFPSBk(uint32_t maxFPSBk);
|
||||
|
|
|
|||
|
|
@ -530,7 +530,7 @@ void CGxDeviceD3d::DeviceWM(EGxWM wm, uintptr_t param1, uintptr_t param2) {
|
|||
|
||||
// TODO
|
||||
|
||||
this->intF6C = 1;
|
||||
this->m_needsReset = 1;
|
||||
|
||||
return;
|
||||
} else {
|
||||
|
|
@ -538,7 +538,7 @@ void CGxDeviceD3d::DeviceWM(EGxWM wm, uintptr_t param1, uintptr_t param2) {
|
|||
}
|
||||
}
|
||||
|
||||
this->intF6C = 1;
|
||||
this->m_needsReset = 1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -1746,7 +1746,7 @@ void CGxDeviceD3d::IStateSync() {
|
|||
|
||||
// TODO
|
||||
|
||||
if (this->intF6C) {
|
||||
if (this->m_needsReset) {
|
||||
this->IXformSetViewport();
|
||||
}
|
||||
}
|
||||
|
|
@ -2124,7 +2124,7 @@ void CGxDeviceD3d::IXformSetViewport() {
|
|||
|
||||
this->m_d3dDevice->SetViewport(&d3dViewport);
|
||||
|
||||
this->intF6C = 0;
|
||||
this->m_needsReset = 0;
|
||||
}
|
||||
|
||||
void CGxDeviceD3d::IXformSetWorld() {
|
||||
|
|
@ -2159,7 +2159,7 @@ void CGxDeviceD3d::SceneClear(uint32_t mask, CImVector color) {
|
|||
flags |= 0x2;
|
||||
}
|
||||
|
||||
if (this->intF6C) {
|
||||
if (this->m_needsReset) {
|
||||
this->IXformSetViewport();
|
||||
}
|
||||
|
||||
|
|
@ -2200,12 +2200,8 @@ void CGxDeviceD3d::ShaderCreate(CGxShader* shaders[], EGxShTarget target, const
|
|||
}
|
||||
|
||||
int32_t CGxDeviceD3d::StereoEnabled() {
|
||||
return this->m_d3dStereoEnabled == 1;
|
||||
}
|
||||
|
||||
void CGxDeviceD3d::CursorUnlock() {
|
||||
CGxDevice::CursorUnlock(x, y);
|
||||
this->m_hwCursorNeedsUpdate = 1;
|
||||
// return this->m_d3dStereoEnabled == 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CGxDeviceD3d::XformSetProjection(const C44Matrix& matrix) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#include "gx/glsdl/CGxDeviceGLSDL.hpp"
|
||||
#include "event/Input.hpp"
|
||||
#include "os/Input.hpp"
|
||||
#include "gx/Blit.hpp"
|
||||
#include "gx/CGxBatch.hpp"
|
||||
#include "gx/Shader.hpp"
|
||||
|
|
@ -681,9 +681,13 @@ void CGxDeviceGLSDL::ISetCaps(const CGxFormat& format) {
|
|||
this->m_caps.m_texMaxSize[GxTex_Rectangle] = 4096;
|
||||
this->m_caps.m_texMaxSize[GxTex_NonPow2] = 4096;
|
||||
|
||||
this->m_caps.m_hardwareCursor = 0;
|
||||
this->m_caps.m_hwCursor = 0;
|
||||
|
||||
// TODO
|
||||
|
||||
// TODO: proper implementation
|
||||
this->m_caps.m_numTmus = 2;
|
||||
this->m_caps.m_numStreams = 1;
|
||||
}
|
||||
|
||||
void CGxDeviceGLSDL::IShaderBindPixel(CGxShader* sh) {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ void GLSDLContext::Create(GLSDLWindow* window) {
|
|||
void GLSDLContext::Destroy() {
|
||||
BC_ASSERT(this->m_sdlGLContext != nullptr);
|
||||
|
||||
SDL_GL_DeleteContext(this->m_sdlGLContext);
|
||||
SDL_GL_DestroyContext(this->m_sdlGLContext);
|
||||
this->m_sdlGLContext = nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ bool GLSDLContext::IsCurrentContext() {
|
|||
|
||||
void GLSDLContext::MakeCurrent(GLSDLWindow* window) {
|
||||
auto status = SDL_GL_MakeCurrent(window->m_sdlWindow, this->m_sdlGLContext);
|
||||
BC_ASSERT(status == 0);
|
||||
BC_ASSERT(status);
|
||||
}
|
||||
|
||||
int32_t GLSDLContext::GetSampleCount() {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#ifndef GX_GL_SDL_GL_SDL_CONTEXT_HPP
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include "gx/glsdl/GLSDLWindow.hpp"
|
||||
#include "gx/glsdl/GLTypes.hpp"
|
||||
|
|
|
|||
|
|
@ -68,15 +68,13 @@ void GLSDLWindow::Create(const char* title, const GLSDLWindowRect& rect, GLTextu
|
|||
|
||||
this->m_sdlWindow = SDL_CreateWindow(
|
||||
title,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
static_cast<int>(rect.size.width), static_cast<int>(rect.size.height),
|
||||
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE
|
||||
);
|
||||
|
||||
BC_ASSERT(this->m_sdlWindow != nullptr);
|
||||
|
||||
SDL_StartTextInput();
|
||||
SDL_StartTextInput(this->m_sdlWindow);
|
||||
}
|
||||
|
||||
void GLSDLWindow::Swap() {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#define GX_GL_SDL_GL_SDL_WINDOW_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include "gx/glsdl/GLTypes.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -141,11 +141,13 @@ void CBLPFile::DecompPalARGB8888(uint8_t* data, void* tempbuffer, uint32_t color
|
|||
auto pixels = data;
|
||||
auto bytes = reinterpret_cast<uint8_t*>(tempbuffer);
|
||||
|
||||
for (auto i = colorSize; i; i--) {
|
||||
auto i = colorSize;
|
||||
while (i != 0) {
|
||||
*reinterpret_cast<BlpPalPixel*>(pixels) = this->m_header.extended.palette[*bytes];
|
||||
pixels[3] = 0xFF;
|
||||
pixels += 4;
|
||||
bytes++;
|
||||
i--;
|
||||
}
|
||||
|
||||
auto alphaBits = this->AlphaBits();
|
||||
|
|
|
|||
|
|
@ -27,7 +27,10 @@ struct BlpPalPixel {
|
|||
uint8_t pad;
|
||||
};
|
||||
|
||||
static_assert(sizeof(BlpPalPixel) == 4);
|
||||
|
||||
class CBLPFile {
|
||||
#pragma pack(push, 1)
|
||||
struct BLPHeader {
|
||||
uint32_t magic = 0x32504C42;
|
||||
uint32_t formatVersion = 1;
|
||||
|
|
@ -49,6 +52,7 @@ class CBLPFile {
|
|||
} jpeg;
|
||||
} extended;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
public:
|
||||
// Static variables
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#include "gx/texture/CGxTex.hpp"
|
||||
#include "gx/Gx.hpp"
|
||||
#include "gx/Device.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
CGxTexFlags::CGxTexFlags(EGxTexFilter filter, uint32_t wrapU, uint32_t wrapV, uint32_t force, uint32_t generateMipMaps, uint32_t renderTarget, uint32_t maxAnisotropy) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue