mirror of
https://github.com/thunderbrewhq/thunderbrew
synced 2026-01-30 19:42:51 +03:00
Merge branch 'master' into master
This commit is contained in:
commit
2ff05376e8
24
.gitmodules
vendored
24
.gitmodules
vendored
@ -1,15 +1,15 @@
|
|||||||
[submodule "lib/common"]
|
[submodule "lib/common"]
|
||||||
path = lib/common
|
path = lib/common
|
||||||
url = https://github.com/whoahq/common.git
|
url = https://github.com/thunderbrewhq/common.git
|
||||||
[submodule "lib/squall"]
|
[submodule "lib/squall"]
|
||||||
path = lib/squall
|
path = lib/squall
|
||||||
url = https://github.com/whoahq/squall.git
|
url = https://github.com/thunderbrewhq/squall.git
|
||||||
[submodule "lib/typhoon"]
|
[submodule "lib/typhoon"]
|
||||||
path = lib/typhoon
|
path = lib/typhoon
|
||||||
url = https://github.com/whoahq/typhoon.git
|
url = https://github.com/thunderbrewhq/typhoon.git
|
||||||
[submodule "lib/system"]
|
[submodule "lib/system"]
|
||||||
path = lib/system
|
path = lib/system
|
||||||
url = https://github.com/whoahq/system.git
|
url = https://github.com/thunderbrewhq/system.git
|
||||||
[submodule "lib/bc"]
|
[submodule "lib/bc"]
|
||||||
path = lib/bc
|
path = lib/bc
|
||||||
url = https://github.com/whoahq/bc
|
url = https://github.com/thunderbrewhq/bc.git
|
||||||
|
|||||||
2
lib/bc
2
lib/bc
@ -1 +1 @@
|
|||||||
Subproject commit 6cff259dcac37698fd0c770d806646be13402b43
|
Subproject commit 2b620905ca9c4f094bfaf3e2e976acbb6ab0d098
|
||||||
@ -1 +1 @@
|
|||||||
Subproject commit 0a260b7bebe28bbc5998068f6f14e459a869de16
|
Subproject commit 833012f1a6d3e185b668634ed2aae28b10a7fa83
|
||||||
@ -1 +1 @@
|
|||||||
Subproject commit f10552acea5fbfaa7f03075eddd46a92132bf732
|
Subproject commit 8bc4f9ee50d348a0b1803017e8c72bc7302b9b56
|
||||||
@ -1 +1 @@
|
|||||||
Subproject commit 036c986cd455179873baeb75e81fd3edaca4abbe
|
Subproject commit a399b42f1142d1e8c2c6e2be804a744bfcf2d597
|
||||||
@ -1,8 +1,11 @@
|
|||||||
#include "client/Client.hpp"
|
#include "client/Client.hpp"
|
||||||
|
#include "bc/os/CommandLine.hpp"
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
// TODO
|
// TODO
|
||||||
|
|
||||||
|
OsSetCommandLine(argc, argv);
|
||||||
|
|
||||||
CommonMain();
|
CommonMain();
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#include "app/mac/WoWApplication.h"
|
#include "app/mac/WoWApplication.h"
|
||||||
#include "app/mac/MacClient.h"
|
#include "app/mac/MacClient.h"
|
||||||
#include "client/Client.hpp"
|
#include "client/Client.hpp"
|
||||||
|
#include "bc/os/CommandLine.hpp"
|
||||||
#include <AppKit/AppKit.h>
|
#include <AppKit/AppKit.h>
|
||||||
#include <Foundation/Foundation.h>
|
#include <Foundation/Foundation.h>
|
||||||
|
|
||||||
@ -8,6 +9,8 @@ int32_t main(int32_t argc, char* argv[]) {
|
|||||||
// TODO
|
// TODO
|
||||||
// MacClient::SetupCommandLine(argc, argv, v10);
|
// MacClient::SetupCommandLine(argc, argv, v10);
|
||||||
|
|
||||||
|
OsSetCommandLine(argc, argv);
|
||||||
|
|
||||||
if (MacClient::IsUsingGLLayer()) {
|
if (MacClient::IsUsingGLLayer()) {
|
||||||
// TODO
|
// TODO
|
||||||
// GxSetRequestedApi(3);
|
// GxSetRequestedApi(3);
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#include "client/Client.hpp"
|
#include "client/Client.hpp"
|
||||||
#include "async/AsyncFile.hpp"
|
#include "async/AsyncFile.hpp"
|
||||||
#include "client/ClientServices.hpp"
|
#include "client/ClientServices.hpp"
|
||||||
|
#include "client/CmdLine.hpp"
|
||||||
#include "console/CVar.hpp"
|
#include "console/CVar.hpp"
|
||||||
#include "console/Client.hpp"
|
#include "console/Client.hpp"
|
||||||
#include "console/Device.hpp"
|
#include "console/Device.hpp"
|
||||||
@ -18,6 +19,7 @@
|
|||||||
#include <bc/Debug.hpp>
|
#include <bc/Debug.hpp>
|
||||||
#include <common/Prop.hpp>
|
#include <common/Prop.hpp>
|
||||||
#include <storm/Error.hpp>
|
#include <storm/Error.hpp>
|
||||||
|
#include <bc/os/Path.hpp>
|
||||||
|
|
||||||
CVar* Client::g_accountListVar;
|
CVar* Client::g_accountListVar;
|
||||||
HEVENTCONTEXT Client::g_clientEventContext;
|
HEVENTCONTEXT Client::g_clientEventContext;
|
||||||
@ -136,12 +138,28 @@ int32_t InitializeEngineCallback(const void* a1, void* a2) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetPaths() {
|
||||||
|
// SFile::DisableSFileCheckDisk();
|
||||||
|
// SFile::EnableDirectAccess(0);
|
||||||
|
|
||||||
|
char buffer[STORM_MAX_PATH] = {0};
|
||||||
|
|
||||||
|
const char* datadir = CmdLineGetString(CMD_DATA_DIR);
|
||||||
|
if (*datadir == '\0') {
|
||||||
|
OsGetExePath(buffer, STORM_MAX_PATH);
|
||||||
|
datadir = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
SFile::SetBasePath(datadir);
|
||||||
|
SFile::SetDataPath("Data\\");
|
||||||
|
|
||||||
|
OsSetCurrentDirectory(datadir);
|
||||||
|
}
|
||||||
|
|
||||||
int32_t InitializeGlobal() {
|
int32_t InitializeGlobal() {
|
||||||
// TODO
|
// TODO
|
||||||
|
|
||||||
// SCmdRegisterArgList(&ProcessCommandLine(void)::s_wowArgList, 17u);
|
ProcessCommandLine();
|
||||||
|
|
||||||
// CmdLineProcess();
|
|
||||||
|
|
||||||
// sub_403600("WoW.mfil");
|
// sub_403600("WoW.mfil");
|
||||||
|
|
||||||
@ -159,10 +177,16 @@ int32_t InitializeGlobal() {
|
|||||||
|
|
||||||
OpenArchives();
|
OpenArchives();
|
||||||
|
|
||||||
|
SetPaths();
|
||||||
|
|
||||||
ConsoleInitializeClientCommand();
|
ConsoleInitializeClientCommand();
|
||||||
|
|
||||||
ConsoleInitializeClientCVar("Config.wtf");
|
ConsoleInitializeClientCVar("Config.wtf");
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// replace enUS with detected locale
|
||||||
|
ClientServices::InitLoginServerCVars(1, "enUS");
|
||||||
|
|
||||||
// sub_7663F0();
|
// sub_7663F0();
|
||||||
|
|
||||||
// v18 = 0;
|
// v18 = 0;
|
||||||
|
|||||||
@ -3,7 +3,9 @@
|
|||||||
#include "glue/CGlueMgr.hpp"
|
#include "glue/CGlueMgr.hpp"
|
||||||
#include "net/Connection.hpp"
|
#include "net/Connection.hpp"
|
||||||
#include "net/Login.hpp"
|
#include "net/Login.hpp"
|
||||||
|
#include "console/Client.hpp"
|
||||||
#include "console/CVar.hpp"
|
#include "console/CVar.hpp"
|
||||||
|
#include "console/Types.hpp"
|
||||||
#include <storm/Memory.hpp>
|
#include <storm/Memory.hpp>
|
||||||
#include <storm/String.hpp>
|
#include <storm/String.hpp>
|
||||||
#include <new>
|
#include <new>
|
||||||
@ -16,10 +18,16 @@ ClientConnection* ClientServices::s_currentConnection;
|
|||||||
ClientServices* ClientServices::s_instance;
|
ClientServices* ClientServices::s_instance;
|
||||||
Login* ClientServices::s_loginObj;
|
Login* ClientServices::s_loginObj;
|
||||||
bool ClientServices::s_newLogin;
|
bool ClientServices::s_newLogin;
|
||||||
CVar* ClientServices::s_realmNameVar;
|
|
||||||
REALM_INFO ClientServices::s_selectRealmInfo;
|
REALM_INFO ClientServices::s_selectRealmInfo;
|
||||||
bool ClientServices::s_selectRealmInfoValid;
|
bool ClientServices::s_selectRealmInfoValid;
|
||||||
|
|
||||||
|
CVar* ClientServices::s_realmNameVar = nullptr;
|
||||||
|
CVar* ClientServices::s_decorateAccountName = nullptr;
|
||||||
|
CVar* ClientServices::s_realmListBNVar = nullptr;
|
||||||
|
CVar* ClientServices::s_darkPortalVar = nullptr;
|
||||||
|
CVar* ClientServices::s_ServerAlertVar = nullptr;
|
||||||
|
CVar* ClientServices::s_realmListVar = nullptr;
|
||||||
|
|
||||||
void ClientServices::ConnectToSelectedServer() {
|
void ClientServices::ConnectToSelectedServer() {
|
||||||
if (!ClientServices::s_selectRealmInfoValid && !ClientServices::SetSelectedRealmInfo(0)) {
|
if (!ClientServices::s_selectRealmInfoValid && !ClientServices::SetSelectedRealmInfo(0)) {
|
||||||
ClientServices::Connection()->Complete(0, 39);
|
ClientServices::Connection()->Complete(0, 39);
|
||||||
@ -138,9 +146,19 @@ void ClientServices::Logon(const char* accountName, const char* password) {
|
|||||||
|
|
||||||
ClientServices::s_loginObj->SetLogonCreds(accountName, password);
|
ClientServices::s_loginObj->SetLogonCreds(accountName, password);
|
||||||
|
|
||||||
|
auto loginServerType = ClientServices::s_loginObj->GetLoginServerType();
|
||||||
|
|
||||||
|
auto portal = loginServerType == 1 ?
|
||||||
|
ClientServices::s_darkPortalVar->GetString() :
|
||||||
|
"";
|
||||||
|
|
||||||
|
auto realmList = loginServerType == 1 ?
|
||||||
|
ClientServices::s_realmListBNVar->GetString() :
|
||||||
|
ClientServices::s_realmListVar->GetString();
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
|
||||||
ClientServices::s_loginObj->Logon(nullptr, nullptr);
|
ClientServices::s_loginObj->Logon(realmList, portal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientServices::SelectRealm(const char* realmName) {
|
void ClientServices::SelectRealm(const char* realmName) {
|
||||||
@ -229,3 +247,107 @@ void ClientServices::RealmEnumCallback(uint32_t a2) {
|
|||||||
|
|
||||||
ClientServices::ConnectToSelectedServer();
|
ClientServices::ConnectToSelectedServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* ClientServices::GetDefaultRealmlistString() {
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
// return default us realmlist for now
|
||||||
|
|
||||||
|
return "us.logon.worldofwarcraft.com:3724";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* ClientServices::GetDefaultPatchListString() {
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
// Return default patchlist for now
|
||||||
|
|
||||||
|
return "public-test.patch.battle.net:1119/patch";
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientServices::InitLoginServerCVars(int32_t overwrite, const char* locale) {
|
||||||
|
if ((ClientServices::s_realmListBNVar == nullptr || ClientServices::s_realmListVar == nullptr) || overwrite != 0 ) {
|
||||||
|
ClientServices::s_decorateAccountName = CVar::Register(
|
||||||
|
"decorateAccountName",
|
||||||
|
"",
|
||||||
|
0,
|
||||||
|
"0",
|
||||||
|
nullptr,
|
||||||
|
CATEGORY::NET,
|
||||||
|
false,
|
||||||
|
nullptr,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
char localRealmList[260] = {0};
|
||||||
|
char localDataDir[272] = {0};
|
||||||
|
|
||||||
|
if (locale == nullptr || *locale == '\0') {
|
||||||
|
localDataDir[0] = '\0';
|
||||||
|
} else {
|
||||||
|
SStrPrintf(localDataDir, STORM_MAX_PATH, "data\\%s\\", locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ClientServices::s_realmListBNVar == nullptr) || overwrite != 0) {
|
||||||
|
ClientServices::s_realmListBNVar = CVar::Register(
|
||||||
|
"realmListbn",
|
||||||
|
"Address of Battle.net server",
|
||||||
|
0,
|
||||||
|
"",
|
||||||
|
nullptr,
|
||||||
|
CATEGORY::NET,
|
||||||
|
false,
|
||||||
|
nullptr,
|
||||||
|
false);
|
||||||
|
|
||||||
|
SStrPrintf(localRealmList, STORM_MAX_PATH, "%srealmlistbn.wtf", localDataDir);
|
||||||
|
|
||||||
|
if (ConsoleLoadClientCVar(localRealmList) == 0) {
|
||||||
|
ConsoleLoadClientCVar("realmlistbn.wtf");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ClientServices::s_darkPortalVar == nullptr || overwrite != 0) {
|
||||||
|
ClientServices::s_darkPortalVar = CVar::Register(
|
||||||
|
"portal",
|
||||||
|
"Name of Battle.net portal to use",
|
||||||
|
0,
|
||||||
|
"public-test",
|
||||||
|
nullptr,
|
||||||
|
CATEGORY::NET,
|
||||||
|
false,
|
||||||
|
nullptr,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ClientServices::s_ServerAlertVar == nullptr || overwrite != 0) {
|
||||||
|
ClientServices::s_ServerAlertVar = CVar::Register(
|
||||||
|
"serverAlert",
|
||||||
|
"Get the glue-string tag for the URL",
|
||||||
|
0,
|
||||||
|
"SERVER_ALERT_URL",
|
||||||
|
nullptr,
|
||||||
|
CATEGORY::NET,
|
||||||
|
false,
|
||||||
|
nullptr,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ClientServices::s_ServerAlertVar == nullptr || overwrite != 0) {
|
||||||
|
ClientServices::s_realmListVar = CVar::Register(
|
||||||
|
"realmList",
|
||||||
|
"Address of realm list server",
|
||||||
|
0,
|
||||||
|
ClientServices::GetDefaultRealmlistString(),
|
||||||
|
nullptr,
|
||||||
|
CATEGORY::NET,
|
||||||
|
false,
|
||||||
|
nullptr,
|
||||||
|
false);
|
||||||
|
|
||||||
|
SStrPrintf(localRealmList, STORM_MAX_PATH, "%srealmlist.wtf", localDataDir);
|
||||||
|
|
||||||
|
if (ConsoleLoadClientCVar(localRealmList) == 0) {
|
||||||
|
ConsoleLoadClientCVar("realmlist.wtf");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -17,10 +17,18 @@ class ClientServices : public LoginResponse {
|
|||||||
static ClientServices* s_instance;
|
static ClientServices* s_instance;
|
||||||
static Login* s_loginObj;
|
static Login* s_loginObj;
|
||||||
static bool s_newLogin;
|
static bool s_newLogin;
|
||||||
static CVar* s_realmNameVar;
|
|
||||||
static REALM_INFO s_selectRealmInfo;
|
static REALM_INFO s_selectRealmInfo;
|
||||||
static bool s_selectRealmInfoValid;
|
static bool s_selectRealmInfoValid;
|
||||||
|
|
||||||
|
// Static console variables
|
||||||
|
static CVar* s_realmNameVar;
|
||||||
|
static CVar* s_decorateAccountName;
|
||||||
|
static CVar* s_realmListBNVar;
|
||||||
|
static CVar* s_darkPortalVar;
|
||||||
|
static CVar* s_ServerAlertVar;
|
||||||
|
static CVar* s_realmListVar;
|
||||||
|
static CVar* s_patchListVar;
|
||||||
|
|
||||||
// Static functions
|
// Static functions
|
||||||
static void ConnectToSelectedServer();
|
static void ConnectToSelectedServer();
|
||||||
static ClientConnection* Connection();
|
static ClientConnection* Connection();
|
||||||
@ -34,6 +42,9 @@ class ClientServices : public LoginResponse {
|
|||||||
static void SelectRealm(const char* realmName);
|
static void SelectRealm(const char* realmName);
|
||||||
static void SetAccountName(const char* accountName);
|
static void SetAccountName(const char* accountName);
|
||||||
static int32_t SetSelectedRealmInfo(int32_t a1);
|
static int32_t SetSelectedRealmInfo(int32_t a1);
|
||||||
|
static void InitLoginServerCVars(int32_t overwrite, const char* locale);
|
||||||
|
static const char* GetDefaultRealmlistString();
|
||||||
|
static const char* GetDefaultPatchListString();
|
||||||
|
|
||||||
// Virtual member functions
|
// Virtual member functions
|
||||||
virtual int32_t GetLoginServerType();
|
virtual int32_t GetLoginServerType();
|
||||||
|
|||||||
74
src/client/CmdLine.cpp
Normal file
74
src/client/CmdLine.cpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#include "client/CmdLine.hpp"
|
||||||
|
|
||||||
|
#include <storm/Command.hpp>
|
||||||
|
|
||||||
|
int32_t CmdLineProcess() {
|
||||||
|
// engine-specific flags.
|
||||||
|
static ARGLIST s_argList[] = {
|
||||||
|
{0x0, CMD_D3D, "d3d", nullptr},
|
||||||
|
{0x0, CMD_D3D9EX, "d3d9ex", nullptr},
|
||||||
|
{STORM_COMMAND_TYPE_STRING, CMD_DATA_DIR, "datadir", nullptr},
|
||||||
|
{0x0, CMD_NO_LAG_FIX, "nolagfix", nullptr},
|
||||||
|
{STORM_COMMAND_TYPE_STRING, CMD_LOADFILE, "loadfile", nullptr},
|
||||||
|
{STORM_COMMAND_TYPE_STRING, CMD_GAMETYPE, "gametype", nullptr},
|
||||||
|
{0x0, CMD_OPENGL, "opengl", nullptr},
|
||||||
|
{0x0, CMD_SW_TNL, "swtnl", nullptr},
|
||||||
|
{0x0, CMD_TIMEDEMO, "timedemo", nullptr},
|
||||||
|
{STORM_COMMAND_TYPE_STRING, CMD_DEMOREZ, "rez", nullptr},
|
||||||
|
{STORM_COMMAND_TYPE_STRING, CMD_DEMODEPTH, "depth", nullptr},
|
||||||
|
{STORM_COMMAND_TYPE_STRING, CMD_DEMODETAIL, "detail", nullptr},
|
||||||
|
{STORM_COMMAND_TYPE_STRING, CMD_DEMOSOUND, "sound", nullptr},
|
||||||
|
{0x0, CMD_FULL_SCREEN, "fullscreen", nullptr},
|
||||||
|
{0x0, CMD_22050HZ, "22050", nullptr},
|
||||||
|
{0x0, CMD_NO_WARNINGS, "nowarnings", nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
// load engine-specific launch flags
|
||||||
|
SCmdRegisterArgList(s_argList, sizeof(s_argList) / sizeof(ARGLIST));
|
||||||
|
|
||||||
|
// parse command line
|
||||||
|
return SCmdProcessCommandLine(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessCommandLine() {
|
||||||
|
static ARGLIST s_wowArgList[] = {
|
||||||
|
{0x0, WOWCMD_RES_800x600, "800x600", nullptr},
|
||||||
|
{0x0, WOWCMD_RES_1024x768, "1024x768", nullptr},
|
||||||
|
{0x0, WOWCMD_RES_1280x960, "1280x960", nullptr},
|
||||||
|
{0x0, WOWCMD_RES_1280x1024, "1280x1024", nullptr},
|
||||||
|
{0x0, WOWCMD_RES_1600x1200, "1600x1200", nullptr},
|
||||||
|
{0x0, WOWCMD_16_BIT, "16bit", nullptr},
|
||||||
|
{0x0, WOWCMD_UP_TO_DATE, "uptodate", nullptr},
|
||||||
|
{0x0, WOWCMD_NO_SOUND, "nosound", nullptr},
|
||||||
|
{0x0, WOWCMD_SOUND_CHAOS, "soundchaos", nullptr},
|
||||||
|
{0x0, WOWCMD_NO_FIX_LAG, "nofixlag", nullptr},
|
||||||
|
{0x0, WOWCMD_DEPTH_16, "d16", nullptr},
|
||||||
|
{0x0, WOWCMD_DEPTH_24, "d24", nullptr},
|
||||||
|
{0x0, WOWCMD_DEPTH_32, "d32", nullptr},
|
||||||
|
{0x0, WOWCMD_WINDOWED, "windowed", nullptr},
|
||||||
|
{0x0, WOWCMD_HW_DETECT, "hwdetect", nullptr},
|
||||||
|
{0x0, WOWCMD_CONSOLE, "console", nullptr},
|
||||||
|
{STORM_COMMAND_TYPE_STRING, WOWCMD_GX_OVERRIDE, "gxoverride", nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load wow-specific launch flags
|
||||||
|
SCmdRegisterArgList(s_wowArgList, sizeof(s_wowArgList) / sizeof(ARGLIST));
|
||||||
|
|
||||||
|
CmdLineProcess();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* CmdLineGetString(uint32_t opt) {
|
||||||
|
static char buffer[260] = {0};
|
||||||
|
|
||||||
|
SCmdGetString(opt, buffer, 260);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t CmdLineGetUint(uint32_t opt) {
|
||||||
|
return SCmdGetNum(opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t CmdLineGetBool(uint32_t opt) {
|
||||||
|
return SCmdGetBool(opt);
|
||||||
|
}
|
||||||
57
src/client/CmdLine.hpp
Normal file
57
src/client/CmdLine.hpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#ifndef CLIENT_CMD_LINE_HPP
|
||||||
|
#define CLIENT_CMD_LINE_HPP
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
enum CMDOPT {
|
||||||
|
CMD_D3D = 0,
|
||||||
|
CMD_D3D9EX = 1,
|
||||||
|
CMD_DATA_DIR = 2,
|
||||||
|
CMD_NO_LAG_FIX = 3,
|
||||||
|
CMD_LOADFILE = 4,
|
||||||
|
CMD_GAMETYPE = 5,
|
||||||
|
CMD_OPENGL = 6,
|
||||||
|
CMD_SW_TNL = 7,
|
||||||
|
CMD_TIMEDEMO = 8,
|
||||||
|
CMD_DEMOREZ = 9,
|
||||||
|
CMD_DEMODEPTH = 10,
|
||||||
|
CMD_DEMODETAIL = 11,
|
||||||
|
CMD_DEMOSOUND = 12,
|
||||||
|
CMD_FULL_SCREEN = 13,
|
||||||
|
CMD_22050HZ = 14,
|
||||||
|
CMD_NO_WARNINGS = 15,
|
||||||
|
CMDOPTS
|
||||||
|
};
|
||||||
|
|
||||||
|
enum WOWCMDOPT {
|
||||||
|
WOWCMD_RES_800x600 = 16,
|
||||||
|
WOWCMD_RES_1024x768 = 17,
|
||||||
|
WOWCMD_RES_1280x960 = 18,
|
||||||
|
WOWCMD_RES_1280x1024 = 19,
|
||||||
|
WOWCMD_RES_1600x1200 = 20,
|
||||||
|
WOWCMD_UP_TO_DATE = 21,
|
||||||
|
WOWCMD_16_BIT = 22,
|
||||||
|
WOWCMD_NO_FIX_LAG = 24,
|
||||||
|
WOWCMD_NO_SOUND = 26,
|
||||||
|
WOWCMD_SOUND_CHAOS = 27,
|
||||||
|
WOWCMD_DEPTH_16 = 29,
|
||||||
|
WOWCMD_DEPTH_24 = 30,
|
||||||
|
WOWCMD_DEPTH_32 = 31,
|
||||||
|
WOWCMD_WINDOWED = 32,
|
||||||
|
WOWCMD_CONSOLE = 35,
|
||||||
|
WOWCMD_HW_DETECT = 36,
|
||||||
|
WOWCMD_GX_OVERRIDE = 39,
|
||||||
|
WOWCMD_OPTS
|
||||||
|
};
|
||||||
|
|
||||||
|
int32_t CmdLineProcess();
|
||||||
|
|
||||||
|
void ProcessCommandLine();
|
||||||
|
|
||||||
|
const char* CmdLineGetString(uint32_t opt);
|
||||||
|
|
||||||
|
uint32_t CmdLineGetUint(uint32_t opt);
|
||||||
|
|
||||||
|
int32_t CmdLineGetBool(uint32_t opt);
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -1,5 +1,6 @@
|
|||||||
file(GLOB PRIVATE_SOURCES
|
file(GLOB PRIVATE_SOURCES
|
||||||
"*.cpp"
|
"*.cpp"
|
||||||
|
"command/*/*.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(console STATIC
|
add_library(console STATIC
|
||||||
|
|||||||
@ -1,6 +1,13 @@
|
|||||||
#include "console/CVar.hpp"
|
#include "console/CVar.hpp"
|
||||||
|
#include "console/Command.hpp"
|
||||||
|
#include "console/Types.hpp"
|
||||||
|
#include "console/Line.hpp"
|
||||||
|
#include "util/SFile.hpp"
|
||||||
|
|
||||||
|
#include <bc/os/File.hpp>
|
||||||
#include <storm/String.hpp>
|
#include <storm/String.hpp>
|
||||||
|
|
||||||
|
const char* s_filename = nullptr;
|
||||||
bool CVar::m_needsSave;
|
bool CVar::m_needsSave;
|
||||||
TSHashTable<CVar, HASHKEY_STRI> CVar::s_registeredCVars;
|
TSHashTable<CVar, HASHKEY_STRI> CVar::s_registeredCVars;
|
||||||
|
|
||||||
@ -68,8 +75,7 @@ CVar* CVar::Register(const char* name, const char* help, uint32_t flags, const c
|
|||||||
var->m_flags |= 0x80;
|
var->m_flags |= 0x80;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
ConsoleCommandRegister(name, CvarCommandHandler, CATEGORY(category), help);
|
||||||
// ConsoleCommandRegister(var->m_key.GetString(), &CvarCommandHandler, category, help);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return var;
|
return var;
|
||||||
@ -147,6 +153,26 @@ bool CVar::Set(const char* value, bool setValue, bool setReset, bool setDefault,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CVar::Reset() {
|
||||||
|
auto value = this->m_resetValue;
|
||||||
|
if (value.GetString() == nullptr) {
|
||||||
|
value = this->m_defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->InternalSet(value.GetString(), true, false, false, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CVar::Default() {
|
||||||
|
auto value = this->m_defaultValue;
|
||||||
|
if (value.GetString() == nullptr) {
|
||||||
|
value = this->m_resetValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->InternalSet(value.GetString(), true, false, false, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t CVar::Update() {
|
int32_t CVar::Update() {
|
||||||
if (!(this->m_flags & 0x2)) {
|
if (!(this->m_flags & 0x2)) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -161,3 +187,221 @@ int32_t CVar::Update() {
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t s_CreatePathDirectories(const char* szPath) {
|
||||||
|
return true == OsCreateDirectory(szPath, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t CVar::Load(HOSFILE file) {
|
||||||
|
char fastData[2048] = {0};
|
||||||
|
char line[2048] = {0};
|
||||||
|
|
||||||
|
auto size = OsGetFileSize(file);
|
||||||
|
|
||||||
|
char* data = nullptr;
|
||||||
|
|
||||||
|
if (0x1fff < size) {
|
||||||
|
data = reinterpret_cast<char*>(SMemAlloc(size + 1, __FILE__, __LINE__, 0));
|
||||||
|
} else {
|
||||||
|
data = fastData;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto grown = 0x1fff < size;
|
||||||
|
|
||||||
|
int32_t result = 0;
|
||||||
|
size_t bytesRead = 0;
|
||||||
|
|
||||||
|
if (OsReadFile(file, data, size, &bytesRead) == 0) {
|
||||||
|
result = 0;
|
||||||
|
} else {
|
||||||
|
data[size] = '\0';
|
||||||
|
const char* curr = data;
|
||||||
|
|
||||||
|
// Skip over UTF-8 byte order mark
|
||||||
|
if ((((data != nullptr) && (2 < bytesRead)) && (data[0] == 0xef)) && ((data[1] == 0xbb && (data[2] == 0xbf)))) {
|
||||||
|
curr = data + 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
SStrTokenize(&curr, line, 0x800, "\r\n", 0);
|
||||||
|
|
||||||
|
// Do not execute commands other than "set ..."
|
||||||
|
if (SStrCmpI(line, "SET ", 4) == 0) {
|
||||||
|
// Execute without adding to history
|
||||||
|
ConsoleCommandExecute(line, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = 1;
|
||||||
|
} while ((curr != nullptr) && (*curr != '\0'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grown) {
|
||||||
|
SMemFree(data, __FILE__, __LINE__, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t CVar::Load(const char* filename) {
|
||||||
|
char path[STORM_MAX_PATH] = {0};
|
||||||
|
|
||||||
|
auto file = OsCreateFile(filename, OS_GENERIC_READ, 0, OS_OPEN_EXISTING, OS_FILE_ATTRIBUTE_NORMAL, 0x3f3f3f3f);
|
||||||
|
|
||||||
|
if (file == HOSFILE_INVALID) {
|
||||||
|
SStrPrintf(path, STORM_MAX_PATH, "WTF\\%s", filename);
|
||||||
|
file = OsCreateFile(path, OS_GENERIC_READ, 0, OS_OPEN_EXISTING, OS_FILE_ATTRIBUTE_NORMAL, 0x3f3f3f3f);
|
||||||
|
if (file == HOSFILE_INVALID) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = CVar::Load(file);
|
||||||
|
|
||||||
|
OsCloseFile(file);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVar::Initialize(const char* filename) {
|
||||||
|
STORM_ASSERT(filename);
|
||||||
|
s_filename = filename;
|
||||||
|
|
||||||
|
// Get data path
|
||||||
|
char path[STORM_MAX_PATH] = {0};
|
||||||
|
SFile::GetBasePath(path, STORM_MAX_PATH);
|
||||||
|
SStrPrintf(path, STORM_MAX_PATH, "%s%s\\", path, "WTF");
|
||||||
|
|
||||||
|
s_CreatePathDirectories(path);
|
||||||
|
|
||||||
|
static ConsoleCommandList baseCommands[] = {
|
||||||
|
{ "set", SetCommandHandler, "Set the value of a CVar" },
|
||||||
|
{ "cvar_reset", CvarResetCommandHandler, "Set the value of a CVar to it's startup value" },
|
||||||
|
{ "cvar_default", CvarDefaultCommandHandler, "Set the value of a CVar to it's coded default value" },
|
||||||
|
{ "cvarlist", CvarListCommandHandler, "List cvars" }
|
||||||
|
};
|
||||||
|
|
||||||
|
CONSOLE_REGISTER_LIST(DEFAULT, baseCommands);
|
||||||
|
|
||||||
|
CVar::Load(s_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t CvarResetCommandHandler(const char* command, const char* arguments) {
|
||||||
|
char cvarName[256] = {0};
|
||||||
|
auto string = arguments;
|
||||||
|
|
||||||
|
SStrTokenize(&string, cvarName, sizeof(cvarName), " ,;\t\"\r\n", nullptr);
|
||||||
|
|
||||||
|
if (*cvarName) {
|
||||||
|
// reset a specific cvar
|
||||||
|
auto cvar = CVar::Lookup(cvarName);
|
||||||
|
if (cvar) {
|
||||||
|
cvar->Reset();
|
||||||
|
} else {
|
||||||
|
ConsoleWriteA("No such cvar \"%s\"\n", ERROR_COLOR, cvarName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
// reset all cvars
|
||||||
|
ConsoleWrite("Resetting all cvars\n", DEFAULT_COLOR);
|
||||||
|
|
||||||
|
for (auto cvar = CVar::s_registeredCVars.Head(); cvar != nullptr; cvar = CVar::s_registeredCVars.Next(cvar)) {
|
||||||
|
cvar->Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t CvarDefaultCommandHandler(const char* command, const char* arguments) {
|
||||||
|
char cvarName[256] = {0};
|
||||||
|
auto string = arguments;
|
||||||
|
|
||||||
|
SStrTokenize(&string, cvarName, sizeof(cvarName), " ,;\t\"\r\n", nullptr);
|
||||||
|
|
||||||
|
if (*cvarName) {
|
||||||
|
// restore a specific cvar
|
||||||
|
auto cvar = CVar::Lookup(cvarName);
|
||||||
|
if (cvar) {
|
||||||
|
cvar->Default();
|
||||||
|
} else {
|
||||||
|
ConsoleWriteA("No such cvar \"%s\"\n", ERROR_COLOR, cvarName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
// restore all cvars
|
||||||
|
ConsoleWrite("Restoring all cvars\n", DEFAULT_COLOR);
|
||||||
|
|
||||||
|
for (auto cvar = CVar::s_registeredCVars.Head(); cvar != nullptr; cvar = CVar::s_registeredCVars.Next(cvar)) {
|
||||||
|
cvar->Default();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t CvarCommandHandler(const char* command, const char* arguments) {
|
||||||
|
auto cvar = CVar::Lookup(command);
|
||||||
|
STORM_ASSERT(cvar);
|
||||||
|
|
||||||
|
while (*arguments == ' ') {
|
||||||
|
arguments++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arguments[0] != '\0') {
|
||||||
|
cvar->Set(arguments, true, true, false, false);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto value = cvar->m_stringValue.GetString();
|
||||||
|
|
||||||
|
ConsoleWriteA("CVar \"%s\" is \"%s\"", DEFAULT_COLOR, command, value ? value : "");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t SetCommandHandler(const char* command, const char* arguments) {
|
||||||
|
char cvarValue[2048] = {0};
|
||||||
|
char cvarName[256] = {0};
|
||||||
|
|
||||||
|
auto str = arguments;
|
||||||
|
|
||||||
|
SStrTokenize(&str, cvarName, sizeof(cvarName), " ,;\t\"\r\n", nullptr);
|
||||||
|
SStrTokenize(&str, cvarValue, sizeof(cvarValue), " ,;\t\"\r\n", nullptr);
|
||||||
|
|
||||||
|
auto var = CVar::Lookup(cvarName);
|
||||||
|
if (var) {
|
||||||
|
var->Set(cvarValue, true, false, false, true);
|
||||||
|
} else {
|
||||||
|
CVar::Register(cvarName, "", 0, cvarValue, nullptr, DEFAULT, true, nullptr, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t CvarListCommandHandler(const char* command, const char* arguments) {
|
||||||
|
char text[256];
|
||||||
|
char text2[256];
|
||||||
|
|
||||||
|
for (auto cvar = CVar::s_registeredCVars.Head(); cvar != nullptr; cvar = CVar::s_registeredCVars.Next(cvar)) {
|
||||||
|
SStrPrintf(text, sizeof(text), " \"%s\" is \"%s\"", cvar->m_key.m_str, cvar->m_stringValue.GetString());
|
||||||
|
|
||||||
|
if (cvar->m_defaultValue.GetString()) {
|
||||||
|
if (SStrCmp(cvar->m_stringValue.GetString(), cvar->m_defaultValue.GetString(), STORM_MAX_STR)) {
|
||||||
|
SStrPrintf(text2, sizeof(text2), " (default \"%s\")", cvar->m_defaultValue.GetString());
|
||||||
|
SStrPack(text, text2, sizeof(text));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cvar->m_resetValue.GetString()) {
|
||||||
|
if (SStrCmp(cvar->m_stringValue.GetString(), cvar->m_resetValue.GetString(), STORM_MAX_STR)) {
|
||||||
|
SStrPrintf(text2, sizeof(text2), " (reset \"%s\")", cvar->m_resetValue.GetString());
|
||||||
|
SStrPack(text, text2, sizeof(text));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsoleWrite(text, DEFAULT_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <common/String.hpp>
|
#include <common/String.hpp>
|
||||||
#include <storm/Hash.hpp>
|
#include <storm/Hash.hpp>
|
||||||
|
#include <bc/os/File.hpp>
|
||||||
|
|
||||||
class CVar : public TSHashObject<CVar, HASHKEY_STRI> {
|
class CVar : public TSHashObject<CVar, HASHKEY_STRI> {
|
||||||
public:
|
public:
|
||||||
@ -14,7 +15,9 @@ class CVar : public TSHashObject<CVar, HASHKEY_STRI> {
|
|||||||
// Static functions
|
// Static functions
|
||||||
static CVar* Lookup(const char* name);
|
static CVar* Lookup(const char* name);
|
||||||
static CVar* Register(const char*, const char*, uint32_t, const char*, bool (*)(CVar*, const char*, const char*, void*), uint32_t, bool, void*, bool);
|
static CVar* Register(const char*, const char*, uint32_t, const char*, bool (*)(CVar*, const char*, const char*, void*), uint32_t, bool, void*, bool);
|
||||||
|
static void Initialize(const char* filename);
|
||||||
|
static int32_t Load(const char* filename);
|
||||||
|
static int32_t Load(HOSFILE fileHandle);
|
||||||
// Member variables
|
// Member variables
|
||||||
uint32_t m_category = 0;
|
uint32_t m_category = 0;
|
||||||
uint32_t m_flags = 0;
|
uint32_t m_flags = 0;
|
||||||
@ -35,7 +38,16 @@ class CVar : public TSHashObject<CVar, HASHKEY_STRI> {
|
|||||||
const char* GetString(void);
|
const char* GetString(void);
|
||||||
void InternalSet(const char*, bool, bool, bool, bool);
|
void InternalSet(const char*, bool, bool, bool, bool);
|
||||||
bool Set(const char*, bool, bool, bool, bool);
|
bool Set(const char*, bool, bool, bool, bool);
|
||||||
|
bool Reset();
|
||||||
|
bool Default();
|
||||||
int32_t Update();
|
int32_t Update();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int32_t SetCommandHandler(const char* command, const char* arguments);
|
||||||
|
int32_t CvarResetCommandHandler(const char* command, const char* arguments);
|
||||||
|
int32_t CvarDefaultCommandHandler(const char* command, const char* arguments);
|
||||||
|
int32_t CvarListCommandHandler(const char* command, const char* arguments);
|
||||||
|
int32_t CvarCommandHandler(const char* command, const char* arguments);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,9 +1,17 @@
|
|||||||
#include "console/Client.hpp"
|
#include "console/Client.hpp"
|
||||||
|
#include "console/Command.hpp"
|
||||||
|
#include "console/CVar.hpp"
|
||||||
|
|
||||||
void ConsoleInitializeClientCommand() {
|
void ConsoleInitializeClientCommand() {
|
||||||
// TODO
|
ConsoleCommandInitialize();
|
||||||
|
ConsoleInitializeCommonCommand();
|
||||||
|
ConsoleInitializeDebugCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleInitializeClientCVar(const char* a1) {
|
void ConsoleInitializeClientCVar(const char* a1) {
|
||||||
// TODO
|
CVar::Initialize(a1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ConsoleLoadClientCVar(const char* a1) {
|
||||||
|
return CVar::Load(a1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,12 @@
|
|||||||
#ifndef CONSOLE_CLIENT_HPP
|
#ifndef CONSOLE_CLIENT_HPP
|
||||||
#define CONSOLE_CLIENT_HPP
|
#define CONSOLE_CLIENT_HPP
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
void ConsoleInitializeClientCommand();
|
void ConsoleInitializeClientCommand();
|
||||||
|
|
||||||
void ConsoleInitializeClientCVar(const char* a1);
|
void ConsoleInitializeClientCVar(const char* a1);
|
||||||
|
|
||||||
|
int32_t ConsoleLoadClientCVar(const char* a1);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,5 +1,11 @@
|
|||||||
#include "console/Command.hpp"
|
#include "console/Command.hpp"
|
||||||
|
#include "console/Line.hpp"
|
||||||
|
|
||||||
#include <storm/Error.hpp>
|
#include <storm/Error.hpp>
|
||||||
|
#include <storm/Unicode.hpp>
|
||||||
|
|
||||||
|
#include <cctype>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
int32_t ValidateFileName(const char* filename) {
|
int32_t ValidateFileName(const char* filename) {
|
||||||
if (SStrStr(filename, "..") || SStrStr(filename, "\\")) {
|
if (SStrStr(filename, "..") || SStrStr(filename, "\\")) {
|
||||||
@ -20,8 +26,49 @@ int32_t ValidateFileName(const char* filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TSHashTable<CONSOLECOMMAND, HASHKEY_STRI> g_consoleCommandHash;
|
TSHashTable<CONSOLECOMMAND, HASHKEY_STRI> g_consoleCommandHash;
|
||||||
char g_commandHistory[HISTORY_DEPTH][CMD_BUFFER_SIZE];
|
char g_commandHistory[CONSOLE_HISTORY_DEPTH][CONSOLE_CMD_BUFFER_SIZE];
|
||||||
uint32_t g_commandHistoryIndex;
|
uint32_t g_commandHistoryIndex;
|
||||||
|
char g_ExecBuffer[CONSOLE_EXEC_BUFFER_SIZE] = {0};
|
||||||
|
EXECMODE g_ExecCreateMode = EM_NOTACTIVE;
|
||||||
|
|
||||||
|
int32_t AddLineToExecFile(const char* currentLine) {
|
||||||
|
char stringToWrite[STORM_MAX_PATH];
|
||||||
|
|
||||||
|
if (g_ExecCreateMode != EM_PROMPTOVERWRITE) {
|
||||||
|
if (!SStrCmpI(currentLine, "end", STORM_MAX_STR)) {
|
||||||
|
if (g_ExecCreateMode != EM_APPEND) {
|
||||||
|
g_ExecCreateMode = EM_WRITEFILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SStrPrintf(stringToWrite, sizeof(stringToWrite), "%s\n", currentLine);
|
||||||
|
|
||||||
|
if (((sizeof(g_ExecBuffer)-1) - SStrLen(g_ExecBuffer)) != SStrLen(stringToWrite)){
|
||||||
|
SStrPack(g_ExecBuffer, stringToWrite, sizeof(g_ExecBuffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentLine[0] == 'n') {
|
||||||
|
ConsoleWrite("Canceled File Creation", ECHO_COLOR);
|
||||||
|
g_ExecCreateMode = EM_NOTACTIVE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentLine[0] != 'y') {
|
||||||
|
ConsoleWrite("You must type 'y' to confirm overwrite. Process aborted!", ERROR_COLOR);
|
||||||
|
g_ExecCreateMode = EM_NOTACTIVE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ConsoleCommandDestroy() {
|
void ConsoleCommandDestroy() {
|
||||||
g_consoleCommandHash.Clear();
|
g_consoleCommandHash.Clear();
|
||||||
@ -29,33 +76,33 @@ void ConsoleCommandDestroy() {
|
|||||||
|
|
||||||
char* ConsoleCommandHistory(uint32_t index) {
|
char* ConsoleCommandHistory(uint32_t index) {
|
||||||
// Return a pointer to the buffer at the specified index
|
// Return a pointer to the buffer at the specified index
|
||||||
return g_commandHistory[((g_commandHistoryIndex + (HISTORY_DEPTH - 1) - index) & (HISTORY_DEPTH - 1))];
|
return g_commandHistory[((g_commandHistoryIndex + (CONSOLE_HISTORY_DEPTH - 1) - index) & (CONSOLE_HISTORY_DEPTH - 1))];
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddToHistory(const char* command) {
|
||||||
|
SStrCopy(g_commandHistory[g_commandHistoryIndex], command, CONSOLE_LINE_LENGTH);
|
||||||
|
g_commandHistoryIndex = (g_commandHistoryIndex + 1) & (CONSOLE_HISTORY_DEPTH-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ConsoleCommandHistoryDepth() {
|
uint32_t ConsoleCommandHistoryDepth() {
|
||||||
return HISTORY_DEPTH;
|
return CONSOLE_HISTORY_DEPTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleCommandInitialize() {
|
int32_t ConsoleCommandRegister(const char* command, COMMANDHANDLER handler, CATEGORY category, const char* helpText) {
|
||||||
ConsoleCommandRegister("help", ConsoleCommand_Help, CONSOLE, "Provides help information about a command.");
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t ConsoleCommandRegister(const char* command, int32_t (*handler)(const char*, const char*), CATEGORY category, const char* helpText) {
|
|
||||||
STORM_ASSERT(command);
|
STORM_ASSERT(command);
|
||||||
STORM_ASSERT(handler);
|
STORM_ASSERT(handler);
|
||||||
|
|
||||||
if (SStrLen(command) > (MAX_CMD_LENGTH - 1) || g_consoleCommandHash.Ptr(command)) {
|
if (SStrLen(command) > (CONSOLE_MAX_CMD_LENGTH - 1) || g_consoleCommandHash.Ptr(command)) {
|
||||||
// The command name exceeds MAX_CMD_LENGTH, minus the null terminator
|
// The command name exceeds CONSOLE_MAX_CMD_LENGTH, minus the null terminator
|
||||||
// or it has already been registered
|
// or it has already been registered
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the new command
|
// Register the new command
|
||||||
auto commandPtr = g_consoleCommandHash.New(command, 0, 0);
|
auto commandPtr = g_consoleCommandHash.New(command, 0, 0);
|
||||||
commandPtr->command = command;
|
commandPtr->m_handler = handler;
|
||||||
commandPtr->handler = handler;
|
commandPtr->m_helpText = helpText;
|
||||||
commandPtr->helpText = helpText;
|
commandPtr->m_category = category;
|
||||||
commandPtr->category = category;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -69,18 +116,162 @@ void ConsoleCommandUnregister(const char* command) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ConsoleCommand_Help(const char* command, const char* arguments) {
|
CONSOLECOMMAND* ParseCommand(const char* commandLine, const char** command, char* arguments, size_t argsize) {
|
||||||
// TODO
|
STORM_ASSERT(commandLine);
|
||||||
return 0;
|
|
||||||
|
auto string = commandLine;
|
||||||
|
|
||||||
|
static char cmd[32] = { 0 };
|
||||||
|
|
||||||
|
auto cmdptr = &cmd[0];
|
||||||
|
|
||||||
|
int32_t end = CONSOLE_MAX_CMD_LENGTH;
|
||||||
|
int32_t i = 0;
|
||||||
|
|
||||||
|
while (i < end) {
|
||||||
|
int32_t chars;
|
||||||
|
|
||||||
|
auto code = SUniSGetUTF8(reinterpret_cast<const uint8_t*>(string), &chars);
|
||||||
|
|
||||||
|
if (code == -1 || code == ' ' || chars > CONSOLE_MAX_CMD_LENGTH) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chars) {
|
||||||
|
for (size_t c = 0; c < chars; c++) {
|
||||||
|
*cmdptr = *string;
|
||||||
|
cmdptr += chars;
|
||||||
|
string += chars;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i += chars;
|
||||||
|
}
|
||||||
|
|
||||||
|
*cmdptr = '\0';
|
||||||
|
|
||||||
|
if (command) {
|
||||||
|
*command = cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto argptr = arguments;
|
||||||
|
|
||||||
|
if (arguments) {
|
||||||
|
int32_t chars;
|
||||||
|
|
||||||
|
auto code = SUniSGetUTF8(reinterpret_cast<const uint8_t*>(string), &chars);
|
||||||
|
|
||||||
|
// Discard space
|
||||||
|
while (code != -1 && code == ' ') {
|
||||||
|
string += chars;
|
||||||
|
code = SUniSGetUTF8(reinterpret_cast<const uint8_t*>(string), &chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
SStrCopy(argptr, string, argsize);
|
||||||
|
|
||||||
|
auto len = SStrLen(argptr);
|
||||||
|
|
||||||
|
while (len > 0 && (argptr[len-1] == ' ')) {
|
||||||
|
len--;
|
||||||
|
argptr[len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_consoleCommandHash.Ptr(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ConsoleCommand_Quit(const char* command, const char* arguments) {
|
void MakeCommandCurrent(CONSOLELINE* lineptr, char* command) {
|
||||||
// TODO
|
auto len = lineptr->inputstart;
|
||||||
// ConsolePostClose()
|
lineptr->inputpos = len;
|
||||||
return 0;
|
lineptr->chars = len;
|
||||||
|
lineptr->buffer[len] = '\0';
|
||||||
|
|
||||||
|
len = SStrLen(command);
|
||||||
|
ReserveInputSpace(lineptr, len);
|
||||||
|
|
||||||
|
SStrCopy(lineptr->buffer + lineptr->inputpos, command, STORM_MAX_STR);
|
||||||
|
|
||||||
|
len = lineptr->inputpos + len;
|
||||||
|
lineptr->inputpos = len;
|
||||||
|
lineptr->chars = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ConsoleCommand_Ver(const char* command, const char* arguments) {
|
void ConsoleCommandExecute(char* commandLine, int32_t addToHistory) {
|
||||||
// TODO
|
auto em = g_ExecCreateMode;
|
||||||
return 0;
|
|
||||||
|
if (em == EM_RECORDING || em == EM_PROMPTOVERWRITE || em == EM_APPEND) {
|
||||||
|
AddLineToExecFile(commandLine);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto history = ConsoleCommandHistory(0);
|
||||||
|
|
||||||
|
if (addToHistory && (history == nullptr || SStrCmp(commandLine, history, STORM_MAX_STR))) {
|
||||||
|
AddToHistory(commandLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* command = nullptr;
|
||||||
|
auto arguments = reinterpret_cast<char*>(SMemAlloc(CONSOLE_CMD_BUFFER_SIZE, __FILE__, __LINE__, 0));
|
||||||
|
|
||||||
|
auto cmd = ParseCommand(commandLine, &command, arguments, CONSOLE_CMD_BUFFER_SIZE);
|
||||||
|
|
||||||
|
if (cmd) {
|
||||||
|
cmd->m_handler(command, arguments);
|
||||||
|
} else {
|
||||||
|
ConsoleWrite("Unknown command", DEFAULT_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arguments) {
|
||||||
|
SMemFree(arguments, __FILE__, __LINE__, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ConsoleCommandList s_consoleSpecificCommands[] = {
|
||||||
|
{ "fontcolor", ConsoleCommand_FontColor, "[ColorClassName] [Red 0-255] [Green 0-255] [Blue 0-255]" },
|
||||||
|
{ "bgcolor", ConsoleCommand_BackGroundColor, "[alpha 0-255] [Red 0-255] [Green 0-255] [Blue 0-255]" },
|
||||||
|
{ "highlightcolor", ConsoleCommand_HighLightColor, "[alpha 0-255] [Red 0-255] [Green 0-255] [Blue 0-255]" },
|
||||||
|
{ "fontsize", ConsoleCommand_FontSize, "[15-50] arbitrary font size" },
|
||||||
|
{ "font", ConsoleCommand_Font, "[fontname] make sure to use the .ttf file name" },
|
||||||
|
{ "consolelines", ConsoleCommand_BufferSize, "[number] number of lines to show in the console" },
|
||||||
|
{ "clear", ConsoleCommand_ClearConsole, "Clears the console buffer" },
|
||||||
|
{ "proportionaltext", ConsoleCommand_Proportional, "Toggles fixed-width text characters" },
|
||||||
|
{ "spacing", ConsoleCommand_CharSpacing, "[float] specifies inter-character spacing, in pixels" },
|
||||||
|
{ "settings", ConsoleCommand_CurrentSettings, "Shows current font and console settings" },
|
||||||
|
{ "default", ConsoleCommand_DefaultSettings, "Resets all the font and console settings" },
|
||||||
|
{ "closeconsole", ConsoleCommand_CloseConsole, "Closes the Console window" },
|
||||||
|
{ "repeat", ConsoleCommand_RepeatHandler, "Repeats a command" },
|
||||||
|
{ "AppendLogToFile", ConsoleCommand_AppendLogToFile, "[filename = ConsoleLogs/Log<Timestamp>.txt] [numLines = all]" }
|
||||||
|
};
|
||||||
|
|
||||||
|
static ConsoleCommandList s_commonCommands[] = {
|
||||||
|
{ "quit", ConsoleCommand_Quit, nullptr },
|
||||||
|
{ "ver", ConsoleCommand_Ver, nullptr },
|
||||||
|
{ "setmap", ConsoleCommand_SetMap, nullptr }
|
||||||
|
};
|
||||||
|
|
||||||
|
void RegisterConsoleCommandList(CATEGORY category, ConsoleCommandList list[], size_t count) {
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
while (i < count) {
|
||||||
|
auto& cmd = list[i];
|
||||||
|
ConsoleCommandRegister(cmd.m_command, cmd.m_handler, category, cmd.m_helpText);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleInitializeScreenCommand() {
|
||||||
|
CONSOLE_REGISTER_LIST(CONSOLE, s_consoleSpecificCommands);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleCommandInitialize() {
|
||||||
|
ConsoleCommandRegister("help", ConsoleCommand_Help, CONSOLE, "Provides help information about a command.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleInitializeCommonCommand() {
|
||||||
|
CONSOLE_REGISTER_LIST(DEFAULT, s_commonCommands);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleInitializeDebugCommand() {
|
||||||
|
// TODO
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,40 +1,23 @@
|
|||||||
#ifndef CONSOLE_COMMAND_HPP
|
#ifndef CONSOLE_COMMAND_HPP
|
||||||
#define CONSOLE_COMMAND_HPP
|
#define CONSOLE_COMMAND_HPP
|
||||||
|
|
||||||
|
#include "console/Types.hpp"
|
||||||
|
|
||||||
#include <storm/Hash.hpp>
|
#include <storm/Hash.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#define EXEC_BUFFER_SIZE 8192
|
#define CONSOLE_REGISTER_LIST(category, list) RegisterConsoleCommandList(category, list, sizeof(list) / sizeof(ConsoleCommandList))
|
||||||
#define CMD_BUFFER_SIZE 1024
|
|
||||||
#define MAX_CMD_LENGTH 64
|
|
||||||
#define HISTORY_DEPTH 32
|
|
||||||
#define NOHELP nullptr
|
|
||||||
|
|
||||||
enum CATEGORY {
|
#define CONSOLE_EXEC_BUFFER_SIZE 8192
|
||||||
DEBUG,
|
#define CONSOLE_CMD_BUFFER_SIZE 1024
|
||||||
GRAPHICS,
|
#define CONSOLE_MAX_CMD_LENGTH 64
|
||||||
CONSOLE,
|
#define CONSOLE_HISTORY_DEPTH 32
|
||||||
COMBAT,
|
#define CONSOLE_NOHELP nullptr
|
||||||
GAME,
|
|
||||||
DEFAULT,
|
|
||||||
NET,
|
|
||||||
SOUND,
|
|
||||||
GM,
|
|
||||||
NONE,
|
|
||||||
LAST
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CONSOLECOMMAND : TSHashObject<CONSOLECOMMAND, HASHKEY_STRI> {
|
|
||||||
const char* command;
|
|
||||||
int32_t (*handler)(const char*, const char*);
|
|
||||||
const char* helpText;
|
|
||||||
CATEGORY category;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern TSHashTable<CONSOLECOMMAND, HASHKEY_STRI> g_consoleCommandHash;
|
extern TSHashTable<CONSOLECOMMAND, HASHKEY_STRI> g_consoleCommandHash;
|
||||||
extern char g_commandHistory[HISTORY_DEPTH][CMD_BUFFER_SIZE];
|
extern char g_commandHistory[CONSOLE_HISTORY_DEPTH][CONSOLE_CMD_BUFFER_SIZE];
|
||||||
extern uint32_t g_commandHistoryIndex;
|
extern uint32_t g_commandHistoryIndex;
|
||||||
extern char g_ExecBuffer[EXEC_BUFFER_SIZE];
|
extern char g_ExecBuffer[CONSOLE_EXEC_BUFFER_SIZE];
|
||||||
|
|
||||||
void ConsoleCommandDestroy();
|
void ConsoleCommandDestroy();
|
||||||
|
|
||||||
@ -42,16 +25,44 @@ char* ConsoleCommandHistory(uint32_t index);
|
|||||||
|
|
||||||
uint32_t ConsoleCommandHistoryDepth();
|
uint32_t ConsoleCommandHistoryDepth();
|
||||||
|
|
||||||
|
int32_t ConsoleCommandRegister(const char* command, COMMANDHANDLER handler, CATEGORY category, const char* helpText);
|
||||||
|
|
||||||
void ConsoleCommandInitialize();
|
void ConsoleCommandInitialize();
|
||||||
|
|
||||||
int32_t ConsoleCommandRegister(const char* command, int32_t (*handler)(const char*, const char*), CATEGORY category, const char* helpText);
|
void ConsoleInitializeCommonCommand();
|
||||||
|
|
||||||
|
void ConsoleInitializeDebugCommand();
|
||||||
|
|
||||||
|
void ConsoleInitializeScreenCommand();
|
||||||
|
|
||||||
|
void RegisterConsoleCommandList(CATEGORY category, ConsoleCommandList list[], size_t count);
|
||||||
|
|
||||||
void ConsoleCommandUnregister(const char* command);
|
void ConsoleCommandUnregister(const char* command);
|
||||||
|
|
||||||
int32_t ConsoleCommand_Help(const char* command, const char* arguments);
|
void ConsoleCommandExecute(char* commandLine, int32_t addToHistory);
|
||||||
|
|
||||||
|
void MakeCommandCurrent(CONSOLELINE* lineptr, char* command);
|
||||||
|
|
||||||
|
// Commands
|
||||||
|
|
||||||
int32_t ConsoleCommand_Quit(const char* command, const char* arguments);
|
int32_t ConsoleCommand_Quit(const char* command, const char* arguments);
|
||||||
|
|
||||||
int32_t ConsoleCommand_Ver(const char* command, const char* arguments);
|
int32_t ConsoleCommand_Ver(const char* command, const char* arguments);
|
||||||
|
int32_t ConsoleCommand_SetMap(const char* command, const char* arguments);
|
||||||
|
|
||||||
|
int32_t ConsoleCommand_Help(const char* command, const char* arguments);
|
||||||
|
int32_t ConsoleCommand_FontColor(const char* command, const char* arguments);
|
||||||
|
int32_t ConsoleCommand_BackGroundColor(const char* command, const char* arguments);
|
||||||
|
int32_t ConsoleCommand_HighLightColor(const char* command, const char* arguments);
|
||||||
|
int32_t ConsoleCommand_FontSize(const char* command, const char* arguments);
|
||||||
|
int32_t ConsoleCommand_Font(const char* command, const char* arguments);
|
||||||
|
int32_t ConsoleCommand_BufferSize(const char* command, const char* arguments);
|
||||||
|
int32_t ConsoleCommand_ClearConsole(const char* command, const char* arguments);
|
||||||
|
int32_t ConsoleCommand_Proportional(const char* command, const char* arguments);
|
||||||
|
int32_t ConsoleCommand_CharSpacing(const char* command, const char* arguments);
|
||||||
|
int32_t ConsoleCommand_CurrentSettings(const char* command, const char* arguments);
|
||||||
|
int32_t ConsoleCommand_DefaultSettings(const char* command, const char* arguments);
|
||||||
|
int32_t ConsoleCommand_CloseConsole(const char* command, const char* arguments);
|
||||||
|
int32_t ConsoleCommand_RepeatHandler(const char* command, const char* arguments);
|
||||||
|
int32_t ConsoleCommand_AppendLogToFile(const char* command, const char* arguments);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,8 +1,13 @@
|
|||||||
#include "console/Console.hpp"
|
#include "console/Console.hpp"
|
||||||
|
#include "event/Context.hpp"
|
||||||
|
#include "event/Event.hpp"
|
||||||
|
|
||||||
static int32_t s_active;
|
static int32_t s_active;
|
||||||
static int32_t s_consoleAccessEnabled;
|
static int32_t s_consoleAccessEnabled;
|
||||||
static KEY s_consoleKey = KEY_TILDE;
|
static KEY s_consoleKey = KEY_TILDE;
|
||||||
|
static float s_consoleLines = 10.0f;
|
||||||
|
static float s_fontHeight = 0.02f;
|
||||||
|
static float s_consoleHeight = s_consoleLines * s_fontHeight;
|
||||||
static CONSOLERESIZESTATE s_consoleResizeState = CS_NONE;
|
static CONSOLERESIZESTATE s_consoleResizeState = CS_NONE;
|
||||||
|
|
||||||
int32_t ConsoleAccessGetEnabled() {
|
int32_t ConsoleAccessGetEnabled() {
|
||||||
@ -17,6 +22,18 @@ int32_t ConsoleGetActive() {
|
|||||||
return s_active;
|
return s_active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float ConsoleGetFontHeight() {
|
||||||
|
return s_fontHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
float ConsoleGetHeight() {
|
||||||
|
return s_consoleHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
float ConsoleGetLines() {
|
||||||
|
return s_consoleLines;
|
||||||
|
}
|
||||||
|
|
||||||
KEY ConsoleGetHotKey() {
|
KEY ConsoleGetHotKey() {
|
||||||
return s_consoleKey;
|
return s_consoleKey;
|
||||||
}
|
}
|
||||||
@ -36,3 +53,11 @@ void ConsoleSetHotKey(KEY hotkey) {
|
|||||||
void ConsoleSetResizeState(CONSOLERESIZESTATE state) {
|
void ConsoleSetResizeState(CONSOLERESIZESTATE state) {
|
||||||
s_consoleResizeState = state;
|
s_consoleResizeState = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConsoleSetHeight(float height) {
|
||||||
|
s_consoleHeight = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsolePostClose() {
|
||||||
|
EventPostCloseEx(EventGetCurrentContext());
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#ifndef CONSOLE_CONSOLE_HPP
|
#ifndef CONSOLE_CONSOLE_HPP
|
||||||
#define CONSOLE_CONSOLE_HPP
|
#define CONSOLE_CONSOLE_HPP
|
||||||
|
|
||||||
|
#include "console/Line.hpp"
|
||||||
#include "console/Types.hpp"
|
#include "console/Types.hpp"
|
||||||
#include "event/Types.hpp"
|
#include "event/Types.hpp"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@ -11,6 +12,12 @@ void ConsoleAccessSetEnabled(int32_t enable);
|
|||||||
|
|
||||||
int32_t ConsoleGetActive();
|
int32_t ConsoleGetActive();
|
||||||
|
|
||||||
|
float ConsoleGetFontHeight();
|
||||||
|
|
||||||
|
float ConsoleGetLines();
|
||||||
|
|
||||||
|
float ConsoleGetHeight();
|
||||||
|
|
||||||
KEY ConsoleGetHotKey();
|
KEY ConsoleGetHotKey();
|
||||||
|
|
||||||
CONSOLERESIZESTATE ConsoleGetResizeState();
|
CONSOLERESIZESTATE ConsoleGetResizeState();
|
||||||
@ -19,6 +26,10 @@ void ConsoleSetActive(int32_t active);
|
|||||||
|
|
||||||
void ConsoleSetHotKey(KEY hotkey);
|
void ConsoleSetHotKey(KEY hotkey);
|
||||||
|
|
||||||
|
void ConsoleSetHeight(float height);
|
||||||
|
|
||||||
void ConsoleSetResizeState(CONSOLERESIZESTATE state);
|
void ConsoleSetResizeState(CONSOLERESIZESTATE state);
|
||||||
|
|
||||||
|
void ConsolePostClose();
|
||||||
|
|
||||||
#endif // ifndef CONSOLE_CONSOLE_HPP
|
#endif // ifndef CONSOLE_CONSOLE_HPP
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#include "console/Device.hpp"
|
#include "console/Device.hpp"
|
||||||
|
#include "client/CmdLine.hpp"
|
||||||
#include "client/Gui.hpp"
|
#include "client/Gui.hpp"
|
||||||
#include "console/Console.hpp"
|
#include "console/Console.hpp"
|
||||||
#include "console/CVar.hpp"
|
#include "console/CVar.hpp"
|
||||||
@ -10,17 +11,49 @@ CVar* s_cvGxMaximize;
|
|||||||
CVar* s_cvGxResolution;
|
CVar* s_cvGxResolution;
|
||||||
CVar* s_cvGxWidescreen;
|
CVar* s_cvGxWidescreen;
|
||||||
CVar* s_cvGxWindow;
|
CVar* s_cvGxWindow;
|
||||||
|
CVar* s_cvGxApi;
|
||||||
DefaultSettings s_defaults;
|
DefaultSettings s_defaults;
|
||||||
bool s_hwDetect;
|
bool s_hwDetect;
|
||||||
bool s_hwChanged;
|
bool s_hwChanged;
|
||||||
CGxFormat s_requestedFormat;
|
CGxFormat s_requestedFormat;
|
||||||
|
|
||||||
|
const char* g_gxApiNames[GxApis_Last] = {
|
||||||
|
"OpenGL", // GxApi_OpenGl
|
||||||
|
"D3D9", // GxApi_D3d9
|
||||||
|
"D3D9Ex", // GxApi_D3d9Ex
|
||||||
|
"D3D10", // GxApi_D3d10
|
||||||
|
"D3D11", // GxApi_D3d11
|
||||||
|
"GLL", // GxApi_GLL
|
||||||
|
"GLSDL" // GxApi_GLSDL
|
||||||
|
};
|
||||||
|
|
||||||
|
EGxApi g_gxApiSupported[] = {
|
||||||
|
#if defined(WHOA_SYSTEM_WIN)
|
||||||
|
GxApi_D3d9,
|
||||||
|
GxApi_GLSDL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WHOA_SYSTEM_MAC)
|
||||||
|
GxApi_GLL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WHOA_SYSTEM_LINUX)
|
||||||
|
GxApi_GLSDL
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t g_numGxApiSupported = sizeof(g_gxApiSupported) / sizeof(EGxApi);
|
||||||
|
|
||||||
bool CVGxMaximizeCallback(CVar*, const char*, const char*, void*) {
|
bool CVGxMaximizeCallback(CVar*, const char*, const char*, void*) {
|
||||||
// TODO
|
// TODO
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CVGxResolutionCallback(CVar*, const char*, const char*, void*) {
|
bool CVGxResolutionCallback(CVar*, const char*, const char*, void*) {
|
||||||
|
// static C2iVector legalSizes[] = {
|
||||||
|
// {}
|
||||||
|
// }
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -30,6 +63,49 @@ bool CVGxWindowCallback(CVar*, const char*, const char*, void*) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CVGxApiCallback(CVar* h, const char* oldValue, const char* newValue, void* arg) {
|
||||||
|
for (size_t api = 0; api < g_numGxApiSupported; api++) {
|
||||||
|
auto apiString = g_gxApiNames[g_gxApiSupported[api]];
|
||||||
|
if (SStrCmpI(newValue, apiString, STORM_MAX_STR) == 0) {
|
||||||
|
// New gxApi is supported, pass
|
||||||
|
ConsoleWrite("GxApi set pending gxRestart", DEFAULT_COLOR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Supported gxApi not supplied, show available apis
|
||||||
|
constexpr size_t msgsize = 1024;
|
||||||
|
char msg[msgsize] = {0};
|
||||||
|
SStrPack(msg, "unsupported api, must be one of ", msgsize);
|
||||||
|
|
||||||
|
for (size_t api = 0; api < g_numGxApiSupported; api++) {
|
||||||
|
if (api > 0) {
|
||||||
|
SStrPack(msg, ", ", msgsize);
|
||||||
|
}
|
||||||
|
auto apiString = g_gxApiNames[g_gxApiSupported[api]];
|
||||||
|
SStrPack(msg, "'", msgsize);
|
||||||
|
SStrPack(msg, apiString, msgsize);
|
||||||
|
SStrPack(msg, "'", msgsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsoleWrite(msg, DEFAULT_COLOR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
EGxApi GxApiDefault() {
|
||||||
|
#if defined(WHOA_SYSTEM_WIN)
|
||||||
|
return GxApi_D3d9;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WHOA_SYSTEM_MAC)
|
||||||
|
return GxApi_GLL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WHOA_SYSTEM_LINUX)
|
||||||
|
return GxApi_GLSDL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void RegisterGxCVars() {
|
void RegisterGxCVars() {
|
||||||
auto& format = s_defaults.format;
|
auto& format = s_defaults.format;
|
||||||
|
|
||||||
@ -92,6 +168,19 @@ void RegisterGxCVars() {
|
|||||||
// TODO s_cvGxRefresh
|
// TODO s_cvGxRefresh
|
||||||
// TODO s_cvGxTripleBuffer
|
// TODO s_cvGxTripleBuffer
|
||||||
// TODO s_cvGxApi
|
// TODO s_cvGxApi
|
||||||
|
|
||||||
|
s_cvGxApi = CVar::Register(
|
||||||
|
"gxApi",
|
||||||
|
"graphics api",
|
||||||
|
0x1 | 0x2,
|
||||||
|
g_gxApiNames[GxApiDefault()],
|
||||||
|
CVGxApiCallback,
|
||||||
|
1,
|
||||||
|
false,
|
||||||
|
nullptr,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
// TODO s_cvGxVSync
|
// TODO s_cvGxVSync
|
||||||
// TODO s_cvGxAspect
|
// TODO s_cvGxAspect
|
||||||
// TODO s_cvGxCursor
|
// TODO s_cvGxCursor
|
||||||
@ -148,8 +237,7 @@ void ConsoleDeviceInitialize(const char* title) {
|
|||||||
// TODO proper logic
|
// TODO proper logic
|
||||||
s_hwDetect = true;
|
s_hwDetect = true;
|
||||||
|
|
||||||
// TODO ConsoleAccessSetEnabled(CmdLineGetBool(35));
|
ConsoleAccessSetEnabled(CmdLineGetBool(WOWCMD_CONSOLE));
|
||||||
ConsoleAccessSetEnabled(1);
|
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
|
||||||
@ -190,13 +278,28 @@ void ConsoleDeviceInitialize(const char* title) {
|
|||||||
CGxFormat format;
|
CGxFormat format;
|
||||||
memcpy(&format, &s_requestedFormat, sizeof(s_requestedFormat));
|
memcpy(&format, &s_requestedFormat, sizeof(s_requestedFormat));
|
||||||
|
|
||||||
// TODO proper api selection
|
// Select gxApi based on user CVars and command-line parameters
|
||||||
EGxApi api = GxApi_OpenGl;
|
EGxApi api = GxApiDefault();
|
||||||
#if defined(WHOA_SYSTEM_WIN)
|
|
||||||
api = GxApi_D3d9;
|
auto gxApiName = s_cvGxApi->GetString();
|
||||||
#elif defined(WHOA_SYSTEM_MAC)
|
|
||||||
api = GxApi_GLL;
|
auto gxOverride = CmdLineGetString(WOWCMD_GX_OVERRIDE);
|
||||||
#endif
|
if (*gxOverride != '\0') {
|
||||||
|
gxApiName = gxOverride;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanitize chosen gxApi against list of supported gxApis
|
||||||
|
for (size_t i = 0; i < g_numGxApiSupported; i++) {
|
||||||
|
EGxApi supportedApi = g_gxApiSupported[i];
|
||||||
|
if (SStrCmpI(gxApiName, g_gxApiNames[supportedApi], STORM_MAX_STR) == 0) {
|
||||||
|
api = supportedApi;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set internally (CVar value reflects the current gxApi at launch),
|
||||||
|
// this will not Set() as CVar gxApi is latched
|
||||||
|
s_cvGxApi->InternalSet(g_gxApiNames[api], true, false, false, true);
|
||||||
|
|
||||||
CGxDevice* device = GxDevCreate(api, OsWindowProc, format);
|
CGxDevice* device = GxDevCreate(api, OsWindowProc, format);
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,34 @@
|
|||||||
#include "console/Handlers.hpp"
|
#include "console/Handlers.hpp"
|
||||||
|
#include "console/Line.hpp"
|
||||||
#include "console/Console.hpp"
|
#include "console/Console.hpp"
|
||||||
|
#include "console/Command.hpp"
|
||||||
#include "console/Screen.hpp"
|
#include "console/Screen.hpp"
|
||||||
#include "event/Event.hpp"
|
#include "event/Event.hpp"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
static int32_t s_historyIndex = 0;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
int32_t OnChar(const EVENT_DATA_CHAR* data, void* param) {
|
int32_t OnChar(const EVENT_DATA_CHAR* data, void* param) {
|
||||||
// TODO
|
char character[2];
|
||||||
|
|
||||||
|
if (ConsoleAccessGetEnabled() && EventIsKeyDown(ConsoleGetHotKey())) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ConsoleGetActive()) {
|
||||||
|
character[0] = char(data->ch);
|
||||||
|
character[1] = 0;
|
||||||
|
|
||||||
|
PasteInInputLine(character);
|
||||||
|
ResetHighlight();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SUniSPutUTF8(data->ch, character);
|
||||||
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +48,7 @@ int32_t OnKeyDown(const EVENT_DATA_KEY* data, void* param) {
|
|||||||
|
|
||||||
// Reset the highlight when toggled off
|
// Reset the highlight when toggled off
|
||||||
if (!ConsoleGetActive()) {
|
if (!ConsoleGetActive()) {
|
||||||
// TODO ResetHighlight();
|
ResetHighlight();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -37,12 +58,111 @@ int32_t OnKeyDown(const EVENT_DATA_KEY* data, void* param) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto anyControl = (1 << KEY_LCONTROL) | (1 << KEY_RCONTROL);
|
||||||
|
|
||||||
|
auto line = GetInputLine();
|
||||||
|
|
||||||
|
switch (data->key) {
|
||||||
|
case KEY_ESCAPE:
|
||||||
|
if (line->inputpos < line->inputstart || line->inputpos == line->inputstart) {
|
||||||
|
ConsoleSetActive(0);
|
||||||
|
} else {
|
||||||
|
line->inputpos = line->inputstart;
|
||||||
|
line->chars = line->inputstart;
|
||||||
|
line->buffer[line->inputstart] = '\0';
|
||||||
|
SetInputString(line->buffer);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_PAGEUP:
|
||||||
|
MoveLinePtr(1, data->metaKeyState);
|
||||||
|
break;
|
||||||
|
case KEY_PAGEDOWN:
|
||||||
|
MoveLinePtr(0, data->metaKeyState);
|
||||||
|
break;
|
||||||
|
case KEY_ENTER:
|
||||||
|
if (line->inputstart <= line->inputpos && line->inputpos != line->inputstart) {
|
||||||
|
line->inputpos = 0;
|
||||||
|
GenerateNodeString(line);
|
||||||
|
ConsoleCommandExecute(line->buffer + line->inputstart, 1);
|
||||||
|
s_historyIndex = -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_HOME:
|
||||||
|
break;
|
||||||
|
case KEY_END:
|
||||||
|
break;
|
||||||
|
case KEY_C:
|
||||||
|
if (data->metaKeyState & anyControl) {
|
||||||
|
CutHighlightToClipboard();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_V:
|
||||||
|
if (data->metaKeyState & anyControl) {
|
||||||
|
PasteClipboardToHighlight();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_LEFT:
|
||||||
|
if (line->inputstart <= line->inputpos && line->inputpos != line->inputstart) {
|
||||||
|
line->inputpos--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_RIGHT:
|
||||||
|
if (line->inputpos < line->chars) {
|
||||||
|
line->inputpos++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_BACKSPACE:
|
||||||
|
BackspaceLine(line);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->key != KEY_TAB && data->key != KEY_LSHIFT && data->key != KEY_RSHIFT && data->key != KEY_LALT && data->key != KEY_RALT && !(data->metaKeyState & anyControl)) {
|
||||||
|
// s_completionMode = 0;
|
||||||
|
ResetHighlight();
|
||||||
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t OnKeyDownRepeat(const EVENT_DATA_KEY* data, void* param) {
|
int32_t OnKeyDownRepeat(const EVENT_DATA_KEY* data, void* param) {
|
||||||
// TODO
|
if (data->key == ConsoleGetHotKey() && ConsoleAccessGetEnabled()) {
|
||||||
|
ConsoleSetActive(!ConsoleGetActive());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto anyControl = (1 << KEY_LCONTROL) | (1 << KEY_RCONTROL);
|
||||||
|
|
||||||
|
auto line = GetInputLine();
|
||||||
|
|
||||||
|
switch (data->key) {
|
||||||
|
case KEY_PAGEUP:
|
||||||
|
MoveLinePtr(1, data->metaKeyState);
|
||||||
|
break;
|
||||||
|
case KEY_PAGEDOWN:
|
||||||
|
MoveLinePtr(0, data->metaKeyState);
|
||||||
|
break;
|
||||||
|
case KEY_LEFT:
|
||||||
|
if (line->inputstart <= line->inputpos && line->inputpos != line->inputstart) {
|
||||||
|
line->inputpos--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_RIGHT:
|
||||||
|
if (line->inputpos < line->chars) {
|
||||||
|
line->inputpos++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_BACKSPACE:
|
||||||
|
BackspaceLine(line);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->key != KEY_TAB && data->key != KEY_LSHIFT && data->key != KEY_RSHIFT && data->key != KEY_LALT && data->key != KEY_RALT && !(data->metaKeyState & anyControl)) {
|
||||||
|
// s_completionMode = 0;
|
||||||
|
ResetHighlight();
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,17 +172,79 @@ int32_t OnKeyUp(const EVENT_DATA_KEY* data, void* param) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t OnMouseDown(const EVENT_DATA_MOUSE* data, void* param) {
|
int32_t OnMouseDown(const EVENT_DATA_MOUSE* data, void* param) {
|
||||||
// TODO
|
auto consoleHeight = ConsoleGetHeight();
|
||||||
|
auto fontHeight = ConsoleGetFontHeight();
|
||||||
|
|
||||||
|
if (EventIsKeyDown(ConsoleGetHotKey()) || !ConsoleGetActive() || (1.0f - consoleHeight) > data->y) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
float clickPos = 1.0f - data->y;
|
||||||
|
|
||||||
|
if (clickPos < (std::min(consoleHeight, 1.0f) - (fontHeight * 0.75f)) || clickPos > consoleHeight) {
|
||||||
|
ResetHighlight();
|
||||||
|
|
||||||
|
auto line = GetLineAtMousePosition(data->y);
|
||||||
|
|
||||||
|
if (line) {
|
||||||
|
SetHighlightCopyText(line->buffer);
|
||||||
|
SetHighlightState(HS_HIGHLIGHTING);
|
||||||
|
|
||||||
|
float v7 = 1.0f - (consoleHeight - (fontHeight * 0.75f) - (fontHeight) - ((consoleHeight - clickPos) / fontHeight - 1.0) * fontHeight);
|
||||||
|
|
||||||
|
auto hRect = GetHighlightRect();
|
||||||
|
|
||||||
|
hRect.bottom = v7;
|
||||||
|
hRect.top = v7 - fontHeight;
|
||||||
|
|
||||||
|
SetHighlightStart(v7);
|
||||||
|
SetHighlightEnd(v7);
|
||||||
|
|
||||||
|
UpdateHighlight();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResetHighlightCopyText();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResetHighlight();
|
||||||
|
|
||||||
|
ConsoleSetResizeState(CS_STRETCH);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t OnMouseMove(const EVENT_DATA_MOUSE* data, void* param) {
|
int32_t OnMouseMove(const EVENT_DATA_MOUSE* data, void* param) {
|
||||||
// TODO
|
if (EventIsKeyDown(ConsoleGetHotKey()) || !ConsoleGetActive()) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ConsoleGetResizeState() == CS_STRETCH) {
|
||||||
|
auto newHeight = std::max(1.0f - data->y, ConsoleGetFontHeight());
|
||||||
|
ConsoleSetHeight(newHeight);
|
||||||
|
} else if ((1.0f - ConsoleGetHeight()) > data->y) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetHighlightEnd(data->x);
|
||||||
|
|
||||||
|
if (GetHighlightState() == HS_HIGHLIGHTING) {
|
||||||
|
UpdateHighlight();
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t OnMouseUp(const EVENT_DATA_MOUSE* data, void* param) {
|
int32_t OnMouseUp(const EVENT_DATA_MOUSE* data, void* param) {
|
||||||
// TODO
|
if (EventIsKeyDown(ConsoleGetHotKey()) || !ConsoleGetActive()) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetHighlightState(HS_ENDHIGHLIGHT);
|
||||||
|
ConsoleSetResizeState(CS_NONE);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
248
src/console/Line.cpp
Normal file
248
src/console/Line.cpp
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
|
||||||
|
#include "console/Line.hpp"
|
||||||
|
#include "console/Types.hpp"
|
||||||
|
#include "console/Console.hpp"
|
||||||
|
#include "console/Screen.hpp"
|
||||||
|
#include "gx/Device.hpp"
|
||||||
|
|
||||||
|
#include <storm/List.hpp>
|
||||||
|
#include <storm/thread/SCritSect.hpp>
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
|
|
||||||
|
static SCritSect s_critsect;
|
||||||
|
// In this list:
|
||||||
|
// The head = the input line.
|
||||||
|
// The tail = the oldest line printed.
|
||||||
|
static STORM_LIST(CONSOLELINE) s_linelist;
|
||||||
|
// Pointer to the current line. Determines what region of the console history gets rendered.
|
||||||
|
static CONSOLELINE* s_currlineptr = nullptr;
|
||||||
|
static uint32_t s_NumLines = 0;
|
||||||
|
|
||||||
|
void EnforceMaxLines() {
|
||||||
|
if (s_NumLines <= CONSOLE_LINES_MAX) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pop oldest line off the list
|
||||||
|
auto lineptr = s_linelist.Tail();
|
||||||
|
|
||||||
|
if (lineptr == nullptr) {
|
||||||
|
lineptr = s_currlineptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lineptr == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up oldest line.
|
||||||
|
s_linelist.UnlinkNode(lineptr);
|
||||||
|
s_linelist.DeleteNode(lineptr);
|
||||||
|
|
||||||
|
s_NumLines--;
|
||||||
|
}
|
||||||
|
|
||||||
|
CONSOLELINE* GetInputLine() {
|
||||||
|
auto head = s_linelist.Head();
|
||||||
|
|
||||||
|
// If the list is empty, or the list's head is an entered input-line,
|
||||||
|
// Create a fresh input line, with "> " prefixed before the caret.
|
||||||
|
if (!head || head->inputpos == 0) {
|
||||||
|
auto l = SMemAlloc(sizeof(CONSOLELINE), __FILE__, __LINE__, 0);
|
||||||
|
auto line = new(l) CONSOLELINE();
|
||||||
|
line->buffer = reinterpret_cast<char*>(SMemAlloc(CONSOLE_LINE_PREALLOC, __FILE__, __LINE__, 0));
|
||||||
|
line->charsalloc = CONSOLE_LINE_PREALLOC;
|
||||||
|
|
||||||
|
s_linelist.LinkToHead(line);
|
||||||
|
|
||||||
|
SStrCopy(line->buffer, "> ", line->charsalloc);
|
||||||
|
SetInputString(line->buffer);
|
||||||
|
auto chars = SStrLen(line->buffer);
|
||||||
|
s_NumLines++;
|
||||||
|
line->inputstart = chars;
|
||||||
|
line->inputpos = chars;
|
||||||
|
line->chars = chars;
|
||||||
|
line->colorType = INPUT_COLOR;
|
||||||
|
|
||||||
|
s_currlineptr = line;
|
||||||
|
|
||||||
|
EnforceMaxLines();
|
||||||
|
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
CONSOLELINE* GetLineAtMousePosition(float y) {
|
||||||
|
// Loop through linelist to find line at mouse position
|
||||||
|
int32_t linePos = static_cast<int32_t>((ConsoleGetHeight() - (1.0 - y)) / ConsoleGetFontHeight());
|
||||||
|
|
||||||
|
if (linePos == 1) {
|
||||||
|
return s_linelist.Head();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_currlineptr != s_linelist.Head()) {
|
||||||
|
linePos--;
|
||||||
|
}
|
||||||
|
|
||||||
|
CONSOLELINE* line = s_currlineptr;
|
||||||
|
|
||||||
|
while (linePos > 1) {
|
||||||
|
linePos--;
|
||||||
|
|
||||||
|
if (!line) {
|
||||||
|
line = s_linelist.Head();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
line = line->Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReserveInputSpace(CONSOLELINE* line, size_t len) {
|
||||||
|
size_t newsize = line->chars + len;
|
||||||
|
if (newsize >= line->charsalloc) {
|
||||||
|
while (line->charsalloc <= newsize) {
|
||||||
|
line->charsalloc += CONSOLE_LINE_PREALLOC;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto buffer = reinterpret_cast<char*>(SMemAlloc(line->charsalloc, __FILE__, __LINE__, 0));
|
||||||
|
SStrCopy(buffer, line->buffer, line->charsalloc);
|
||||||
|
SMemFree(line->buffer, __FILE__, __LINE__, 0x0);
|
||||||
|
line->buffer = buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleWrite(const char* str, COLOR_T color) {
|
||||||
|
if (g_theGxDevicePtr == nullptr || str[0] == '\0') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_critsect.Enter();
|
||||||
|
|
||||||
|
auto l = reinterpret_cast<char*>(SMemAlloc(sizeof(CONSOLELINE), __FILE__, __LINE__, 0));
|
||||||
|
auto lineptr = new(l) CONSOLELINE();
|
||||||
|
|
||||||
|
auto head = s_linelist.Head();
|
||||||
|
|
||||||
|
if (head == nullptr || head->inputpos == 0) {
|
||||||
|
// Attach console line to head
|
||||||
|
s_linelist.LinkToHead(lineptr);
|
||||||
|
} else {
|
||||||
|
// Attach console line between head and head-1
|
||||||
|
s_linelist.LinkNode(lineptr, 1, head->Prev());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t len = SStrLen(str) + 1;
|
||||||
|
lineptr->chars = len;
|
||||||
|
lineptr->charsalloc = len;
|
||||||
|
lineptr->buffer = reinterpret_cast<char*>(SMemAlloc(len, __FILE__, __LINE__, 0));
|
||||||
|
lineptr->colorType = color;
|
||||||
|
|
||||||
|
SStrCopy(lineptr->buffer, str, STORM_MAX_STR);
|
||||||
|
|
||||||
|
GenerateNodeString(lineptr);
|
||||||
|
|
||||||
|
s_NumLines++;
|
||||||
|
|
||||||
|
EnforceMaxLines();
|
||||||
|
//
|
||||||
|
|
||||||
|
s_critsect.Leave();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleWriteA(const char* str, COLOR_T color, ...) {
|
||||||
|
char buffer[1024] = {0};
|
||||||
|
|
||||||
|
if (str != nullptr && str[0] != '\0') {
|
||||||
|
va_list list;
|
||||||
|
va_start(list, color);
|
||||||
|
vsnprintf(buffer, sizeof(buffer), str, list);
|
||||||
|
va_end(list);
|
||||||
|
|
||||||
|
ConsoleWrite(buffer, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveLinePtr(int32_t direction, int32_t modifier) {
|
||||||
|
CONSOLELINE* lineptr = s_currlineptr;
|
||||||
|
|
||||||
|
auto anyControl = (1 << KEY_LCONTROL) | (1 << KEY_RCONTROL);
|
||||||
|
|
||||||
|
if (modifier & anyControl) {
|
||||||
|
for (int32_t i = 0; i < 10 && lineptr != nullptr; i++) {
|
||||||
|
CONSOLELINE* next;
|
||||||
|
|
||||||
|
if (direction == 1) {
|
||||||
|
next = lineptr->m_link.Next();
|
||||||
|
} else {
|
||||||
|
next = lineptr->m_link.Prev();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next != nullptr) {
|
||||||
|
lineptr = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// if (s_currlineptr == s_linelist.Head()) {
|
||||||
|
// s_currlineptr = s_currlineptr->Prev();
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (direction == 1) {
|
||||||
|
lineptr = lineptr->m_link.Next();
|
||||||
|
} else {
|
||||||
|
lineptr = lineptr->m_link.Prev();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lineptr) {
|
||||||
|
s_currlineptr = lineptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BackspaceLine(CONSOLELINE* line) {
|
||||||
|
if (line->inputstart <= line->inputpos && line->inputpos != line->inputstart) {
|
||||||
|
if (line->inputpos < line->chars) {
|
||||||
|
memmove(line->buffer + line->inputpos + -1, line->buffer + line->inputpos, (line->chars - line->inputpos) + 1);
|
||||||
|
} else {
|
||||||
|
line->buffer[line->inputpos - 1] = '\0';
|
||||||
|
}
|
||||||
|
line->chars--;
|
||||||
|
line->inputpos--;
|
||||||
|
|
||||||
|
SetInputString(line->buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CONSOLELINE* GetCurrentLine() {
|
||||||
|
return s_currlineptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CONSOLELINE::~CONSOLELINE() {
|
||||||
|
if (this->buffer) {
|
||||||
|
SMemFree(this->buffer, __FILE__, __LINE__, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->fontPointer) {
|
||||||
|
GxuFontDestroyString(this->fontPointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleClear() {
|
||||||
|
s_NumLines = 0;
|
||||||
|
|
||||||
|
auto ptr = s_linelist.Head();
|
||||||
|
|
||||||
|
while (ptr) {
|
||||||
|
s_linelist.UnlinkNode(ptr);
|
||||||
|
s_linelist.DeleteNode(ptr);
|
||||||
|
ptr = s_linelist.Head();
|
||||||
|
}
|
||||||
|
}
|
||||||
30
src/console/Line.hpp
Normal file
30
src/console/Line.hpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef CONSOLE_LINE_HPP
|
||||||
|
#define CONSOLE_LINE_HPP
|
||||||
|
|
||||||
|
#include "console/Types.hpp"
|
||||||
|
|
||||||
|
#include <storm/List.hpp>
|
||||||
|
|
||||||
|
#define CONSOLE_LINES_MAX 256
|
||||||
|
#define CONSOLE_LINE_LENGTH 1024
|
||||||
|
#define CONSOLE_LINE_PREALLOC 16
|
||||||
|
|
||||||
|
void ConsoleWrite(const char* str, COLOR_T color);
|
||||||
|
void ConsoleWriteA(const char* str, COLOR_T color, ...);
|
||||||
|
|
||||||
|
void PasteInInputLine(char* characters);
|
||||||
|
|
||||||
|
void MoveLinePtr(int32_t direction, int32_t modifier);
|
||||||
|
|
||||||
|
void BackspaceLine(CONSOLELINE* line);
|
||||||
|
|
||||||
|
void ReserveInputSpace(CONSOLELINE* line, size_t len);
|
||||||
|
|
||||||
|
CONSOLELINE* GetInputLine();
|
||||||
|
CONSOLELINE* GetCurrentLine();
|
||||||
|
|
||||||
|
CONSOLELINE* GetLineAtMousePosition(float y);
|
||||||
|
|
||||||
|
void ConsoleClear();
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -1,6 +1,8 @@
|
|||||||
#include "console/Screen.hpp"
|
#include "console/Screen.hpp"
|
||||||
#include "console/Console.hpp"
|
#include "console/Console.hpp"
|
||||||
|
#include "console/Command.hpp"
|
||||||
#include "console/Handlers.hpp"
|
#include "console/Handlers.hpp"
|
||||||
|
#include "console/Line.hpp"
|
||||||
#include "console/Types.hpp"
|
#include "console/Types.hpp"
|
||||||
#include "gx/Buffer.hpp"
|
#include "gx/Buffer.hpp"
|
||||||
#include "gx/Coordinate.hpp"
|
#include "gx/Coordinate.hpp"
|
||||||
@ -10,23 +12,34 @@
|
|||||||
#include "gx/Gx.hpp"
|
#include "gx/Gx.hpp"
|
||||||
#include "gx/RenderState.hpp"
|
#include "gx/RenderState.hpp"
|
||||||
#include "gx/Screen.hpp"
|
#include "gx/Screen.hpp"
|
||||||
|
#include <bc/Debug.hpp>
|
||||||
#include <storm/String.hpp>
|
#include <storm/String.hpp>
|
||||||
#include <tempest/Rect.hpp>
|
#include <tempest/Rect.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
static CGxStringBatch* s_batch;
|
static CGxStringBatch* s_batch;
|
||||||
|
static uint32_t s_baseTextFlags = 0x8;
|
||||||
|
static int32_t s_caret = 0;
|
||||||
static float s_caretpixwidth;
|
static float s_caretpixwidth;
|
||||||
static float s_caretpixheight;
|
static float s_caretpixheight;
|
||||||
static float s_consoleLines = 10.0f;
|
static float s_charSpacing = 0.0f;
|
||||||
static float s_fontHeight = 0.02f;
|
static CGxString* s_inputString = nullptr;
|
||||||
static float s_consoleHeight = s_consoleLines * s_fontHeight;
|
|
||||||
static char s_fontName[STORM_MAX_PATH];
|
static char s_fontName[STORM_MAX_PATH];
|
||||||
static int32_t s_highlightState;
|
|
||||||
static HLAYER s_layerBackground;
|
static HLAYER s_layerBackground;
|
||||||
static HLAYER s_layerText;
|
static HLAYER s_layerText;
|
||||||
static RECTF s_rect = { 0.0f, 1.0f, 1.0f, 1.0f };
|
static RECTF s_rect = { 0.0f, 1.0f, 1.0f, 1.0f };
|
||||||
static HTEXTFONT s_textFont;
|
static HTEXTFONT s_textFont;
|
||||||
|
|
||||||
|
static HIGHLIGHTSTATE s_highlightState = HS_NONE;
|
||||||
|
static RECTF s_hRect = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
static float s_highlightHStart = 0.0f;
|
||||||
|
static float s_highlightHEnd = 0.0f;
|
||||||
|
static uint32_t s_highlightLeftCharIndex = 0;
|
||||||
|
static uint32_t s_highlightRightCharIndex = 0;
|
||||||
|
static int32_t s_highlightInput = 0;
|
||||||
|
static char s_copyText[HIGHLIGHT_COPY_SIZE] = { 0 };
|
||||||
|
|
||||||
static CImVector s_colorArray[] = {
|
static CImVector s_colorArray[] = {
|
||||||
{ 0xFF, 0xFF, 0xFF, 0xFF }, // DEFAULT_COLOR
|
{ 0xFF, 0xFF, 0xFF, 0xFF }, // DEFAULT_COLOR
|
||||||
{ 0xFF, 0xFF, 0xFF, 0xFF }, // INPUT_COLOR
|
{ 0xFF, 0xFF, 0xFF, 0xFF }, // INPUT_COLOR
|
||||||
@ -70,7 +83,64 @@ void DrawBackground() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DrawHighLight() {
|
void DrawHighLight() {
|
||||||
// TODO
|
uint16_t indices[] = {
|
||||||
|
0, 1, 2, 3
|
||||||
|
};
|
||||||
|
|
||||||
|
C3Vector position[] = {
|
||||||
|
{ s_hRect.left, s_hRect.bottom, 0.0f },
|
||||||
|
{ s_hRect.right, s_hRect.bottom, 0.0f },
|
||||||
|
{ s_hRect.left, s_hRect.top, 0.0f },
|
||||||
|
{ s_hRect.right, s_hRect.top, 0.0f }
|
||||||
|
};
|
||||||
|
|
||||||
|
GxRsPush();
|
||||||
|
|
||||||
|
GxRsSet(GxRs_Lighting, 0);
|
||||||
|
GxRsSet(GxRs_BlendingMode, GxBlend_Alpha);
|
||||||
|
GxRsSet(GxRs_AlphaRef, CGxDevice::s_alphaRef[GxBlend_Alpha]);
|
||||||
|
|
||||||
|
GxPrimLockVertexPtrs(4, position, sizeof(C3Vector), nullptr, 0, &s_colorArray[HIGHLIGHT_COLOR], 0, nullptr, 0, nullptr, 0, nullptr, 0);
|
||||||
|
GxDrawLockedElements(GxPrim_TriangleStrip, 4, indices);
|
||||||
|
GxPrimUnlockVertexPtrs();
|
||||||
|
|
||||||
|
GxRsPop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawCaret(C3Vector& caretpos) {
|
||||||
|
uint16_t indices[] = {
|
||||||
|
0, 1, 2, 3
|
||||||
|
};
|
||||||
|
|
||||||
|
float minX = caretpos.x;
|
||||||
|
float minY = caretpos.y;
|
||||||
|
|
||||||
|
float maxX = caretpos.x + (s_caretpixwidth * 2);
|
||||||
|
float maxY = caretpos.y + ConsoleGetFontHeight();
|
||||||
|
|
||||||
|
C3Vector position[] = {
|
||||||
|
{ minX, minY, 0.0f },
|
||||||
|
{ maxX, minY, 0.0f },
|
||||||
|
{ minX, maxY, 0.0f },
|
||||||
|
{ maxX, maxY, 0.0f }
|
||||||
|
};
|
||||||
|
|
||||||
|
GxRsPush();
|
||||||
|
|
||||||
|
GxRsSet(GxRs_Lighting, 0);
|
||||||
|
GxRsSet(GxRs_Fog, 0);
|
||||||
|
GxRsSet(GxRs_DepthTest, 0);
|
||||||
|
GxRsSet(GxRs_DepthWrite, 0);
|
||||||
|
GxRsSet(GxRs_Culling, 0);
|
||||||
|
GxRsSet(GxRs_PolygonOffset, 0.0f);
|
||||||
|
GxRsSet(GxRs_BlendingMode, GxBlend_Alpha);
|
||||||
|
GxRsSet(GxRs_AlphaRef, CGxDevice::s_alphaRef[GxBlend_Alpha]);
|
||||||
|
|
||||||
|
GxPrimLockVertexPtrs(4, position, sizeof(C3Vector), nullptr, 0, &s_colorArray[INPUT_COLOR], 0, nullptr, 0, nullptr, 0, nullptr, 0);
|
||||||
|
GxDrawLockedElements(GxPrim_TriangleStrip, 4, indices);
|
||||||
|
GxPrimUnlockVertexPtrs();
|
||||||
|
|
||||||
|
GxRsPop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintBackground(void* param, const RECTF* rect, const RECTF* visible, float elapsedSec) {
|
void PaintBackground(void* param, const RECTF* rect, const RECTF* visible, float elapsedSec) {
|
||||||
@ -83,12 +153,252 @@ void PaintBackground(void* param, const RECTF* rect, const RECTF* visible, float
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetInputString(char* buffer) {
|
||||||
|
// s_highlightState = HS_NONE;
|
||||||
|
// s_hRect = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
// s_highlightLeftCharIndex = 0;
|
||||||
|
// s_highlightRightCharIndex = 0;
|
||||||
|
// s_highlightInput = 0;
|
||||||
|
|
||||||
|
if (s_inputString) {
|
||||||
|
GxuFontDestroyString(s_inputString);
|
||||||
|
}
|
||||||
|
|
||||||
|
s_inputString = nullptr;
|
||||||
|
|
||||||
|
auto fontHeight = ConsoleGetFontHeight();
|
||||||
|
|
||||||
|
if (buffer && buffer[0] != '\0') {
|
||||||
|
C3Vector pos = { 0.0f, 0.0f, 1.0f };
|
||||||
|
|
||||||
|
auto font = TextBlockGetFontPtr(s_textFont);
|
||||||
|
|
||||||
|
GxuFontCreateString(font, buffer, fontHeight, pos, 1.0f, fontHeight, 0.0f, s_inputString, GxVJ_Middle, GxHJ_Left, s_baseTextFlags, s_colorArray[INPUT_COLOR], s_charSpacing, 1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PasteInInputLine(char* characters) {
|
||||||
|
auto len = SStrLen(characters);
|
||||||
|
|
||||||
|
if (!len) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto line = GetInputLine();
|
||||||
|
|
||||||
|
ReserveInputSpace(line, len);
|
||||||
|
|
||||||
|
if (line->inputpos < line->chars) {
|
||||||
|
if (len <= 1) {
|
||||||
|
memmove(&line->buffer[line->inputpos + 1], &line->buffer[line->inputpos], line->chars - (line->inputpos + 1));
|
||||||
|
|
||||||
|
line->buffer[line->inputpos] = *characters;
|
||||||
|
|
||||||
|
line->inputpos++;
|
||||||
|
line->chars++;
|
||||||
|
} else {
|
||||||
|
auto input = reinterpret_cast<char*>(SMemAlloc(line->charsalloc, __FILE__, __LINE__, 0x0));
|
||||||
|
SStrCopy(input, &line->buffer[line->inputpos], STORM_MAX_STR);
|
||||||
|
|
||||||
|
auto buffer = reinterpret_cast<char*>(SMemAlloc(line->charsalloc, __FILE__, __LINE__, 0x0));
|
||||||
|
SStrCopy(buffer, line->buffer, STORM_MAX_STR);
|
||||||
|
buffer[line->inputpos] = '\0';
|
||||||
|
|
||||||
|
SStrPack(buffer, characters, line->charsalloc);
|
||||||
|
|
||||||
|
auto len = SStrLen(buffer);
|
||||||
|
|
||||||
|
line->inputpos = len;
|
||||||
|
|
||||||
|
SStrPack(buffer, input, line->charsalloc);
|
||||||
|
SStrCopy(line->buffer, buffer, STORM_MAX_STR);
|
||||||
|
|
||||||
|
line->chars = SStrLen(line->buffer);
|
||||||
|
|
||||||
|
if (input) {
|
||||||
|
SMemFree(input, __FILE__, __LINE__, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer) {
|
||||||
|
SMemFree(input, __FILE__, __LINE__, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int32_t i = 0; i < len; i++) {
|
||||||
|
line->buffer[line->inputpos++] = characters[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
line->buffer[line->inputpos] = '\0';
|
||||||
|
line->chars = line->inputpos;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetInputString(line->buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenerateNodeString(CONSOLELINE* node) {
|
||||||
|
auto font = TextBlockGetFontPtr(s_textFont);
|
||||||
|
|
||||||
|
if (font && node && node->buffer && node->buffer[0] != '\0') {
|
||||||
|
if (node->fontPointer) {
|
||||||
|
GxuFontDestroyString(node->fontPointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
C3Vector pos = {
|
||||||
|
0.0f, 0.0f, 1.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
auto fontHeight = ConsoleGetFontHeight();
|
||||||
|
|
||||||
|
GxuFontCreateString(font, node->buffer, fontHeight, pos, 1.0f, fontHeight, 0.0f, node->fontPointer, GxVJ_Middle, GxHJ_Left, s_baseTextFlags, s_colorArray[node->colorType], s_charSpacing, 1.0f);
|
||||||
|
BLIZZARD_ASSERT(node->fontPointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PaintText(void* param, const RECTF* rect, const RECTF* visible, float elapsedSec) {
|
void PaintText(void* param, const RECTF* rect, const RECTF* visible, float elapsedSec) {
|
||||||
// TODO
|
if (s_rect.bottom >= 1.0f) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float carettime = 0.0f;
|
||||||
|
static C3Vector caretpos = { 0.0f, 0.0f, 0.0f };
|
||||||
|
|
||||||
|
//
|
||||||
|
carettime += elapsedSec;
|
||||||
|
if ((!s_caret && carettime > 0.2) || (carettime > 0.3)) {
|
||||||
|
s_caret = !s_caret;
|
||||||
|
carettime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto line = GetInputLine();
|
||||||
|
|
||||||
|
C3Vector pos = {
|
||||||
|
s_rect.left,
|
||||||
|
(ConsoleGetFontHeight() * 0.75f) + s_rect.bottom,
|
||||||
|
1.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
GxuFontClearBatch(s_batch);
|
||||||
|
|
||||||
|
if (s_inputString) {
|
||||||
|
GxuFontSetStringPosition(s_inputString, pos);
|
||||||
|
GxuFontAddToBatch(s_batch, s_inputString);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto font = TextBlockGetFontPtr(s_textFont);
|
||||||
|
|
||||||
|
if (line->inputpos) {
|
||||||
|
caretpos = pos;
|
||||||
|
|
||||||
|
GxuFontGetTextExtent(font, line->buffer, line->inputpos, ConsoleGetFontHeight(), &caretpos.x, 0.0f, 1.0f, s_charSpacing, s_baseTextFlags);
|
||||||
|
|
||||||
|
DrawCaret(caretpos);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos.y += ConsoleGetFontHeight();
|
||||||
|
|
||||||
|
for (auto lineptr = GetCurrentLine(); (lineptr && pos.y < 1.0); lineptr = lineptr->Next()) {
|
||||||
|
if (lineptr != line) {
|
||||||
|
if (lineptr->fontPointer == nullptr) {
|
||||||
|
GenerateNodeString(lineptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
GxuFontSetStringPosition(lineptr->fontPointer, pos);
|
||||||
|
GxuFontAddToBatch(s_batch, lineptr->fontPointer);
|
||||||
|
pos.y += ConsoleGetFontHeight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GxuFontRenderBatch(s_batch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateHighlight() {
|
||||||
|
auto font = TextBlockGetFontPtr(s_textFont);
|
||||||
|
BLIZZARD_ASSERT(font);
|
||||||
|
|
||||||
|
auto len = SStrLen(s_copyText);
|
||||||
|
|
||||||
|
float left = std::min(s_highlightHStart, s_highlightHEnd);
|
||||||
|
float right = std::max(s_highlightHStart, s_highlightHEnd);
|
||||||
|
|
||||||
|
auto chars = GxuFontGetMaxCharsWithinWidth(font, s_copyText, ConsoleGetFontHeight(), left, len, &s_hRect.left, 0.0f, 1.0f, s_charSpacing, s_baseTextFlags);
|
||||||
|
|
||||||
|
s_highlightLeftCharIndex = chars;
|
||||||
|
|
||||||
|
if (chars) {
|
||||||
|
s_highlightRightCharIndex = chars - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_hRect.left < 0.015f) {
|
||||||
|
s_hRect.left = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_highlightRightCharIndex = GxuFontGetMaxCharsWithinWidth(font, s_copyText, ConsoleGetFontHeight(), right, len, &s_hRect.right, 0.0f, 1.0f, s_charSpacing, s_baseTextFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetHighlight() {
|
||||||
|
s_highlightState = HS_NONE;
|
||||||
|
s_hRect = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
}
|
||||||
|
|
||||||
|
HIGHLIGHTSTATE GetHighlightState() {
|
||||||
|
return s_highlightState;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetHighlightState(HIGHLIGHTSTATE hs) {
|
||||||
|
s_highlightState = hs;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* GetHighlightCopyText() {
|
||||||
|
return s_copyText;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetHighlightCopyText(char* text) {
|
||||||
|
SStrCopy(s_copyText, text, HIGHLIGHT_COPY_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetHighlightCopyText() {
|
||||||
|
s_copyText[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
RECTF& GetHighlightRect() {
|
||||||
|
return s_hRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetHighlightStart(float start) {
|
||||||
|
s_highlightHStart = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetHighlightEnd(float end) {
|
||||||
|
s_highlightHEnd = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CutHighlightToClipboard() {
|
||||||
|
char buffer[HIGHLIGHT_COPY_SIZE];
|
||||||
|
|
||||||
|
if (s_copyText[0] != '\0') {
|
||||||
|
uint32_t size = s_highlightRightCharIndex - s_highlightLeftCharIndex;
|
||||||
|
uint32_t capsize = HIGHLIGHT_COPY_SIZE-1;
|
||||||
|
size = std::min(size, capsize);
|
||||||
|
|
||||||
|
SStrCopy(buffer, &s_copyText[s_highlightLeftCharIndex], size);
|
||||||
|
|
||||||
|
buffer[size] = '\0';
|
||||||
|
|
||||||
|
// OsClipboardPutString(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
ResetHighlight();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PasteClipboardToHighlight() {
|
||||||
|
// auto buffer = OsClipboardGetString();
|
||||||
|
// PasteInInputLine(buffer);
|
||||||
|
// SMemFree(buffer, __FILE__, __LINE__, 0);
|
||||||
|
// ResetHighlight();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleScreenAnimate(float elapsedSec) {
|
void ConsoleScreenAnimate(float elapsedSec) {
|
||||||
auto finalPos = ConsoleGetActive() ? std::min(1.0f - s_consoleHeight, 1.0f) : 1.0f;
|
auto finalPos = ConsoleGetActive() ? std::min(1.0f - ConsoleGetHeight(), 1.0f) : 1.0f;
|
||||||
finalPos = std::max(finalPos, 0.0f);
|
finalPos = std::max(finalPos, 0.0f);
|
||||||
|
|
||||||
if (s_rect.bottom == finalPos) {
|
if (s_rect.bottom == finalPos) {
|
||||||
@ -120,7 +430,7 @@ void ConsoleScreenInitialize(const char* title) {
|
|||||||
s_caretpixheight = height == 0.0f ? 1.0f : 1.0f / height;
|
s_caretpixheight = height == 0.0f ? 1.0f : 1.0f / height;
|
||||||
|
|
||||||
SStrCopy(s_fontName, "Fonts\\ARIALN.ttf", sizeof(s_fontName));
|
SStrCopy(s_fontName, "Fonts\\ARIALN.ttf", sizeof(s_fontName));
|
||||||
s_textFont = TextBlockGenerateFont(s_fontName, 0, NDCToDDCHeight(s_fontHeight));
|
s_textFont = TextBlockGenerateFont(s_fontName, 0, NDCToDDCHeight(ConsoleGetFontHeight()));
|
||||||
|
|
||||||
ScrnLayerCreate(&s_rect, 6.0f, 0x1 | 0x2, nullptr, PaintBackground, &s_layerBackground);
|
ScrnLayerCreate(&s_rect, 6.0f, 0x1 | 0x2, nullptr, PaintBackground, &s_layerBackground);
|
||||||
ScrnLayerCreate(&s_rect, 7.0f, 0x1 | 0x2, nullptr, PaintText, &s_layerText);
|
ScrnLayerCreate(&s_rect, 7.0f, 0x1 | 0x2, nullptr, PaintText, &s_layerText);
|
||||||
@ -128,10 +438,11 @@ void ConsoleScreenInitialize(const char* title) {
|
|||||||
RegisterHandlers();
|
RegisterHandlers();
|
||||||
|
|
||||||
// TODO register commands
|
// TODO register commands
|
||||||
|
ConsoleInitializeScreenCommand();
|
||||||
|
|
||||||
// TODO EventSetConfirmCloseCallback(EventCloseCallback, 0);
|
// TODO EventSetConfirmCloseCallback(EventCloseCallback, 0);
|
||||||
|
|
||||||
// TODO ConsoleCommandExecute("ver", 1);
|
ConsoleCommandExecute("ver", 1);
|
||||||
|
|
||||||
s_batch = GxuFontCreateBatch(false, false);
|
s_batch = GxuFontCreateBatch(false, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,46 @@
|
|||||||
#ifndef CONSOLE_SCREEN_HPP
|
#ifndef CONSOLE_SCREEN_HPP
|
||||||
#define CONSOLE_SCREEN_HPP
|
#define CONSOLE_SCREEN_HPP
|
||||||
|
|
||||||
|
#define HIGHLIGHT_COPY_SIZE 128
|
||||||
|
|
||||||
|
#include "console/Line.hpp"
|
||||||
|
#include <storm/region/Types.hpp>
|
||||||
|
|
||||||
|
enum HIGHLIGHTSTATE {
|
||||||
|
HS_NONE = 0,
|
||||||
|
HS_HIGHLIGHTING = 1,
|
||||||
|
HS_ENDHIGHLIGHT = 2,
|
||||||
|
NUM_HIGHLIGHTSTATES
|
||||||
|
};
|
||||||
|
|
||||||
void ConsoleScreenAnimate(float elapsedSec);
|
void ConsoleScreenAnimate(float elapsedSec);
|
||||||
|
|
||||||
void ConsoleScreenInitialize(const char* title);
|
void ConsoleScreenInitialize(const char* title);
|
||||||
|
|
||||||
|
void SetInputString(char* buffer);
|
||||||
|
|
||||||
|
void ResetHighlight();
|
||||||
|
|
||||||
|
void UpdateHighlight();
|
||||||
|
|
||||||
|
HIGHLIGHTSTATE GetHighlightState();
|
||||||
|
|
||||||
|
void SetHighlightState(HIGHLIGHTSTATE hs);
|
||||||
|
|
||||||
|
void SetHighlightCopyText(char* text);
|
||||||
|
|
||||||
|
char* GetHighlightCopyText();
|
||||||
|
|
||||||
|
void ResetHighlightCopyText();
|
||||||
|
|
||||||
|
void SetHighlightStart(float start);
|
||||||
|
void SetHighlightEnd(float end);
|
||||||
|
|
||||||
|
RECTF& GetHighlightRect();
|
||||||
|
|
||||||
|
void CutHighlightToClipboard();
|
||||||
|
void PasteClipboardToHighlight();
|
||||||
|
|
||||||
|
void GenerateNodeString(CONSOLELINE* node);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,6 +1,11 @@
|
|||||||
#ifndef CONSOLE_TYPES_HPP
|
#ifndef CONSOLE_TYPES_HPP
|
||||||
#define CONSOLE_TYPES_HPP
|
#define CONSOLE_TYPES_HPP
|
||||||
|
|
||||||
|
#include "gx/Font.hpp"
|
||||||
|
|
||||||
|
#include <storm/Hash.hpp>
|
||||||
|
#include <storm/List.hpp>
|
||||||
|
|
||||||
enum COLOR_T {
|
enum COLOR_T {
|
||||||
DEFAULT_COLOR,
|
DEFAULT_COLOR,
|
||||||
INPUT_COLOR,
|
INPUT_COLOR,
|
||||||
@ -14,10 +19,63 @@ enum COLOR_T {
|
|||||||
NUM_COLORTYPES,
|
NUM_COLORTYPES,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum CATEGORY {
|
||||||
|
DEBUG,
|
||||||
|
GRAPHICS,
|
||||||
|
CONSOLE,
|
||||||
|
COMBAT,
|
||||||
|
GAME,
|
||||||
|
DEFAULT,
|
||||||
|
NET,
|
||||||
|
SOUND,
|
||||||
|
GM,
|
||||||
|
NONE,
|
||||||
|
LAST
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EXECMODE {
|
||||||
|
EM_PROMPTOVERWRITE = 0,
|
||||||
|
EM_RECORDING = 1,
|
||||||
|
EM_APPEND = 2,
|
||||||
|
EM_WRITEFILE = 3,
|
||||||
|
EM_NOTACTIVE = 4,
|
||||||
|
EM_NUM_EXECMODES = 5
|
||||||
|
};
|
||||||
|
|
||||||
enum CONSOLERESIZESTATE {
|
enum CONSOLERESIZESTATE {
|
||||||
CS_NONE,
|
CS_NONE,
|
||||||
CS_STRETCH,
|
CS_STRETCH,
|
||||||
NUM_CONSOLERESIZESTATES,
|
NUM_CONSOLERESIZESTATES,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef int32_t (*COMMANDHANDLER)(const char*, const char*);
|
||||||
|
|
||||||
|
class CONSOLECOMMAND : public TSHashObject<CONSOLECOMMAND, HASHKEY_STRI> {
|
||||||
|
public:
|
||||||
|
COMMANDHANDLER m_handler;
|
||||||
|
const char* m_helpText;
|
||||||
|
CATEGORY m_category;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CONSOLELINE : public TSLinkedNode<CONSOLELINE> {
|
||||||
|
public:
|
||||||
|
char* buffer;
|
||||||
|
uint32_t chars;
|
||||||
|
uint32_t charsalloc;
|
||||||
|
uint32_t inputpos;
|
||||||
|
uint32_t inputstart;
|
||||||
|
COLOR_T colorType;
|
||||||
|
CGxString* fontPointer;
|
||||||
|
|
||||||
|
~CONSOLELINE();
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConsoleCommandList {
|
||||||
|
public:
|
||||||
|
const char* m_command;
|
||||||
|
COMMANDHANDLER m_handler;
|
||||||
|
const char* m_helpText;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
6
src/console/command/console/AppendLogToFile.cpp
Normal file
6
src/console/command/console/AppendLogToFile.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "console/Command.hpp"
|
||||||
|
|
||||||
|
int32_t ConsoleCommand_AppendLogToFile(const char* command, const char* arguments) {
|
||||||
|
// TODO
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
6
src/console/command/console/BackGroundColor.cpp
Normal file
6
src/console/command/console/BackGroundColor.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "console/Command.hpp"
|
||||||
|
|
||||||
|
int32_t ConsoleCommand_BackGroundColor(const char* command, const char* arguments) {
|
||||||
|
// TODO
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
6
src/console/command/console/BufferSize.cpp
Normal file
6
src/console/command/console/BufferSize.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "console/Command.hpp"
|
||||||
|
|
||||||
|
int32_t ConsoleCommand_BufferSize(const char* command, const char* arguments) {
|
||||||
|
// TODO
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
6
src/console/command/console/CharSpacing.cpp
Normal file
6
src/console/command/console/CharSpacing.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "console/Command.hpp"
|
||||||
|
|
||||||
|
int32_t ConsoleCommand_CharSpacing(const char* command, const char* arguments) {
|
||||||
|
// TODO
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
7
src/console/command/console/ClearConsole.cpp
Normal file
7
src/console/command/console/ClearConsole.cpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include "console/Command.hpp"
|
||||||
|
#include "console/Console.hpp"
|
||||||
|
|
||||||
|
int32_t ConsoleCommand_ClearConsole(const char* command, const char* arguments) {
|
||||||
|
ConsoleClear();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
7
src/console/command/console/CloseConsole.cpp
Normal file
7
src/console/command/console/CloseConsole.cpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include "console/Command.hpp"
|
||||||
|
#include "console/Console.hpp"
|
||||||
|
|
||||||
|
int32_t ConsoleCommand_CloseConsole(const char* command, const char* arguments) {
|
||||||
|
ConsoleSetActive(false);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
6
src/console/command/console/CurrentSettings.cpp
Normal file
6
src/console/command/console/CurrentSettings.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "console/Command.hpp"
|
||||||
|
|
||||||
|
int32_t ConsoleCommand_CurrentSettings(const char* command, const char* arguments) {
|
||||||
|
// TODO
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
6
src/console/command/console/DefaultSettings.cpp
Normal file
6
src/console/command/console/DefaultSettings.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "console/Command.hpp"
|
||||||
|
|
||||||
|
int32_t ConsoleCommand_DefaultSettings(const char* command, const char* arguments) {
|
||||||
|
// TODO
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
6
src/console/command/console/Font.cpp
Normal file
6
src/console/command/console/Font.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "console/Command.hpp"
|
||||||
|
|
||||||
|
int32_t ConsoleCommand_Font(const char* command, const char* arguments) {
|
||||||
|
// TODO
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
6
src/console/command/console/FontColor.cpp
Normal file
6
src/console/command/console/FontColor.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "console/Command.hpp"
|
||||||
|
|
||||||
|
int32_t ConsoleCommand_FontColor(const char* command, const char* arguments) {
|
||||||
|
// TODO
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
6
src/console/command/console/FontSize.cpp
Normal file
6
src/console/command/console/FontSize.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "console/Command.hpp"
|
||||||
|
|
||||||
|
int32_t ConsoleCommand_FontSize(const char* command, const char* arguments) {
|
||||||
|
// TODO
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
111
src/console/command/console/Help.cpp
Normal file
111
src/console/command/console/Help.cpp
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
#include "console/Command.hpp"
|
||||||
|
#include "console/Line.hpp"
|
||||||
|
|
||||||
|
struct CategoryTranslation {
|
||||||
|
CATEGORY categoryValue;
|
||||||
|
char categoryString[20];
|
||||||
|
};
|
||||||
|
|
||||||
|
CategoryTranslation s_translation[] = {
|
||||||
|
{ DEBUG, "debug" },
|
||||||
|
{ GRAPHICS, "graphics" },
|
||||||
|
{ CONSOLE, "console" },
|
||||||
|
{ COMBAT, "combat" },
|
||||||
|
{ GAME, "game" },
|
||||||
|
{ DEFAULT, "default" },
|
||||||
|
{ NET, "net" },
|
||||||
|
{ SOUND, "sound" },
|
||||||
|
{ GM, "gm" }
|
||||||
|
};
|
||||||
|
|
||||||
|
int32_t ConsoleCommand_Help(const char* command, const char* arguments) {
|
||||||
|
char buffer[128];
|
||||||
|
bool showCategories = *arguments == '\0';
|
||||||
|
|
||||||
|
auto numTranslation = sizeof(s_translation) / sizeof(CategoryTranslation);
|
||||||
|
|
||||||
|
if (showCategories) {
|
||||||
|
memset(buffer, 0, sizeof(buffer));
|
||||||
|
|
||||||
|
ConsoleWrite("Console help categories: ", DEFAULT_COLOR);
|
||||||
|
|
||||||
|
uint32_t offset = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < numTranslation; i++) {
|
||||||
|
auto& translation = s_translation[i];
|
||||||
|
SStrPack(buffer, translation.categoryString, sizeof(buffer));
|
||||||
|
|
||||||
|
if (i + 1 != numTranslation) {
|
||||||
|
SStrPack(buffer, ", ", sizeof(buffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsoleWrite(buffer, WARNING_COLOR);
|
||||||
|
ConsoleWrite("For more information type 'help [command] or [category]'", WARNING_COLOR);
|
||||||
|
} else {
|
||||||
|
for (size_t i = 0; i < numTranslation; i++) {
|
||||||
|
auto& translation = s_translation[i];
|
||||||
|
|
||||||
|
if (SStrCmpI(translation.categoryString, arguments, STORM_MAX_STR) == 0) {
|
||||||
|
if (translation.categoryValue != NONE) {
|
||||||
|
memset(buffer, 0, sizeof(buffer));
|
||||||
|
SStrPrintf(buffer, sizeof(buffer), "Commands registered for the category %s:", arguments);
|
||||||
|
|
||||||
|
ConsoleWrite(buffer, WARNING_COLOR);
|
||||||
|
|
||||||
|
buffer[0] = '\0';
|
||||||
|
|
||||||
|
uint32_t counter = 0;
|
||||||
|
|
||||||
|
for (auto cmd = g_consoleCommandHash.Head(); cmd; cmd = g_consoleCommandHash.Next(cmd)) {
|
||||||
|
if (cmd->m_category == translation.categoryValue) {
|
||||||
|
SStrPack(buffer, cmd->m_key.m_str, sizeof(buffer));
|
||||||
|
SStrPack(buffer, ", ", sizeof(buffer));
|
||||||
|
|
||||||
|
if (++counter == 8) {
|
||||||
|
ConsoleWrite(buffer, DEFAULT_COLOR);
|
||||||
|
buffer[0] = '\0';
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* wr = nullptr;
|
||||||
|
|
||||||
|
if (buffer[0]) {
|
||||||
|
auto comma = reinterpret_cast<char*>(SStrChrR(buffer, ','));
|
||||||
|
if (comma) {
|
||||||
|
*comma = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
wr = buffer;
|
||||||
|
} else {
|
||||||
|
wr = "NONE";
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsoleWrite(wr, DEFAULT_COLOR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cmd = g_consoleCommandHash.Ptr(arguments);
|
||||||
|
|
||||||
|
if (cmd == nullptr) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SStrPrintf(buffer, 0xa5, "Help for command %s:", arguments);
|
||||||
|
ConsoleWrite(buffer, WARNING_COLOR);
|
||||||
|
|
||||||
|
auto help = cmd->m_helpText;
|
||||||
|
if (help == nullptr) {
|
||||||
|
help = "No help yet";
|
||||||
|
}
|
||||||
|
|
||||||
|
SStrPrintf(buffer, 0xa5, " %s %s", arguments, help);
|
||||||
|
ConsoleWrite(buffer, DEFAULT_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
6
src/console/command/console/HighLightColor.cpp
Normal file
6
src/console/command/console/HighLightColor.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "console/Command.hpp"
|
||||||
|
|
||||||
|
int32_t ConsoleCommand_HighLightColor(const char* command, const char* arguments) {
|
||||||
|
// TODO
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
6
src/console/command/console/Proportional.cpp
Normal file
6
src/console/command/console/Proportional.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "console/Command.hpp"
|
||||||
|
|
||||||
|
int32_t ConsoleCommand_Proportional(const char* command, const char* arguments) {
|
||||||
|
// TODO
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
7
src/console/command/console/RepeatHandler.cpp
Normal file
7
src/console/command/console/RepeatHandler.cpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include "console/Command.hpp"
|
||||||
|
#include "console/Console.hpp"
|
||||||
|
|
||||||
|
int32_t ConsoleCommand_RepeatHandler(const char* command, const char* arguments) {
|
||||||
|
// TODO
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
7
src/console/command/console/Ver.cpp
Normal file
7
src/console/command/console/Ver.cpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include "console/Command.hpp"
|
||||||
|
#include "console/Line.hpp"
|
||||||
|
|
||||||
|
int32_t ConsoleCommand_Ver(const char* command, const char* arguments) {
|
||||||
|
ConsoleWrite("Whoa <https://github.com/whoahq/whoa>", DEFAULT_COLOR);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
7
src/console/command/default/Quit.cpp
Normal file
7
src/console/command/default/Quit.cpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include "console/Command.hpp"
|
||||||
|
#include "console/Console.hpp"
|
||||||
|
|
||||||
|
int32_t ConsoleCommand_Quit(const char* command, const char* arguments) {
|
||||||
|
ConsolePostClose();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
5
src/console/command/default/SetMap.cpp
Normal file
5
src/console/command/default/SetMap.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#include "console/Command.hpp"
|
||||||
|
|
||||||
|
int32_t ConsoleCommand_SetMap(const char* command, const char* arguments) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@ -53,7 +53,28 @@ int32_t EventIsControlKeyDown() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t EventIsKeyDown(KEY key) {
|
int32_t EventIsKeyDown(KEY key) {
|
||||||
// TODO
|
auto hContext = PropGet(PROP_EVENTCONTEXT);
|
||||||
|
auto contextId = *reinterpret_cast<uint32_t*>(hContext);
|
||||||
|
int32_t findMask;
|
||||||
|
|
||||||
|
auto context = TSingletonInstanceId<EvtContext, offsetof(EvtContext, m_id)>::s_idTable.Ptr(
|
||||||
|
contextId,
|
||||||
|
0,
|
||||||
|
&findMask
|
||||||
|
);
|
||||||
|
|
||||||
|
if (context) {
|
||||||
|
auto keystate = IEvtQueueCheckSyncKeyState(context, key);
|
||||||
|
|
||||||
|
if (findMask != -1) {
|
||||||
|
TSingletonInstanceId<EvtContext, offsetof(EvtContext, m_id)>::s_idTable.Unlock(
|
||||||
|
findMask & (INSTANCE_TABLE_SLOT_COUNT - 1),
|
||||||
|
findMask >= INSTANCE_TABLE_SLOT_COUNT
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return keystate;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,11 +3,89 @@
|
|||||||
#include "event/EvtHandler.hpp"
|
#include "event/EvtHandler.hpp"
|
||||||
#include <storm/Error.hpp>
|
#include <storm/Error.hpp>
|
||||||
|
|
||||||
|
void UpdateSyncMouseState(EvtContext* context, MOUSEBUTTON button, int32_t down) {
|
||||||
|
if (down) {
|
||||||
|
context->m_queueSyncButtonState |= button;
|
||||||
|
} else {
|
||||||
|
context->m_queueSyncButtonState &= ~button;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateSyncKeyState(EvtContext* context, KEY key, EVENTID& id) {
|
||||||
|
context->m_critsect.Enter();
|
||||||
|
|
||||||
|
int32_t keyDown = 0;
|
||||||
|
|
||||||
|
auto list = &context->m_queueSyncKeyDownList;
|
||||||
|
|
||||||
|
for (auto node = list->Head(); node;) {
|
||||||
|
if (node->key == key) {
|
||||||
|
keyDown = 1;
|
||||||
|
auto dead = node;
|
||||||
|
node = list->Next(node);
|
||||||
|
list->UnlinkNode(dead);
|
||||||
|
list->DeleteNode(dead);
|
||||||
|
} else {
|
||||||
|
node = list->Next(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id == EVENT_ID_KEYDOWN) {
|
||||||
|
if (keyDown) {
|
||||||
|
id = EVENT_ID_KEYDOWN_REPEATING;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto node = context->m_queueSyncKeyDownList.NewNode(2, 0, 0);
|
||||||
|
node->key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
context->m_critsect.Leave();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetSyncState(EvtContext* context) {
|
||||||
|
context->m_queueSyncButtonState = 0;
|
||||||
|
|
||||||
|
context->m_critsect.Enter();
|
||||||
|
|
||||||
|
EvtKeyDown* node;
|
||||||
|
|
||||||
|
auto list = &context->m_queueSyncKeyDownList;
|
||||||
|
|
||||||
|
while (node = list->Head()) {
|
||||||
|
list->UnlinkNode(node);
|
||||||
|
list->DeleteNode(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
context->m_critsect.Leave();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateSyncState(EvtContext* context, EVENTID& id, const void* data) {
|
||||||
|
KEY key;
|
||||||
|
MOUSEBUTTON button;
|
||||||
|
|
||||||
|
STORM_ASSERT(context);
|
||||||
|
|
||||||
|
switch (id) {
|
||||||
|
case EVENT_ID_FOCUS:
|
||||||
|
ResetSyncState(context);
|
||||||
|
break;
|
||||||
|
case EVENT_ID_KEYDOWN:
|
||||||
|
case EVENT_ID_KEYUP:
|
||||||
|
key = reinterpret_cast<const EVENT_DATA_KEY*>(data)->key;
|
||||||
|
UpdateSyncKeyState(context, key, id);
|
||||||
|
break;
|
||||||
|
case EVENT_ID_MOUSEDOWN:
|
||||||
|
case EVENT_ID_MOUSEUP:
|
||||||
|
button = reinterpret_cast<const EVENT_DATA_MOUSE*>(data)->button;
|
||||||
|
UpdateSyncMouseState(context, button, id == EVENT_ID_MOUSEDOWN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void IEvtQueueDispatch(EvtContext* context, EVENTID id, const void* data) {
|
void IEvtQueueDispatch(EvtContext* context, EVENTID id, const void* data) {
|
||||||
STORM_ASSERT(context);
|
STORM_ASSERT(context);
|
||||||
|
|
||||||
// TODO
|
UpdateSyncState(context, id, data);
|
||||||
// UpdateSyncState(data, &id, context, v3);
|
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// if (SErrIsDisplayingError()) {
|
// if (SErrIsDisplayingError()) {
|
||||||
@ -65,3 +143,24 @@ void IEvtQueueRegister(EvtContext* context, EVENTID id, int32_t (*handler)(const
|
|||||||
|
|
||||||
handlerList->LinkNode(evtHandler, 2, h);
|
handlerList->LinkNode(evtHandler, 2, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t IEvtQueueCheckSyncKeyState(EvtContext* context, KEY key) {
|
||||||
|
STORM_VALIDATE(context, ERROR_INVALID_PARAMETER, 0);
|
||||||
|
|
||||||
|
context->m_critsect.Enter();
|
||||||
|
|
||||||
|
int32_t keystate = 0;
|
||||||
|
|
||||||
|
auto list = &context->m_queueSyncKeyDownList;
|
||||||
|
|
||||||
|
for (auto node = list->Head(); node; node = list->Next(node)) {
|
||||||
|
if (node->key == key) {
|
||||||
|
keystate = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context->m_critsect.Leave();
|
||||||
|
|
||||||
|
return keystate;
|
||||||
|
}
|
||||||
|
|||||||
@ -11,4 +11,6 @@ void IEvtQueueDispatchAll(EvtContext* context);
|
|||||||
|
|
||||||
void IEvtQueueRegister(EvtContext* context, EVENTID id, int32_t (*handler)(const void*, void*), void* param, float priority);
|
void IEvtQueueRegister(EvtContext* context, EVENTID id, int32_t (*handler)(const void*, void*), void* param, float priority);
|
||||||
|
|
||||||
|
int32_t IEvtQueueCheckSyncKeyState(EvtContext* context, KEY key);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -112,7 +112,7 @@ void IEvtSchedulerInitialize(int32_t threadCount, int32_t netServer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IEvtSchedulerProcess() {
|
void IEvtSchedulerProcess() {
|
||||||
#if defined(WHOA_SYSTEM_WIN)
|
#if defined(WHOA_SYSTEM_WIN) || defined(WHOA_SYSTEM_LINUX)
|
||||||
Event::s_startEvent.Set();
|
Event::s_startEvent.Set();
|
||||||
|
|
||||||
SchedulerThreadProc(reinterpret_cast<void*>(1));
|
SchedulerThreadProc(reinterpret_cast<void*>(1));
|
||||||
|
|||||||
@ -3,9 +3,17 @@
|
|||||||
#include "event/Queue.hpp"
|
#include "event/Queue.hpp"
|
||||||
#include <common/Time.hpp>
|
#include <common/Time.hpp>
|
||||||
|
|
||||||
|
#if defined(WHOA_SYSTEM_WIN)
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
void SynthesizeDestroy(EvtContext* context) {
|
void SynthesizeDestroy(EvtContext* context) {
|
||||||
// TODO
|
// TODO
|
||||||
|
#if defined(WHOA_SYSTEM_WIN)
|
||||||
|
ExitProcess(0);
|
||||||
|
#else
|
||||||
exit(0);
|
exit(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SynthesizeIdle(EvtContext* context, uint32_t currTime, float elapsedSec) {
|
void SynthesizeIdle(EvtContext* context, uint32_t currTime, float elapsedSec) {
|
||||||
|
|||||||
@ -1,8 +1,14 @@
|
|||||||
#include "event/Input.hpp"
|
#include "event/Input.hpp"
|
||||||
|
#include <common/Time.hpp>
|
||||||
|
|
||||||
int32_t OsInputGet(OSINPUT* id, int32_t* param0, int32_t* param1, int32_t* param2, int32_t* param3) {
|
int32_t OsInputGet(OSINPUT* id, int32_t* param0, int32_t* param1, int32_t* param2, int32_t* param3) {
|
||||||
// TODO
|
if (Input::s_queueTail == Input::s_queueHead) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
OsQueueSetParam(3, OsGetAsyncTimeMs());
|
||||||
|
|
||||||
|
return OsQueueGet(id, param0, param1, param2, param3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OsInputSetMouseMode(OS_MOUSE_MODE mode) {
|
void OsInputSetMouseMode(OS_MOUSE_MODE mode) {
|
||||||
|
|||||||
@ -14,6 +14,10 @@
|
|||||||
#include "gx/d3d/CGxDeviceD3d.hpp"
|
#include "gx/d3d/CGxDeviceD3d.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(WHOA_SYSTEM_LINUX) || defined(WHOA_SYSTEM_WIN)
|
||||||
|
#include "gx/glsdl/CGxDeviceGLSDL.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(WHOA_SYSTEM_MAC)
|
#if defined(WHOA_SYSTEM_MAC)
|
||||||
#include "gx/gll/CGxDeviceGLL.hpp"
|
#include "gx/gll/CGxDeviceGLL.hpp"
|
||||||
#endif
|
#endif
|
||||||
@ -120,13 +124,16 @@ CGxDevice* CGxDevice::NewGLL() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
CGxDevice* CGxDevice::NewOpenGl() {
|
CGxDevice* CGxDevice::NewOpenGl() {
|
||||||
// TODO
|
|
||||||
// auto m = SMemAlloc(sizeof(CGxDeviceOpenGl), __FILE__, __LINE__, 0x0);
|
|
||||||
// return new (m) CGxDeviceOpenGl();
|
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(WHOA_SYSTEM_WIN) || defined(WHOA_SYSTEM_LINUX)
|
||||||
|
CGxDevice* CGxDevice::NewGLSDL() {
|
||||||
|
auto m = SMemAlloc(sizeof(CGxDeviceGLSDL), __FILE__, __LINE__, 0x0);
|
||||||
|
return new (m) CGxDeviceGLSDL();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
uint32_t CGxDevice::PrimCalcCount(EGxPrim primType, uint32_t count) {
|
uint32_t CGxDevice::PrimCalcCount(EGxPrim primType, uint32_t count) {
|
||||||
auto div = CGxDevice::s_primVtxDiv[primType];
|
auto div = CGxDevice::s_primVtxDiv[primType];
|
||||||
if (div != 1) {
|
if (div != 1) {
|
||||||
|
|||||||
@ -56,6 +56,9 @@ class CGxDevice {
|
|||||||
#endif
|
#endif
|
||||||
#if defined(WHOA_SYSTEM_MAC)
|
#if defined(WHOA_SYSTEM_MAC)
|
||||||
static CGxDevice* NewGLL();
|
static CGxDevice* NewGLL();
|
||||||
|
#endif
|
||||||
|
#if defined(WHOA_SYSTEM_LINUX) || defined(WHOA_SYSTEM_WIN)
|
||||||
|
static CGxDevice* NewGLSDL();
|
||||||
#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);
|
||||||
|
|||||||
@ -19,6 +19,12 @@ if(WHOA_SYSTEM_MAC)
|
|||||||
list(APPEND GX_SOURCES ${GLL_SOURCES})
|
list(APPEND GX_SOURCES ${GLL_SOURCES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Build OpenGL/SDL graphics device on Windows and Linux
|
||||||
|
if(WHOA_SYSTEM_WIN OR WHOA_SYSTEM_LINUX)
|
||||||
|
file(GLOB GLSDL_SOURCES "glsdl/*.cpp")
|
||||||
|
list(APPEND GX_SOURCES ${GLSDL_SOURCES})
|
||||||
|
endif()
|
||||||
|
|
||||||
add_library(gx STATIC ${GX_SOURCES})
|
add_library(gx STATIC ${GX_SOURCES})
|
||||||
|
|
||||||
target_include_directories(gx
|
target_include_directories(gx
|
||||||
@ -47,6 +53,15 @@ if(WHOA_SYSTEM_WIN)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Link SDL3 and GLEW for Windows and Linux
|
||||||
|
if (WHOA_SYSTEM_WIN OR WHOA_SYSTEM_LINUX)
|
||||||
|
target_link_libraries(gx
|
||||||
|
PRIVATE
|
||||||
|
SDL3::SDL3-static
|
||||||
|
libglew_static
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WHOA_SYSTEM_MAC)
|
if(WHOA_SYSTEM_MAC)
|
||||||
target_link_libraries(gx
|
target_link_libraries(gx
|
||||||
PRIVATE
|
PRIVATE
|
||||||
|
|||||||
@ -14,6 +14,8 @@ CGxDevice* GxDevCreate(EGxApi api, int32_t (*windowProc)(void* window, uint32_t
|
|||||||
device = CGxDevice::NewD3d();
|
device = CGxDevice::NewD3d();
|
||||||
} else if (api == GxApi_D3d9Ex) {
|
} else if (api == GxApi_D3d9Ex) {
|
||||||
device = CGxDevice::NewD3d9Ex();
|
device = CGxDevice::NewD3d9Ex();
|
||||||
|
} else if (api == GxApi_GLSDL) {
|
||||||
|
device = CGxDevice::NewGLSDL();
|
||||||
} else {
|
} else {
|
||||||
// Error
|
// Error
|
||||||
}
|
}
|
||||||
@ -29,6 +31,14 @@ CGxDevice* GxDevCreate(EGxApi api, int32_t (*windowProc)(void* window, uint32_t
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(WHOA_SYSTEM_LINUX)
|
||||||
|
if (api == GxApi_GLSDL) {
|
||||||
|
device = CGxDevice::NewGLSDL();
|
||||||
|
} else {
|
||||||
|
// Error
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
g_theGxDevicePtr = device;
|
g_theGxDevicePtr = device;
|
||||||
|
|
||||||
if (g_theGxDevicePtr->DeviceCreate(windowProc, format)) {
|
if (g_theGxDevicePtr->DeviceCreate(windowProc, format)) {
|
||||||
|
|||||||
@ -337,6 +337,16 @@ int32_t GxuFontDestroyBatch(CGxStringBatch* batch) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t GxuFontClearBatch(CGxStringBatch* batch) {
|
||||||
|
if (!batch) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
batch->m_fontBatch.Clear();
|
||||||
|
|
||||||
|
return batch != 0;
|
||||||
|
}
|
||||||
|
|
||||||
void GxuFontDestroyFont(CGxFont*& font) {
|
void GxuFontDestroyFont(CGxFont*& font) {
|
||||||
if (font) {
|
if (font) {
|
||||||
g_fonts.DeleteNode(font);
|
g_fonts.DeleteNode(font);
|
||||||
|
|||||||
@ -67,6 +67,8 @@ int32_t GxuFontCreateString(CGxFont*, const char*, float, const C3Vector&, float
|
|||||||
|
|
||||||
int32_t GxuFontDestroyBatch(CGxStringBatch*);
|
int32_t GxuFontDestroyBatch(CGxStringBatch*);
|
||||||
|
|
||||||
|
int32_t GxuFontClearBatch(CGxStringBatch* batch);
|
||||||
|
|
||||||
void GxuFontDestroyFont(CGxFont*& font);
|
void GxuFontDestroyFont(CGxFont*& font);
|
||||||
|
|
||||||
void GxuFontDestroyString(CGxString*&);
|
void GxuFontDestroyString(CGxString*&);
|
||||||
|
|||||||
@ -35,7 +35,8 @@ enum EGxApi {
|
|||||||
GxApi_D3d10 = 3,
|
GxApi_D3d10 = 3,
|
||||||
GxApi_D3d11 = 4,
|
GxApi_D3d11 = 4,
|
||||||
GxApi_GLL = 5,
|
GxApi_GLL = 5,
|
||||||
GxApis_Last = 6
|
GxApi_GLSDL = 6,
|
||||||
|
GxApis_Last = 7
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EGxBlend {
|
enum EGxBlend {
|
||||||
|
|||||||
1326
src/gx/glsdl/CGxDeviceGLSDL.cpp
Normal file
1326
src/gx/glsdl/CGxDeviceGLSDL.cpp
Normal file
File diff suppressed because it is too large
Load Diff
82
src/gx/glsdl/CGxDeviceGLSDL.hpp
Normal file
82
src/gx/glsdl/CGxDeviceGLSDL.hpp
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#ifndef GX_GL_SDL_C_GX_DEVICE_GL_SDL_HPP
|
||||||
|
#define GX_GL_SDL_C_GX_DEVICE_GL_SDL_HPP
|
||||||
|
|
||||||
|
#include "gx/CGxDevice.hpp"
|
||||||
|
#include "gx/glsdl/GLSDLDevice.hpp"
|
||||||
|
#include "gx/glsdl/GLSDLWindow.hpp"
|
||||||
|
|
||||||
|
class CGxBatch;
|
||||||
|
class CGxShader;
|
||||||
|
|
||||||
|
class CGxDeviceGLSDL : public CGxDevice {
|
||||||
|
public:
|
||||||
|
// Static variables
|
||||||
|
static GLEnum s_glCubeMapFaces[];
|
||||||
|
static GLEnum s_glDstBlend[];
|
||||||
|
static GLEnum s_glSrcBlend[];
|
||||||
|
static GLTextureFormat s_gxTexFmtToGLSDLFmt[];
|
||||||
|
static GLEnum s_poolTarget2BufferFormat[];
|
||||||
|
static GLEnum s_poolTarget2BufferType[];
|
||||||
|
static GLEnum s_poolUsage2BufferUsage[];
|
||||||
|
static GLEnum s_primitiveConversion[];
|
||||||
|
|
||||||
|
// Member variables
|
||||||
|
GLSDLDevice m_GLSDLDevice;
|
||||||
|
GLSDLWindow m_GLSDLWindow;
|
||||||
|
GLVertexFormat m_glFormats[GxVertexBufferFormats_Last] = {};
|
||||||
|
|
||||||
|
// Virtual member functions
|
||||||
|
virtual void ITexMarkAsUpdated(CGxTex*);
|
||||||
|
virtual void IRsSendToHw(EGxRenderState);
|
||||||
|
virtual int32_t DeviceCreate(int32_t (*windowProc)(void* window, uint32_t message, uintptr_t wparam, intptr_t lparam), const CGxFormat&);
|
||||||
|
virtual int32_t DeviceSetFormat(const CGxFormat&);
|
||||||
|
virtual void* DeviceWindow();
|
||||||
|
virtual void DeviceWM(EGxWM wm, uintptr_t param1, uintptr_t param2) {};
|
||||||
|
virtual void CapsWindowSize(CRect&);
|
||||||
|
virtual void CapsWindowSizeInScreenCoords(CRect& dst);
|
||||||
|
virtual void ScenePresent();
|
||||||
|
virtual void SceneClear(uint32_t, CImVector);
|
||||||
|
virtual void XformSetProjection(const C44Matrix&);
|
||||||
|
virtual void XformSetView(const C44Matrix&);
|
||||||
|
virtual void Draw(CGxBatch* batch, int32_t indexed);
|
||||||
|
virtual void PoolSizeSet(CGxPool*, uint32_t);
|
||||||
|
virtual char* BufLock(CGxBuf*);
|
||||||
|
virtual int32_t BufUnlock(CGxBuf*, uint32_t);
|
||||||
|
virtual void BufData(CGxBuf* buf, const void* data, size_t size, uintptr_t offset);
|
||||||
|
virtual void TexDestroy(CGxTex* texId);
|
||||||
|
virtual void IShaderCreate(CGxShader*);
|
||||||
|
virtual void ShaderCreate(CGxShader*[], EGxShTarget, const char*, const char*, int32_t);
|
||||||
|
virtual int32_t StereoEnabled();
|
||||||
|
|
||||||
|
// Member functions
|
||||||
|
CGxDeviceGLSDL();
|
||||||
|
char* IBufLock(CGxBuf*);
|
||||||
|
int32_t IBufUnlock(CGxBuf*);
|
||||||
|
void ISceneBegin();
|
||||||
|
void ISetCaps(const CGxFormat& format);
|
||||||
|
void IShaderBindPixel(CGxShader*);
|
||||||
|
void IShaderBindVertex(CGxShader*);
|
||||||
|
void IShaderConstantsFlush();
|
||||||
|
void IShaderCreatePixel(CGxShader*);
|
||||||
|
void IShaderCreateVertex(CGxShader*);
|
||||||
|
void IStateSetGLSDLDefaults();
|
||||||
|
void IStateSync();
|
||||||
|
void IStateSyncEnables();
|
||||||
|
void IStateSyncIndexPtr();
|
||||||
|
void IStateSyncLights();
|
||||||
|
void IStateSyncMaterial();
|
||||||
|
void IStateSyncScissorRect();
|
||||||
|
void IStateSyncVertexPtrs();
|
||||||
|
void IStateSyncXforms();
|
||||||
|
void ITexCreate(CGxTex*);
|
||||||
|
void ITexSetFlags(CGxTex*);
|
||||||
|
void ITexUpload(CGxTex*);
|
||||||
|
void IXformSetProjection(const C44Matrix&);
|
||||||
|
void IXformSetView(const C44Matrix&);
|
||||||
|
void IXformSetViewport();
|
||||||
|
void PatchPixelShader(CGxShader*);
|
||||||
|
void PatchVertexShader(CGxShader*);
|
||||||
|
void Resize(uint32_t width, uint32_t height);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
50
src/gx/glsdl/GL.cpp
Normal file
50
src/gx/glsdl/GL.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#include "gx/glsdl/GL.hpp"
|
||||||
|
|
||||||
|
TextureFormatInfo k_TextureFormatInfo[GLTF_NUM_TEXTURE_FORMATS] = {
|
||||||
|
{ 0, 0, 0, 0, 0, "GLTF INVALID!!" },
|
||||||
|
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0, 4, "ARGB8888" },
|
||||||
|
{ GL_RGB8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0, 4, "XRGB8888" },
|
||||||
|
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, 0, 4, "RGBA8888" },
|
||||||
|
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 0, 4, "ABGR8888" },
|
||||||
|
{ GL_RGB8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0, 4, "ARGB0888" },
|
||||||
|
{ GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, 0, 3, "RGB888" },
|
||||||
|
{ GL_RGB8, GL_BGR, GL_UNSIGNED_BYTE, 0, 3, "BGR888" },
|
||||||
|
{ GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, 0, 16, "RGBA32F" },
|
||||||
|
{ GL_RGBA16F_ARB, GL_RGBA, GL_HALF_FLOAT, 0, 8, "RGBA16F" },
|
||||||
|
{ GL_RGB16F_ARB, GL_RGB, GL_HALF_FLOAT, 0, 6, "RG16F" },
|
||||||
|
{ GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, 4, "D32" },
|
||||||
|
{ GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, 4, "D24" },
|
||||||
|
{ GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0, 2, "D16" },
|
||||||
|
{ GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_HALF_FLOAT, 0, 4, "DF" },
|
||||||
|
{ GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0, 4, "D24S8" },
|
||||||
|
{ GL_ALPHA8, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, 0, 1, "S8" },
|
||||||
|
{ GL_RGBA4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV, 0, 2, "ARGB4444" },
|
||||||
|
{ GL_RGB5_A1, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0, 2, "ARGB1555" },
|
||||||
|
{ GL_RGB5, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0, 2, "ARGB0555" },
|
||||||
|
{ GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0, 2, "RGB565" },
|
||||||
|
{ GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, 0, 4, "A2RGB10" },
|
||||||
|
{ GL_RGB16, GL_RGB, GL_UNSIGNED_SHORT, 0, 6, "RGB16" },
|
||||||
|
{ GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, 1, "L8" },
|
||||||
|
{ GL_ALPHA8, GL_ALPHA, GL_UNSIGNED_BYTE, 0, 1, "A8" },
|
||||||
|
{ GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 0, 2, "A8L8" },
|
||||||
|
{ GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_BYTE, 1, 8, "DXT1" },
|
||||||
|
{ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE, 1, 16, "DXT3" },
|
||||||
|
{ GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE, 1, 16, "DXT5" }
|
||||||
|
};
|
||||||
|
|
||||||
|
VertexTypeInfo k_VertexTypeInfo[GLVT_NUM_VERTEX_TYPES] = {
|
||||||
|
{ 0, 0, 0, 0, "INVALID" },
|
||||||
|
{ GL_FLOAT, 1, 0, 4, "FLOAT1" },
|
||||||
|
{ GL_FLOAT, 2, 0, 8, "FLOAT2" },
|
||||||
|
{ GL_FLOAT, 3, 0, 12, "FLOAT3" },
|
||||||
|
{ GL_FLOAT, 4, 0, 16, "FLOAT4" },
|
||||||
|
{ GL_UNSIGNED_BYTE, 4, 0, 4, "UBYTE4" },
|
||||||
|
{ GL_UNSIGNED_BYTE, 4, 1, 4, "UBYTE4N" },
|
||||||
|
{ GL_SHORT, 1, 0, 2, "SHORT" },
|
||||||
|
{ GL_SHORT, 2, 0, 4, "SHORT2" },
|
||||||
|
{ GL_SHORT, 4, 0, 8, "SHORT4" },
|
||||||
|
{ GL_SHORT, 2, 1, 4, "SHORT2N" },
|
||||||
|
{ GL_SHORT, 4, 1, 8, "SHORT4N" },
|
||||||
|
{ GL_UNSIGNED_SHORT, 2, 1, 4, "USHORT2N" },
|
||||||
|
{ GL_UNSIGNED_SHORT, 4, 1, 8, "USHORT4N" }
|
||||||
|
};
|
||||||
33
src/gx/glsdl/GL.hpp
Normal file
33
src/gx/glsdl/GL.hpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_HPP
|
||||||
|
#define GX_GL_SDL_GL_HPP
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GL/gl.h>
|
||||||
|
|
||||||
|
#include "gx/glsdl/GLTypes.hpp"
|
||||||
|
|
||||||
|
typedef GLenum GLEnum;
|
||||||
|
|
||||||
|
#define kMAX_VERTEX_ATTRIBS 16
|
||||||
|
|
||||||
|
struct TextureFormatInfo {
|
||||||
|
GLenum m_InternalFormat;
|
||||||
|
GLenum m_DataFormat;
|
||||||
|
GLenum m_DataType;
|
||||||
|
int32_t m_IsCompressed;
|
||||||
|
int32_t m_BytePerPixel;
|
||||||
|
char m_Name[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertexTypeInfo {
|
||||||
|
GLenum m_Type;
|
||||||
|
GLint m_Size;
|
||||||
|
GLboolean m_Normalized;
|
||||||
|
GLint m_ByteSize;
|
||||||
|
const char* m_Name;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern TextureFormatInfo k_TextureFormatInfo[GLTF_NUM_TEXTURE_FORMATS];
|
||||||
|
extern VertexTypeInfo k_VertexTypeInfo[GLVT_NUM_VERTEX_TYPES];
|
||||||
|
|
||||||
|
#endif
|
||||||
45
src/gx/glsdl/GLBatch.hpp
Normal file
45
src/gx/glsdl/GLBatch.hpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_BATCH_HPP
|
||||||
|
#define GX_GL_SDL_GL_BATCH_HPP
|
||||||
|
|
||||||
|
#include "gx/glsdl/GLBuffer.hpp"
|
||||||
|
#include "gx/glsdl/GLShader.hpp"
|
||||||
|
#include "gx/glsdl/GLTexture.hpp"
|
||||||
|
#include "gx/glsdl/GLTypes.hpp"
|
||||||
|
#include "gx/glsdl/GLVertexFormat.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
class GLBatch {
|
||||||
|
public:
|
||||||
|
GLShader* var0;
|
||||||
|
GLShader* var1;
|
||||||
|
GLTexture* textures[16];
|
||||||
|
GLBuffer* var3;
|
||||||
|
GLBuffer* var4[4];
|
||||||
|
uint32_t var5[4];
|
||||||
|
uint32_t var6[4];
|
||||||
|
GLVertexFormat* var7;
|
||||||
|
uint32_t var8;
|
||||||
|
uint32_t var9;
|
||||||
|
uint32_t var10;
|
||||||
|
uint32_t var11;
|
||||||
|
uint32_t var12;
|
||||||
|
uint32_t var13;
|
||||||
|
uint32_t var14;
|
||||||
|
int32_t var15;
|
||||||
|
bool var16;
|
||||||
|
bool var17;
|
||||||
|
GLStates var18;
|
||||||
|
GLTexture2D* colorBuffer[4];
|
||||||
|
GLTexture2D* var20;
|
||||||
|
uint32_t var21[128];
|
||||||
|
char var22[64];
|
||||||
|
char var23[1024];
|
||||||
|
uint32_t var24;
|
||||||
|
bool var25;
|
||||||
|
int64_t var26;
|
||||||
|
int64_t var27;
|
||||||
|
float var28[4096];
|
||||||
|
float var29[1024];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
131
src/gx/glsdl/GLBuffer.cpp
Normal file
131
src/gx/glsdl/GLBuffer.cpp
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
#include "gx/glsdl/GLBuffer.hpp"
|
||||||
|
#include "gx/glsdl/GLSDLDevice.hpp"
|
||||||
|
#include "gx/glsdl/GLPool.hpp"
|
||||||
|
#include "gx/glsdl/GL.hpp"
|
||||||
|
#include <bc/Debug.hpp>
|
||||||
|
#include <bc/Memory.hpp>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
bool GLBuffer::m_UsingVBO = 1;
|
||||||
|
|
||||||
|
GLEnum GLBuffer::s_FlagToAccess[] = {
|
||||||
|
GL_READ_WRITE, // GLMap_None
|
||||||
|
GL_WRITE_ONLY, // GLMap_Unk1
|
||||||
|
GL_WRITE_ONLY, // GLMap_Unk2
|
||||||
|
GL_READ_ONLY // GLMap_Unk3
|
||||||
|
};
|
||||||
|
|
||||||
|
GLBuffer* GLBuffer::Create(GLEnum type, uint32_t size, const void* a3, GLEnum usage, GLEnum format) {
|
||||||
|
GLBuffer* buffer = GLPool<GLBuffer>::Get()->GetNextObject();
|
||||||
|
|
||||||
|
buffer->m_Type = type;
|
||||||
|
buffer->m_Size = size;
|
||||||
|
buffer->m_Usage = usage;
|
||||||
|
buffer->m_IndexFormat = format;
|
||||||
|
|
||||||
|
GLSDLDevice* device = GLSDLDevice::Get();
|
||||||
|
device->BindBuffer(buffer, GL_ZERO);
|
||||||
|
|
||||||
|
if (GLBuffer::m_UsingVBO) {
|
||||||
|
glBufferData(buffer->m_Type, buffer->m_Size, a3, buffer->m_Usage);
|
||||||
|
// glBufferParameteriAPPLE(buffer->m_Type, GL_BUFFER_SERIALIZED_MODIFY_APPLE, buffer->m_Usage - GL_DYNAMIC_DRAW > 1);
|
||||||
|
// glBufferParameteriAPPLE(buffer->m_Type, GL_BUFFER_FLUSHING_UNMAP_APPLE, 0);
|
||||||
|
} else {
|
||||||
|
Blizzard::Memory::Free(buffer->m_Data);
|
||||||
|
|
||||||
|
void* data = Blizzard::Memory::Allocate(size);
|
||||||
|
if (a3) {
|
||||||
|
memcpy(data, a3, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->m_Data = reinterpret_cast<char*>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// buffer->m_TimeStamp = Blizzard::Time::GetTimestamp();
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLBuffer::GLBuffer() : GLObject() {
|
||||||
|
if (GLBuffer::m_UsingVBO) {
|
||||||
|
this->m_BufferID = GLPool<GLBuffer>::Get()->GetNextName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char* GLBuffer::Map(uint32_t offset, uint32_t size, eMapFlag flag) {
|
||||||
|
BLIZZARD_ASSERT((offset + size) <= this->m_Size);
|
||||||
|
BLIZZARD_ASSERT(this->m_Usage == GL_STATIC_DRAW || flag != GLMap_None);
|
||||||
|
BLIZZARD_ASSERT(this->m_MapFlag == GLMap_NotMapped);
|
||||||
|
BLIZZARD_ASSERT(flag >= GLMap_None && flag < GLMap_Count);
|
||||||
|
|
||||||
|
this->m_MapOffset = offset;
|
||||||
|
this->m_MapSize = offset + size == 0 ? this->m_Size : size;
|
||||||
|
this->m_MapFlag = flag;
|
||||||
|
|
||||||
|
if (GLBuffer::m_UsingVBO) {
|
||||||
|
GLSDLDevice* device = GLSDLDevice::Get();
|
||||||
|
device->BindBuffer(this, GL_ZERO);
|
||||||
|
|
||||||
|
if (flag == GLMap_Unk2) {
|
||||||
|
if (this->m_Usage - GL_DYNAMIC_DRAW <= 1) {
|
||||||
|
BLIZZARD_ASSERT(offset == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBufferData(this->m_Type, this->m_Size, nullptr, this->m_Usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* data = glMapBuffer(this->m_Type, GLBuffer::s_FlagToAccess[flag]);
|
||||||
|
this->m_Data = reinterpret_cast<char*>(data);
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT(this->m_Data != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this->m_Data + offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBuffer::ReleaseObject() {
|
||||||
|
if (GLBuffer::m_UsingVBO) {
|
||||||
|
if (this->m_Type) {
|
||||||
|
GLSDLDevice* device = GLSDLDevice::Get();
|
||||||
|
device->BindBuffer(this, GL_ZERO);
|
||||||
|
|
||||||
|
glBufferData(this->m_Type, 1, nullptr, this->m_Usage);
|
||||||
|
|
||||||
|
// TODO GLPool<GLBuffer>::GLObjectPool::Push((GLPool<GLBuffer>::m_pool + 32776), this);
|
||||||
|
} else {
|
||||||
|
// TODO GLPool<GLBuffer>::GLObjectPool::Push((GLPool<GLBuffer>::m_pool + 32776), this);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Blizzard::Memory::Free(this->m_Data);
|
||||||
|
this->m_Data = nullptr;
|
||||||
|
|
||||||
|
// TODO GLPool<GLBuffer>::GLObjectPool::Push((GLPool<GLBuffer>::m_pool + 32776), this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBuffer::Unmap(uint32_t size) {
|
||||||
|
BLIZZARD_ASSERT((this->m_MapOffset + size) <= m_Size);
|
||||||
|
|
||||||
|
GLSDLDevice* device = GLSDLDevice::Get();
|
||||||
|
device->BindBuffer(this, GL_ZERO);
|
||||||
|
|
||||||
|
if (this->m_MapFlag != 3) {
|
||||||
|
if (GLBuffer::m_UsingVBO) {
|
||||||
|
glFlushMappedBufferRange(this->m_Type, this->m_MapOffset, size ? size : this->m_MapSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// this->m_TimeStamp = Blizzard::Time::GetTimestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GLBuffer::m_UsingVBO) {
|
||||||
|
this->m_MapFlag = GLMap_NotMapped;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLboolean result = glUnmapBuffer(this->m_Type);
|
||||||
|
BLIZZARD_ASSERT(result);
|
||||||
|
|
||||||
|
this->m_MapFlag = GLMap_NotMapped;
|
||||||
|
}
|
||||||
47
src/gx/glsdl/GLBuffer.hpp
Normal file
47
src/gx/glsdl/GLBuffer.hpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_BUFFER_HPP
|
||||||
|
#define GX_GL_SDL_GL_BUFFER_HPP
|
||||||
|
|
||||||
|
#include "gx/glsdl/GL.hpp"
|
||||||
|
#include "gx/glsdl/GLObject.hpp"
|
||||||
|
#include "gx/glsdl/GLTypes.hpp"
|
||||||
|
|
||||||
|
class GLBuffer : public GLObject {
|
||||||
|
public:
|
||||||
|
// Types
|
||||||
|
enum eMapFlag {
|
||||||
|
GLMap_NotMapped = -1,
|
||||||
|
GLMap_None = 0,
|
||||||
|
GLMap_Unk1 = 1,
|
||||||
|
GLMap_Unk2 = 2,
|
||||||
|
GLMap_Unk3 = 3,
|
||||||
|
GLMap_Count = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
// Static variables
|
||||||
|
static bool m_UsingVBO;
|
||||||
|
static GLEnum s_FlagToAccess[];
|
||||||
|
|
||||||
|
// Static functions
|
||||||
|
static GLBuffer* Create(GLEnum, uint32_t, const void*, GLEnum, GLEnum);
|
||||||
|
|
||||||
|
// Member variables
|
||||||
|
uint32_t m_Size = 0;
|
||||||
|
GLEnum m_Type = 0;
|
||||||
|
GLEnum m_Usage = 0;
|
||||||
|
uint32_t m_BufferID = 0;
|
||||||
|
GLEnum m_IndexFormat = 0;
|
||||||
|
char* m_Data = nullptr;
|
||||||
|
uint32_t m_MapOffset = 0;
|
||||||
|
uint32_t m_MapSize = 0;
|
||||||
|
uint32_t m_MapFlag = GLMap_NotMapped;
|
||||||
|
|
||||||
|
// Virtual member functions
|
||||||
|
virtual void ReleaseObject();
|
||||||
|
|
||||||
|
// Member functions
|
||||||
|
GLBuffer();
|
||||||
|
char* Map(uint32_t, uint32_t, eMapFlag);
|
||||||
|
void Unmap(uint32_t);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
8
src/gx/glsdl/GLBufferPool.hpp
Normal file
8
src/gx/glsdl/GLBufferPool.hpp
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_BUFFER_POOL_HPP
|
||||||
|
#define GX_GL_SDL_GL_BUFFER_POOL_HPP
|
||||||
|
|
||||||
|
class GLBufferPool {
|
||||||
|
public:
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
8
src/gx/glsdl/GLDebugMipmap2D.hpp
Normal file
8
src/gx/glsdl/GLDebugMipmap2D.hpp
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_DEBUG_MIPMAP_2D_HPP
|
||||||
|
#define GX_GL_SDL_GL_DEBUG_MIPMAP_2D_HPP
|
||||||
|
|
||||||
|
class GLDebugMipmap2D {
|
||||||
|
public:
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
150
src/gx/glsdl/GLFramebuffer.cpp
Normal file
150
src/gx/glsdl/GLFramebuffer.cpp
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
#include "gx/glsdl/GLFramebuffer.hpp"
|
||||||
|
#include "gx/glsdl/GLSDLDevice.hpp"
|
||||||
|
#include "gx/glsdl/GLMipmap.hpp"
|
||||||
|
#include "gx/glsdl/GLPool.hpp"
|
||||||
|
#include "gx/glsdl/GLTypes.hpp"
|
||||||
|
#include <bc/Debug.hpp>
|
||||||
|
|
||||||
|
GLFramebuffer* GLFramebuffer::Create(bool a1) {
|
||||||
|
GLFramebuffer* framebuffer = new GLFramebuffer(a1);
|
||||||
|
|
||||||
|
if (!a1) {
|
||||||
|
// TODO
|
||||||
|
// BLIZZARD_ASSERT(framebuffer->m_FramebufferID >= PoolStats<GLFramebuffer>::NAME_POOL_FIRST_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT(framebuffer->m_NumAttach == 0);
|
||||||
|
|
||||||
|
framebuffer->m_Width = 0;
|
||||||
|
framebuffer->m_Height = 0;
|
||||||
|
framebuffer->m_Device = GLSDLDevice::Get();
|
||||||
|
|
||||||
|
return framebuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFramebuffer::GLFramebuffer(bool a1) : GLObject() {
|
||||||
|
if (!a1) {
|
||||||
|
this->m_FramebufferID = GLPool<GLFramebuffer>::Get()->GetNextName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLFramebuffer::Attach(GLMipmap* image, GLenum a3, int32_t a4) {
|
||||||
|
BLIZZARD_ASSERT(this->m_Device == GLSDLDevice::Get());
|
||||||
|
|
||||||
|
if (!image) {
|
||||||
|
this->Detach(a3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a3 == GL_DEPTH_STENCIL) {
|
||||||
|
BLIZZARD_ASSERT(image->GetFormat() == GLTF_D24S8);
|
||||||
|
|
||||||
|
this->Attach(image, GL_DEPTH_ATTACHMENT, 0);
|
||||||
|
this->Attach(image, GL_STENCIL_ATTACHMENT, 0);
|
||||||
|
|
||||||
|
(*image->m_AttachPoints)[this->m_FramebufferID].point = GL_DEPTH_STENCIL;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t index;
|
||||||
|
|
||||||
|
if (a3 == GL_DEPTH_ATTACHMENT) {
|
||||||
|
index = 4;
|
||||||
|
} else if (a3 == GL_STENCIL_ATTACHMENT) {
|
||||||
|
index = 5;
|
||||||
|
} else {
|
||||||
|
index = a3 - GL_COLOR_ATTACHMENT0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT(index < MAX_ATTACHMENT);
|
||||||
|
|
||||||
|
GLMipmap* oldImage = this->m_Attachments[index];
|
||||||
|
|
||||||
|
if (image != oldImage) {
|
||||||
|
if (oldImage) {
|
||||||
|
oldImage->Detach(this, a3, true);
|
||||||
|
} else {
|
||||||
|
++this->m_NumAttach;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->m_Attachments[index] = image;
|
||||||
|
|
||||||
|
this->m_Width = image->m_Width;
|
||||||
|
this->m_Height = image->m_Height;
|
||||||
|
|
||||||
|
image->Attach(this, a3, a4);
|
||||||
|
this->m_Device->Sub38460(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT((*image->m_AttachPoints)[m_FramebufferID].framebuffer == this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLFramebuffer::Detach(GLenum a2) {
|
||||||
|
int32_t v2 = a2;
|
||||||
|
int32_t index;
|
||||||
|
|
||||||
|
if (a2 == GL_DEPTH_STENCIL) {
|
||||||
|
index = 5;
|
||||||
|
v2 = GL_STENCIL_ATTACHMENT;
|
||||||
|
this->Detach(GL_DEPTH_ATTACHMENT);
|
||||||
|
} else if (a2 == GL_DEPTH_ATTACHMENT) {
|
||||||
|
index = 4;
|
||||||
|
} else if (a2 == GL_STENCIL_ATTACHMENT) {
|
||||||
|
index = 5;
|
||||||
|
} else {
|
||||||
|
index = a2 - GL_COLOR_ATTACHMENT0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT(index < MAX_ATTACHMENT);
|
||||||
|
|
||||||
|
GLMipmap* oldImage = this->m_Attachments[index];
|
||||||
|
|
||||||
|
if (oldImage) {
|
||||||
|
oldImage->Detach(this, v2, 0);
|
||||||
|
|
||||||
|
--this->m_NumAttach;
|
||||||
|
|
||||||
|
this->m_Attachments[index] = 0;
|
||||||
|
|
||||||
|
if (this->m_Device == GLSDLDevice::Get()) {
|
||||||
|
this->m_Device->Sub38460(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->m_NumAttach == 0) {
|
||||||
|
this->m_Width = 0;
|
||||||
|
this->m_Height = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLMipmap* GLFramebuffer::GetAttachment(GLEnum a2) {
|
||||||
|
int32_t index;
|
||||||
|
|
||||||
|
if (a2 == GL_DEPTH_ATTACHMENT) {
|
||||||
|
index = 4;
|
||||||
|
} else if (a2 == GL_STENCIL_ATTACHMENT) {
|
||||||
|
index = 5;
|
||||||
|
} else {
|
||||||
|
index = a2 - GL_COLOR_ATTACHMENT0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT(index < MAX_ATTACHMENT);
|
||||||
|
|
||||||
|
return this->m_Attachments[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t GLFramebuffer::GetSampleCount() {
|
||||||
|
return this->m_FramebufferID
|
||||||
|
? 1
|
||||||
|
: this->m_Device->m_Context.GetSampleCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GLFramebuffer::IsValid() {
|
||||||
|
auto status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
|
||||||
|
return status == GL_FRAMEBUFFER_COMPLETE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLFramebuffer::ReleaseObject() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
38
src/gx/glsdl/GLFramebuffer.hpp
Normal file
38
src/gx/glsdl/GLFramebuffer.hpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_FRAMEBUFFER_HPP
|
||||||
|
#define GX_GL_SDL_GL_FRAMEBUFFER_HPP
|
||||||
|
|
||||||
|
#include "gx/glsdl/GL.hpp"
|
||||||
|
#include "gx/glsdl/GLObject.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#define MAX_ATTACHMENT 6
|
||||||
|
|
||||||
|
class GLSDLDevice;
|
||||||
|
class GLMipmap;
|
||||||
|
|
||||||
|
class GLFramebuffer : public GLObject {
|
||||||
|
public:
|
||||||
|
// Static functions
|
||||||
|
static GLFramebuffer* Create(bool);
|
||||||
|
|
||||||
|
// Member variables
|
||||||
|
int32_t m_Width = 0;
|
||||||
|
int32_t m_Height = 0;
|
||||||
|
uint32_t m_FramebufferID = 0;
|
||||||
|
GLSDLDevice* m_Device;
|
||||||
|
GLMipmap* m_Attachments[6] = {};
|
||||||
|
uint32_t m_NumAttach = 0;
|
||||||
|
|
||||||
|
// Virtual member functions
|
||||||
|
virtual void ReleaseObject();
|
||||||
|
|
||||||
|
// Member functions
|
||||||
|
GLFramebuffer(bool);
|
||||||
|
void Attach(GLMipmap*, GLenum, int32_t);
|
||||||
|
void Detach(GLenum);
|
||||||
|
GLMipmap* GetAttachment(GLEnum);
|
||||||
|
int32_t GetSampleCount(void);
|
||||||
|
bool IsValid();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
7
src/gx/glsdl/GLGLSLProgram.cpp
Normal file
7
src/gx/glsdl/GLGLSLProgram.cpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include "gx/glsdl/GLGLSLProgram.hpp"
|
||||||
|
#include "gx/glsdl/GLShader.hpp"
|
||||||
|
|
||||||
|
GLGLSLProgram* GLGLSLProgram::Find(GLShader* a1, GLShader* a2) {
|
||||||
|
// TODO
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
14
src/gx/glsdl/GLGLSLProgram.hpp
Normal file
14
src/gx/glsdl/GLGLSLProgram.hpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_GLSL_PROGRAM_HPP
|
||||||
|
#define GX_GL_SDL_GL_GLSL_PROGRAM_HPP
|
||||||
|
|
||||||
|
#include "gx/glsdl/GLObject.hpp"
|
||||||
|
|
||||||
|
class GLShader;
|
||||||
|
|
||||||
|
class GLGLSLProgram : public GLObject {
|
||||||
|
public:
|
||||||
|
// Static functions
|
||||||
|
static GLGLSLProgram* Find(GLShader*, GLShader*);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
480
src/gx/glsdl/GLMipmap.cpp
Normal file
480
src/gx/glsdl/GLMipmap.cpp
Normal file
@ -0,0 +1,480 @@
|
|||||||
|
#include "gx/glsdl/GLMipmap.hpp"
|
||||||
|
#include "gx/glsdl/GLSDLDevice.hpp"
|
||||||
|
#include "gx/glsdl/GLFramebuffer.hpp"
|
||||||
|
#include <bc/Debug.hpp>
|
||||||
|
|
||||||
|
int32_t GLMipmap::GetDepthBits() {
|
||||||
|
return this->m_DepthBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLMipmap::Attach(GLFramebuffer* framebuffer, GLenum attachPoint, int32_t a4) {
|
||||||
|
if (!this->m_AttachPoints) {
|
||||||
|
this->m_AttachPoints = new std::vector<GLAttachPoint>();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& attachPoints = *this->m_AttachPoints;
|
||||||
|
auto framebufferID = framebuffer->m_FramebufferID;
|
||||||
|
|
||||||
|
if (framebufferID >= attachPoints.size()) {
|
||||||
|
attachPoints.resize(framebufferID + 1);
|
||||||
|
} else {
|
||||||
|
BLIZZARD_ASSERT(attachPoints[framebufferID].framebuffer != framebuffer || attachPoints[framebufferID].point != attachPoint);
|
||||||
|
|
||||||
|
auto& attach = attachPoints[framebufferID];
|
||||||
|
|
||||||
|
if (
|
||||||
|
attach.point
|
||||||
|
&& (attach.point != GL_DEPTH_ATTACHMENT || attachPoint != GL_STENCIL_ATTACHMENT)
|
||||||
|
&& (attach.point != GL_STENCIL_ATTACHMENT || attachPoint != GL_DEPTH_ATTACHMENT)
|
||||||
|
) {
|
||||||
|
framebuffer->Detach(attach.point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLSDLDevice* device = GLSDLDevice::Get();
|
||||||
|
|
||||||
|
auto currentTarget = device->GetCurrentTarget();
|
||||||
|
device->BindFramebuffer(framebuffer);
|
||||||
|
|
||||||
|
if (framebufferID) {
|
||||||
|
if (this->m_Target == GL_TEXTURE_3D) {
|
||||||
|
glFramebufferTexture3DEXT(
|
||||||
|
GL_FRAMEBUFFER,
|
||||||
|
attachPoint,
|
||||||
|
GL_TEXTURE_3D,
|
||||||
|
this->m_Texture->m_TextureID,
|
||||||
|
this->m_Level,
|
||||||
|
a4
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
glFramebufferTexture2DEXT(
|
||||||
|
GL_FRAMEBUFFER,
|
||||||
|
attachPoint,
|
||||||
|
this->m_Target,
|
||||||
|
this->m_Texture->m_TextureID,
|
||||||
|
this->m_Level
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attachPoint == GL_DEPTH_ATTACHMENT && !this->m_DepthBits) {
|
||||||
|
GLint depthBits = 0;
|
||||||
|
glGetIntegerv(GL_DEPTH_BITS, &depthBits);
|
||||||
|
this->m_DepthBits = depthBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
device->BindFramebuffer(currentTarget);
|
||||||
|
|
||||||
|
auto& attach = attachPoints[framebufferID];
|
||||||
|
attach.framebuffer = framebuffer;
|
||||||
|
attach.zOffset = a4;
|
||||||
|
|
||||||
|
if (
|
||||||
|
(attach.point != GL_DEPTH_ATTACHMENT || attachPoint != GL_STENCIL_ATTACHMENT)
|
||||||
|
&& (attach.point != GL_STENCIL_ATTACHMENT || attachPoint != GL_DEPTH_ATTACHMENT)
|
||||||
|
) {
|
||||||
|
attach.point = attachPoint;
|
||||||
|
} else {
|
||||||
|
attach.point = GL_DEPTH_STENCIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLMipmap::Detach(GLFramebuffer* framebuffer, GLenum attachPoint, bool a4) {
|
||||||
|
GLuint framebufferID = framebuffer->m_FramebufferID;
|
||||||
|
|
||||||
|
auto& attachPoints = *this->m_AttachPoints;
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT(attachPoints.size() >= framebufferID);
|
||||||
|
BLIZZARD_ASSERT(attachPoints[framebufferID].framebuffer == framebuffer);
|
||||||
|
|
||||||
|
if (!a4 && framebufferID) {
|
||||||
|
GLSDLDevice* v12 = GLSDLDevice::Get();
|
||||||
|
GLFramebuffer* v14 = v12->GetCurrentTarget();
|
||||||
|
v12->BindFramebuffer(framebuffer);
|
||||||
|
|
||||||
|
if (this->m_Target == GL_TEXTURE_3D) {
|
||||||
|
glFramebufferTexture3DEXT(GL_FRAMEBUFFER, attachPoint, GL_TEXTURE_3D, 0, 0, 0);
|
||||||
|
} else {
|
||||||
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER, attachPoint, this->m_Target, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
v12->BindFramebuffer(v14);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLAttachPoint* v9 = &attachPoints[framebufferID];
|
||||||
|
|
||||||
|
if (v9->point == GL_DEPTH_STENCIL) {
|
||||||
|
BLIZZARD_ASSERT(this->GetFormat() == GLTF_D24S8);
|
||||||
|
|
||||||
|
if (attachPoint == GL_DEPTH_ATTACHMENT) {
|
||||||
|
v9->point = GL_STENCIL_ATTACHMENT;
|
||||||
|
} else if (attachPoint == GL_STENCIL_ATTACHMENT) {
|
||||||
|
v9->point = GL_DEPTH_ATTACHMENT;
|
||||||
|
} else {
|
||||||
|
BLIZZARD_ASSERT(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
BLIZZARD_ASSERT(attachPoints[framebufferID].point == attachPoint);
|
||||||
|
|
||||||
|
v9->framebuffer = 0;
|
||||||
|
v9->point = 0;
|
||||||
|
v9->zOffset = 0;
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// this->m_Texture->m_TimeStamp = Blizzard::Time::GetTimestamp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLMipmap::DetachAll() {
|
||||||
|
if (!this->m_AttachPoints) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& attachPoints = *this->m_AttachPoints;
|
||||||
|
for (int32_t i = 0; i < attachPoints.size(); i++) {
|
||||||
|
BLIZZARD_ASSERT(attachPoints[i].point != GL_ZERO);
|
||||||
|
BLIZZARD_ASSERT(attachPoints[i].framebuffer->m_FramebufferID == i);
|
||||||
|
|
||||||
|
attachPoints[i].framebuffer->Detach(attachPoints[i].point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLTextureFormat GLMipmap::GetFormat() {
|
||||||
|
return this->m_Texture->GetFormat();
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureFormatInfo& GLMipmap::GetFormatInfo() {
|
||||||
|
return this->m_Texture->GetFormatInfo();
|
||||||
|
};
|
||||||
|
|
||||||
|
uint16_t GLMipmap::GetHeight() {
|
||||||
|
return this->m_Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t GLMipmap::GetPitch() {
|
||||||
|
int32_t bpp = this->GetFormatInfo().m_BytePerPixel;
|
||||||
|
int32_t v4 = this->m_Texture->var12 >> this->m_Level;
|
||||||
|
return v4 >= bpp ? v4 : bpp;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLTexture* GLMipmap::GetTexture() {
|
||||||
|
return this->m_Texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t GLMipmap::GetTextureID() {
|
||||||
|
return this->m_Texture->m_TextureID;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t GLMipmap::GetWidth() {
|
||||||
|
return this->m_Width;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* GLMipmap::Map(GLEnum mode, const GLBox* area) {
|
||||||
|
BLIZZARD_ASSERT(!this->m_Texture->IsSystemBuffer());
|
||||||
|
BLIZZARD_ASSERT(this->m_Data != nullptr);
|
||||||
|
BLIZZARD_ASSERT(!this->m_Texture->IsRenderTarget());
|
||||||
|
BLIZZARD_ASSERT(mode != GL_ZERO);
|
||||||
|
BLIZZARD_ASSERT(this->m_MapParams == nullptr);
|
||||||
|
|
||||||
|
if (mode != GL_READ_ONLY) {
|
||||||
|
this->m_Texture->m_MappedMipmaps++;
|
||||||
|
}
|
||||||
|
|
||||||
|
MapParams* mapParams = new MapParams();
|
||||||
|
this->m_MapParams = mapParams;
|
||||||
|
|
||||||
|
if (area) {
|
||||||
|
BLIZZARD_ASSERT(area->width > 0);
|
||||||
|
BLIZZARD_ASSERT(area->height > 0);
|
||||||
|
BLIZZARD_ASSERT(area->depth > 0);
|
||||||
|
BLIZZARD_ASSERT(!this->GetFormatInfo().m_IsCompressed || ((area->top & 0x3) == 0 && (area->left & 0x3) == 0 && (area->width & 0x3) == 0 && (area->height & 0x3) == 0));
|
||||||
|
BLIZZARD_ASSERT((area->height + area->top) <= this->m_Height);
|
||||||
|
BLIZZARD_ASSERT((area->depth + area->front) <= this->m_Depth);
|
||||||
|
BLIZZARD_ASSERT((area->width + area->left) <= this->m_Width);
|
||||||
|
|
||||||
|
mapParams->m_MapArea = {
|
||||||
|
area->left,
|
||||||
|
area->top,
|
||||||
|
area->front,
|
||||||
|
area->width,
|
||||||
|
area->height,
|
||||||
|
area->depth
|
||||||
|
};
|
||||||
|
|
||||||
|
int32_t size = this->GetFormatInfo().m_BytePerPixel
|
||||||
|
* this->m_Width
|
||||||
|
* mapParams->m_MapArea.depth
|
||||||
|
* mapParams->m_MapArea.height;
|
||||||
|
|
||||||
|
mapParams->m_Size = this->GetFormatInfo().m_IsCompressed
|
||||||
|
? size >> 4
|
||||||
|
: size;
|
||||||
|
|
||||||
|
mapParams->m_Unk7 = (this->GetFormatInfo().m_BytePerPixel * mapParams->m_MapArea.left)
|
||||||
|
>> this->GetFormatInfo().m_IsCompressed ? 2 : 0;
|
||||||
|
} else {
|
||||||
|
mapParams->m_MapArea = {
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
this->m_Width,
|
||||||
|
this->m_Height,
|
||||||
|
this->m_Depth
|
||||||
|
};
|
||||||
|
|
||||||
|
mapParams->m_Size = this->m_Size;
|
||||||
|
|
||||||
|
mapParams->m_Unk7 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mapParams->m_MapMode = mode;
|
||||||
|
|
||||||
|
int32_t rowPitch = this->GetPitch();
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT(((mapParams->m_MapArea.top * rowPitch) + mapParams->m_MapArea.left * this->GetFormatInfo().m_BytePerPixel) < (this->GetFormatInfo().m_IsCompressed ? this->m_Size << 4 : this->m_Size));
|
||||||
|
|
||||||
|
int32_t v22 = rowPitch * this->m_Height;
|
||||||
|
if (this->GetFormatInfo().m_IsCompressed) {
|
||||||
|
v22 >>= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* v24 = this->m_Data
|
||||||
|
+ ((mapParams->m_MapArea.top * rowPitch) >> (this->GetFormatInfo().m_IsCompressed ? 2 : 0))
|
||||||
|
+ (mapParams->m_MapArea.front * v22);
|
||||||
|
|
||||||
|
mapParams->m_Unk8 = v24;
|
||||||
|
|
||||||
|
return v24 + mapParams->m_Unk7;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* GLMipmap::Map(GLEnum mode, const GLRect* rect) {
|
||||||
|
if (rect) {
|
||||||
|
GLBox area = {
|
||||||
|
rect->left,
|
||||||
|
rect->top,
|
||||||
|
0,
|
||||||
|
rect->width,
|
||||||
|
rect->height,
|
||||||
|
1
|
||||||
|
};
|
||||||
|
|
||||||
|
return this->Map(mode, &area);
|
||||||
|
} else {
|
||||||
|
return this->Map(mode, static_cast<GLBox*>(nullptr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLMipmap::ReleaseObject() {
|
||||||
|
BLIZZARD_ASSERT(this->m_MapParams == nullptr);
|
||||||
|
|
||||||
|
this->RemoveDebugMipmap();
|
||||||
|
this->DetachAll();
|
||||||
|
|
||||||
|
if (this->m_AttachPoints) {
|
||||||
|
delete this->m_AttachPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->m_AttachPoints = nullptr;
|
||||||
|
this->m_Unk24 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLMipmap::RemoveDebugMipmap() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLMipmap::ResetData(GLEnum target, int32_t level, unsigned char* data) {
|
||||||
|
BLIZZARD_ASSERT(this->m_Target != GL_TEXTURE_3D || !this->GetFormatInfo().m_IsCompressed);
|
||||||
|
|
||||||
|
this->m_Target = target;
|
||||||
|
this->m_Level = level;
|
||||||
|
this->m_Data = data;
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT(this->GetFormat() != GLTF_INVALID);
|
||||||
|
BLIZZARD_ASSERT(this->GetFormat() < GLTF_NUM_TEXTURE_FORMATS);
|
||||||
|
|
||||||
|
if (!this->m_Texture->IsSystemBuffer() && this->m_Texture->IsRenderTarget()) {
|
||||||
|
BLIZZARD_ASSERT(!this->GetFormatInfo().m_IsCompressed);
|
||||||
|
|
||||||
|
this->TexImage(nullptr);
|
||||||
|
this->m_Unk24 = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLMipmap::ResetSize(uint32_t width, uint32_t height, uint32_t depth) {
|
||||||
|
this->m_Width = width ? width : 1;
|
||||||
|
this->m_Height = height ? height : 1;
|
||||||
|
this->m_Depth = depth ? depth : 1;
|
||||||
|
|
||||||
|
if (this->GetFormatInfo().m_IsCompressed) {
|
||||||
|
BLIZZARD_ASSERT(this->m_Depth == 1);
|
||||||
|
|
||||||
|
this->m_Width = (this->m_Width + 3) & 0xFFFC;
|
||||||
|
this->m_Height = (this->m_Height + 3) & 0xFFFC;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t v11 = this->GetFormatInfo().m_BytePerPixel;
|
||||||
|
uint32_t v20 = this->m_Texture->var12 >> this->m_Level;
|
||||||
|
|
||||||
|
if (v20 >= v11) {
|
||||||
|
v11 = v20;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t v15 = v11 * this->m_Height;
|
||||||
|
uint32_t v12;
|
||||||
|
|
||||||
|
if (this->GetFormatInfo().m_IsCompressed) {
|
||||||
|
v12 = v15 >> 2;
|
||||||
|
} else {
|
||||||
|
v12 = v15;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->m_Size = this->m_Depth * v12;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLMipmap::TexImage(const void* pixels) {
|
||||||
|
BLIZZARD_ASSERT((this->m_Texture->IsRenderTarget() || pixels != nullptr) && GLSDLDevice::Get()->GetVertexArrayStates().buffers[eGLBT_PIXEL_UNPACK] == 0);
|
||||||
|
|
||||||
|
if (this->m_Target == GL_TEXTURE_3D) {
|
||||||
|
glTexImage3D(
|
||||||
|
GL_TEXTURE_3D,
|
||||||
|
this->m_Level,
|
||||||
|
this->GetFormatInfo().m_InternalFormat,
|
||||||
|
this->m_Width,
|
||||||
|
this->m_Height,
|
||||||
|
this->m_Depth,
|
||||||
|
0,
|
||||||
|
this->GetFormatInfo().m_DataFormat,
|
||||||
|
this->GetFormatInfo().m_DataType,
|
||||||
|
pixels
|
||||||
|
);
|
||||||
|
} else if (this->GetFormatInfo().m_IsCompressed) {
|
||||||
|
glCompressedTexImage2D(
|
||||||
|
this->m_Target,
|
||||||
|
this->m_Level,
|
||||||
|
this->GetFormatInfo().m_InternalFormat,
|
||||||
|
this->m_Width,
|
||||||
|
this->m_Height,
|
||||||
|
0,
|
||||||
|
this->m_Size,
|
||||||
|
pixels
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
glTexImage2D(
|
||||||
|
this->m_Target,
|
||||||
|
this->m_Level,
|
||||||
|
this->GetFormatInfo().m_InternalFormat,
|
||||||
|
this->m_Width,
|
||||||
|
this->m_Height,
|
||||||
|
0,
|
||||||
|
this->GetFormatInfo().m_DataFormat,
|
||||||
|
this->GetFormatInfo().m_DataType,
|
||||||
|
pixels
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLMipmap::TexSubImage(const GLBox& a2, int32_t size, const void* pixels) {
|
||||||
|
BLIZZARD_ASSERT(!this->m_Texture->IsRenderTarget() && pixels != nullptr && GLSDLDevice::Get()->GetVertexArrayStates().buffers[eGLBT_PIXEL_UNPACK] == 0);
|
||||||
|
|
||||||
|
if (this->m_Target == GL_TEXTURE_3D) {
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, this->m_Width);
|
||||||
|
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, this->m_Height);
|
||||||
|
|
||||||
|
glTexSubImage3D(
|
||||||
|
this->m_Target,
|
||||||
|
this->m_Level,
|
||||||
|
a2.left,
|
||||||
|
a2.top,
|
||||||
|
a2.front,
|
||||||
|
a2.width,
|
||||||
|
a2.height,
|
||||||
|
a2.depth,
|
||||||
|
this->GetFormatInfo().m_DataFormat,
|
||||||
|
this->GetFormatInfo().m_DataType,
|
||||||
|
pixels
|
||||||
|
);
|
||||||
|
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||||
|
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
|
||||||
|
} else if (this->GetFormatInfo().m_IsCompressed) {
|
||||||
|
glCompressedTexSubImage2D(
|
||||||
|
this->m_Target,
|
||||||
|
this->m_Level,
|
||||||
|
0,
|
||||||
|
a2.top,
|
||||||
|
this->m_Width,
|
||||||
|
a2.height,
|
||||||
|
this->GetFormatInfo().m_InternalFormat,
|
||||||
|
size,
|
||||||
|
pixels
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, this->m_Width);
|
||||||
|
|
||||||
|
glTexSubImage2D(
|
||||||
|
this->m_Target,
|
||||||
|
this->m_Level,
|
||||||
|
a2.left,
|
||||||
|
a2.top,
|
||||||
|
a2.width,
|
||||||
|
a2.height,
|
||||||
|
this->GetFormatInfo().m_DataFormat,
|
||||||
|
this->GetFormatInfo().m_DataType,
|
||||||
|
pixels
|
||||||
|
);
|
||||||
|
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLMipmap::Unmap() {
|
||||||
|
BLIZZARD_ASSERT(!this->m_Texture->IsRenderTarget());
|
||||||
|
BLIZZARD_ASSERT(!this->m_Texture->IsSystemBuffer());
|
||||||
|
BLIZZARD_ASSERT(this->m_MapParams != nullptr);
|
||||||
|
|
||||||
|
if (this->m_MapParams->m_MapMode == GL_READ_ONLY) {
|
||||||
|
delete this->m_MapParams;
|
||||||
|
this->m_MapParams = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLSDLDevice* device = GLSDLDevice::Get();
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT(this->m_Texture->m_MappedMipmaps > 0);
|
||||||
|
|
||||||
|
this->Unmap(this->m_MapParams);
|
||||||
|
|
||||||
|
this->m_MapParams = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLMipmap::Unmap(MapParams* mapParams) {
|
||||||
|
BLIZZARD_ASSERT(mapParams != nullptr);
|
||||||
|
|
||||||
|
this->m_Texture->Bind(nullptr, 0);
|
||||||
|
|
||||||
|
if (this->m_Unk24) {
|
||||||
|
if (this->GetFormatInfo().m_IsCompressed) {
|
||||||
|
GLBox area = {
|
||||||
|
0,
|
||||||
|
mapParams->m_MapArea.top,
|
||||||
|
mapParams->m_MapArea.front,
|
||||||
|
this->m_Width,
|
||||||
|
mapParams->m_MapArea.height,
|
||||||
|
mapParams->m_MapArea.depth
|
||||||
|
};
|
||||||
|
|
||||||
|
this->TexSubImage(area, mapParams->m_Size, mapParams->m_Unk8);
|
||||||
|
} else {
|
||||||
|
this->TexSubImage(mapParams->m_MapArea, mapParams->m_Size, mapParams->m_Unk8 + mapParams->m_Unk7);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this->TexImage(this->m_Data);
|
||||||
|
this->m_Unk24 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete mapParams;
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
this->m_Texture->m_MappedMipmaps--;
|
||||||
|
}
|
||||||
62
src/gx/glsdl/GLMipmap.hpp
Normal file
62
src/gx/glsdl/GLMipmap.hpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_MIPMAP_HPP
|
||||||
|
#define GX_GL_SDL_GL_MIPMAP_HPP
|
||||||
|
|
||||||
|
#include "gx/glsdl/GL.hpp"
|
||||||
|
#include "gx/glsdl/GLTypes.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class GLFramebuffer;
|
||||||
|
class GLTexture;
|
||||||
|
|
||||||
|
class GLMipmap {
|
||||||
|
public:
|
||||||
|
// Types
|
||||||
|
struct MapParams {
|
||||||
|
GLBox m_MapArea;
|
||||||
|
int32_t m_MapMode = 0;
|
||||||
|
int32_t m_Unk7 = 0;
|
||||||
|
unsigned char* m_Unk8 = nullptr;
|
||||||
|
int32_t m_Size = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Member variables
|
||||||
|
GLTexture* m_Texture = nullptr;
|
||||||
|
uint16_t m_Width = 0;
|
||||||
|
uint16_t m_Height = 0;
|
||||||
|
uint16_t m_Depth = 0;
|
||||||
|
uint8_t m_Level = 0;
|
||||||
|
uint8_t m_DepthBits = 0;
|
||||||
|
uint32_t m_Size = 0;
|
||||||
|
int32_t m_Target = 0;
|
||||||
|
unsigned char* m_Data = nullptr; // TODO proper type
|
||||||
|
MapParams* m_MapParams = nullptr;
|
||||||
|
std::vector<GLAttachPoint>* m_AttachPoints = nullptr;
|
||||||
|
uint32_t m_Unk20 = 0;
|
||||||
|
uint32_t m_Unk24 = 0;
|
||||||
|
|
||||||
|
// Member functions
|
||||||
|
void Attach(GLFramebuffer*, GLenum, int32_t);
|
||||||
|
void Detach(GLFramebuffer*, GLenum, bool);
|
||||||
|
void DetachAll();
|
||||||
|
int32_t GetDepthBits(void);
|
||||||
|
GLTextureFormat GetFormat(void);
|
||||||
|
TextureFormatInfo& GetFormatInfo(void);
|
||||||
|
uint16_t GetHeight(void);
|
||||||
|
int32_t GetPitch(void);
|
||||||
|
GLTexture* GetTexture();
|
||||||
|
uint32_t GetTextureID(void);
|
||||||
|
uint16_t GetWidth(void);
|
||||||
|
void* Map(GLEnum, const GLBox*);
|
||||||
|
void* Map(GLEnum, const GLRect*);
|
||||||
|
void ReleaseObject();
|
||||||
|
void RemoveDebugMipmap();
|
||||||
|
void ResetData(GLEnum, int32_t, unsigned char*);
|
||||||
|
void ResetSize(uint32_t, uint32_t, uint32_t);
|
||||||
|
void TexImage(const void*);
|
||||||
|
void TexSubImage(const GLBox&, int32_t, const void*);
|
||||||
|
void Unmap(void);
|
||||||
|
void Unmap(MapParams*);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
22
src/gx/glsdl/GLObject.cpp
Normal file
22
src/gx/glsdl/GLObject.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include "gx/glsdl/GLObject.hpp"
|
||||||
|
#include <bc/Debug.hpp>
|
||||||
|
|
||||||
|
void GLObject::AddRefTwin() {
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t GLObject::Release() {
|
||||||
|
BLIZZARD_ASSERT(this->m_RefCount > 0);
|
||||||
|
|
||||||
|
this->m_RefCount--;
|
||||||
|
|
||||||
|
if (this->m_RefCount == 0) {
|
||||||
|
this->ReleaseObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->ReleaseTwin();
|
||||||
|
|
||||||
|
return this->m_RefCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLObject::ReleaseTwin() {
|
||||||
|
}
|
||||||
22
src/gx/glsdl/GLObject.hpp
Normal file
22
src/gx/glsdl/GLObject.hpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_OBJECT_HPP
|
||||||
|
#define GX_GL_SDL_GL_OBJECT_HPP
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
class GLObject {
|
||||||
|
public:
|
||||||
|
// Member variables
|
||||||
|
GLObject* m_Next;
|
||||||
|
uint32_t m_RefCount;
|
||||||
|
int64_t m_TimeStamp;
|
||||||
|
|
||||||
|
// Virtual member functions
|
||||||
|
virtual void ReleaseObject() = 0;
|
||||||
|
virtual void AddRefTwin();
|
||||||
|
virtual void ReleaseTwin();
|
||||||
|
|
||||||
|
// Member functions
|
||||||
|
uint32_t Release();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
17
src/gx/glsdl/GLPixelShader.cpp
Normal file
17
src/gx/glsdl/GLPixelShader.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include "gx/glsdl/GLPixelShader.hpp"
|
||||||
|
#include "gx/glsdl/GL.hpp"
|
||||||
|
|
||||||
|
GLPixelShader* GLPixelShader::Create() {
|
||||||
|
// TODO
|
||||||
|
// GLPool stuff
|
||||||
|
|
||||||
|
GLPixelShader* shader = new GLPixelShader();
|
||||||
|
|
||||||
|
shader->m_ShaderID = 0;
|
||||||
|
shader->m_RefCount = 1;
|
||||||
|
shader->m_ShaderType = ePixelShader;
|
||||||
|
shader->m_UsingGLSL = 0;
|
||||||
|
shader->var5 = GL_FRAGMENT_PROGRAM_ARB;
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
12
src/gx/glsdl/GLPixelShader.hpp
Normal file
12
src/gx/glsdl/GLPixelShader.hpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef GX_SDL_GL_PIXEL_SHADER_HPP
|
||||||
|
#define GX_SDL_GL_PIXEL_SHADER_HPP
|
||||||
|
|
||||||
|
#include "gx/glsdl/GLShader.hpp"
|
||||||
|
|
||||||
|
class GLPixelShader : public GLShader {
|
||||||
|
public:
|
||||||
|
// Static functions
|
||||||
|
static GLPixelShader* Create(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
57
src/gx/glsdl/GLPool.hpp
Normal file
57
src/gx/glsdl/GLPool.hpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_POOL_HPP
|
||||||
|
#define GX_GL_SDL_GL_POOL_HPP
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class GLPool {
|
||||||
|
public:
|
||||||
|
// Static variables
|
||||||
|
static GLPool<T>* m_pool;
|
||||||
|
|
||||||
|
// Static functions
|
||||||
|
static GLPool<T>* Get(void);
|
||||||
|
static void Init(void);
|
||||||
|
|
||||||
|
// Member variables
|
||||||
|
std::atomic<uint32_t> m_NextName;
|
||||||
|
|
||||||
|
// Member functions
|
||||||
|
uint32_t GetNextName(void);
|
||||||
|
T* GetNextObject(void);
|
||||||
|
void SetNextName(uint32_t);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
GLPool<T>* GLPool<T>::m_pool;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
GLPool<T>* GLPool<T>::Get() {
|
||||||
|
return GLPool<T>::m_pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void GLPool<T>::Init() {
|
||||||
|
GLPool<T>::m_pool = new GLPool<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
uint32_t GLPool<T>::GetNextName() {
|
||||||
|
return this->m_NextName++;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
T* GLPool<T>::GetNextObject() {
|
||||||
|
// TODO
|
||||||
|
// - pop off of GLObjectPool
|
||||||
|
|
||||||
|
return new T();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void GLPool<T>::SetNextName(uint32_t name) {
|
||||||
|
this->m_NextName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
50
src/gx/glsdl/GLSDLContext.cpp
Normal file
50
src/gx/glsdl/GLSDLContext.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#include "gx/glsdl/GLSDLContext.hpp"
|
||||||
|
#include <bc/Debug.hpp>
|
||||||
|
#include <storm/Error.hpp>
|
||||||
|
|
||||||
|
static bool s_GLEW_Initialized = false;
|
||||||
|
|
||||||
|
void GLSDLContext::Create(GLSDLWindow* window) {
|
||||||
|
BLIZZARD_ASSERT(this->m_sdlGLContext == nullptr);
|
||||||
|
|
||||||
|
this->m_sdlGLContext = SDL_GL_CreateContext(window->m_sdlWindow);
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT(this->m_sdlGLContext != nullptr);
|
||||||
|
|
||||||
|
if (s_GLEW_Initialized == false) {
|
||||||
|
glewExperimental = true;
|
||||||
|
|
||||||
|
auto glewError = glewInit();
|
||||||
|
|
||||||
|
if (glewError != GLEW_OK) {
|
||||||
|
SErrDisplayAppFatal("Error initializing GLEW: %s\n", glewGetErrorString(glewError));
|
||||||
|
}
|
||||||
|
|
||||||
|
s_GLEW_Initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLSDLContext::Destroy() {
|
||||||
|
BLIZZARD_ASSERT(this->m_sdlGLContext != nullptr);
|
||||||
|
|
||||||
|
SDL_GL_DeleteContext(this->m_sdlGLContext);
|
||||||
|
this->m_sdlGLContext = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GLSDLContext::IsCurrentContext() {
|
||||||
|
return this->m_sdlGLContext == SDL_GL_GetCurrentContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLSDLContext::MakeCurrent(GLSDLWindow* window) {
|
||||||
|
auto status = SDL_GL_MakeCurrent(window->m_sdlWindow, this->m_sdlGLContext);
|
||||||
|
BLIZZARD_ASSERT(status == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t GLSDLContext::GetSampleCount() {
|
||||||
|
int samples;
|
||||||
|
auto status = SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &samples);
|
||||||
|
if (status != 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return static_cast<int32_t>(samples);
|
||||||
|
}
|
||||||
20
src/gx/glsdl/GLSDLContext.hpp
Normal file
20
src/gx/glsdl/GLSDLContext.hpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_SDL_CONTEXT_HPP
|
||||||
|
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
#include "gx/glsdl/GLSDLWindow.hpp"
|
||||||
|
#include "gx/glsdl/GLTypes.hpp"
|
||||||
|
|
||||||
|
class GLSDLContext {
|
||||||
|
public:
|
||||||
|
SDL_GLContext m_sdlGLContext = nullptr;
|
||||||
|
|
||||||
|
GLSDLContext() = default;
|
||||||
|
void Create(GLSDLWindow* window);
|
||||||
|
void Destroy();
|
||||||
|
bool IsCurrentContext();
|
||||||
|
void MakeCurrent(GLSDLWindow* window);
|
||||||
|
int32_t GetSampleCount();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
2785
src/gx/glsdl/GLSDLDevice.cpp
Normal file
2785
src/gx/glsdl/GLSDLDevice.cpp
Normal file
File diff suppressed because it is too large
Load Diff
190
src/gx/glsdl/GLSDLDevice.hpp
Normal file
190
src/gx/glsdl/GLSDLDevice.hpp
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_SDL_DEVICE_HPP
|
||||||
|
#define GX_GL_SDL_GL_SDL_DEVICE_HPP
|
||||||
|
|
||||||
|
#include "gx/glsdl/GL.hpp"
|
||||||
|
#include "gx/glsdl/GLSDLWindow.hpp"
|
||||||
|
#include "gx/glsdl/GLBatch.hpp"
|
||||||
|
#include "gx/glsdl/GLBufferPool.hpp"
|
||||||
|
#include "gx/glsdl/GLSDLContext.hpp"
|
||||||
|
#include "gx/glsdl/GLDebugMipmap2D.hpp"
|
||||||
|
#include "gx/glsdl/GLFramebuffer.hpp"
|
||||||
|
#include "gx/glsdl/GLGLSLProgram.hpp"
|
||||||
|
#include "gx/glsdl/GLMipmap.hpp"
|
||||||
|
#include "gx/glsdl/GLShader.hpp"
|
||||||
|
#include "gx/glsdl/GLTexture.hpp"
|
||||||
|
#include "gx/glsdl/GLTypes.hpp"
|
||||||
|
#include "gx/glsdl/GLVertexArray.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <bc/Thread.hpp>
|
||||||
|
|
||||||
|
class GLSDLDevice {
|
||||||
|
public:
|
||||||
|
// Types
|
||||||
|
enum GLSDLDeviceOption {
|
||||||
|
eUseMTGL = 0,
|
||||||
|
eUseVertexArray = 1,
|
||||||
|
eUseGLSL = 2,
|
||||||
|
eCheckGLStates = 3,
|
||||||
|
eFlushBeforeDraw = 4,
|
||||||
|
eDeviceOption5 = 5,
|
||||||
|
eUseHybridShader = 6,
|
||||||
|
eDeviceOption7 = 7,
|
||||||
|
eDeviceOption8 = 8,
|
||||||
|
eShaderConstantBindings = 9
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RendererInfo {
|
||||||
|
uint8_t init = 0;
|
||||||
|
uint32_t vendor_id;
|
||||||
|
uint32_t renderer_id;
|
||||||
|
uint32_t max_color_attachments;
|
||||||
|
uint32_t unk36; // max clip planes
|
||||||
|
uint32_t unk100;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Static variables
|
||||||
|
static Blizzard::Thread::TLSSlot m_CurrentDevice;
|
||||||
|
static std::vector<GLSDLDevice*> m_Devices;
|
||||||
|
static bool m_ExtARBShadow;
|
||||||
|
static bool m_ExtColorMaskIndexed;
|
||||||
|
static RendererInfo m_RendererInfo;
|
||||||
|
static bool m_ShaderConstantBindings;
|
||||||
|
static int32_t m_StaticResourcesRefCount;
|
||||||
|
static bool m_UseHybridShader;
|
||||||
|
static GLBuffer* m_BlitQuadVBO;
|
||||||
|
static GLShader* m_DeviceShaders[];
|
||||||
|
static GLTexture* m_DeviceTextures[];
|
||||||
|
static GLVertexFormat m_NormalBlitVF;
|
||||||
|
static GLVertexFormat m_InvertedBlitVF;
|
||||||
|
static GLFramebuffer* m_F8330C;
|
||||||
|
|
||||||
|
// Static functions
|
||||||
|
static GLSDLDevice* Get();
|
||||||
|
static void Set(GLSDLDevice* device);
|
||||||
|
static void InitPools();
|
||||||
|
static RendererInfo GetRendererInfo();
|
||||||
|
static void InitRendererInfo();
|
||||||
|
static void SetOption(GLSDLDeviceOption option, bool enable);
|
||||||
|
static void StaticInit();
|
||||||
|
|
||||||
|
// Member variables
|
||||||
|
std::string m_DebugName;
|
||||||
|
GLStates m_States;
|
||||||
|
GLTexture* m_Textures[16] = {};
|
||||||
|
GLShader* m_PixelShader = nullptr;
|
||||||
|
GLShader* m_VertexShader = nullptr;
|
||||||
|
GLGLSLProgram* m_GLSLProgram = nullptr;
|
||||||
|
GLVertexArray* m_VertexArrayObject = &m_DefaultVertexArrayObject;
|
||||||
|
GLFramebuffer* m_SystemTarget = nullptr;
|
||||||
|
GLFramebuffer* m_FBOTarget = nullptr;
|
||||||
|
GLFramebuffer* m_CurrentTarget = nullptr;
|
||||||
|
GLMipmap* m_CurrentTargetColor[4] = {};
|
||||||
|
GLMipmap* m_CurrentTargetDepth = nullptr;
|
||||||
|
GLMipmap* m_CurrentTargetStencil = nullptr;
|
||||||
|
GLMipmap* m_CurrentDepthBuffer = nullptr;
|
||||||
|
GLTexture2D* m_BackBufferColor = nullptr;
|
||||||
|
GLTexture2D* m_BackBufferDepth = nullptr;
|
||||||
|
GLTexture2D* m_BackBufferStencil = nullptr;
|
||||||
|
GLSDLWindow* m_Window = nullptr;
|
||||||
|
GLBufferPool* m_PBOPool = nullptr;
|
||||||
|
GLSDLContext m_Context;
|
||||||
|
GLTexture* m_BoundTextures[4][16] = {};
|
||||||
|
GLVertexArray m_DefaultVertexArrayObject;
|
||||||
|
GLDirtyRange m_DirtyVertexShaderConsts;
|
||||||
|
GLDirtyRange m_DirtyPixelShaderConsts;
|
||||||
|
float m_ConstantDepthBias = 0.0f;
|
||||||
|
float m_SlopeScaledDepthBias = 0.0f;
|
||||||
|
bool m_Init = 0;
|
||||||
|
uint32_t m_DrawCount = 0;
|
||||||
|
uint32_t m_ID = -1;
|
||||||
|
std::list<GLTexture*> m_TextureList;
|
||||||
|
std::list<GLTexture*>::iterator m_OldestActiveTexture;
|
||||||
|
uint32_t m_TextureTotalSize = 0;
|
||||||
|
uint32_t m_FrameNumber = 1;
|
||||||
|
std::list<GLDebugMipmap2D*> m_DebugMipmaps;
|
||||||
|
bool m_BatchViewerEnabled = 0;
|
||||||
|
bool m_UseWindowSystemBuffer = 0;
|
||||||
|
bool m_FlippedSystemBuffer = 0;
|
||||||
|
bool m_ShaderCompiler = 0;
|
||||||
|
bool m_WorkerDevice;
|
||||||
|
GLStates m_DefaultStates;
|
||||||
|
std::vector<GLBatch>* m_FrameBatches;
|
||||||
|
bool m_CaptureOnlyOneFrame = 0;
|
||||||
|
bool m_StopCapturingBatches = 0;
|
||||||
|
bool m_CaptureBatches = 0;
|
||||||
|
int32_t m_IndentLevel = 0;
|
||||||
|
|
||||||
|
// Member functions
|
||||||
|
GLSDLDevice();
|
||||||
|
void ApplyGLBindings(const GLStates& states, bool a3);
|
||||||
|
void ApplyGLStates(const GLStates& states, bool force);
|
||||||
|
void ApplyShaderConstants();
|
||||||
|
void ApplyTransforms();
|
||||||
|
void BindBuffer(GLBuffer* buffer, GLEnum target);
|
||||||
|
void BindFramebuffer(GLFramebuffer* framebuffer);
|
||||||
|
void BindGLSLProgram(GLGLSLProgram* a2);
|
||||||
|
void BindShader(GLShader* shader);
|
||||||
|
void BindTexture(GLEnum textureType, GLTexture* texture);
|
||||||
|
void BindVertexArray(GLVertexArray* a2);
|
||||||
|
void BlitFramebuffer(GLMipmap* src, const GLRect* srcRect, GLMipmap* dst, const GLRect* dstRect, GLEnum mask, GLEnum filter);
|
||||||
|
void CheckDepthTarget();
|
||||||
|
void Clear(uint32_t clearMask, const GLColor4f& clearColor, double clearDepth, int32_t clearStencil);
|
||||||
|
void CopyTex(uint32_t a2, uint32_t a3, GLMipmap* dst, const GLRect* framebufferRect);
|
||||||
|
GLBuffer* CreateBuffer(GLEnum type, uint32_t a3, const void* a4, GLEnum usage, GLEnum format);
|
||||||
|
GLShader* CreateShader(GLShader::ShaderType type, const void* buf, int32_t codeLen, const char* name);
|
||||||
|
GLTexture* CreateTexture2D(uint32_t width, uint32_t height, uint32_t numMipMap, GLTextureFormat format, uint32_t flags);
|
||||||
|
GLTexture* CreateTextureCubeMap(uint32_t size, uint32_t numMipMap, GLTextureFormat format, uint32_t flags);
|
||||||
|
void Draw(GLEnum primitive, uint32_t a3, uint32_t a4);
|
||||||
|
void DrawIndexed(GLEnum primitive, uint32_t a3, uint32_t a4, uint32_t a5, uint32_t a6, uint32_t count);
|
||||||
|
void DrawRect();
|
||||||
|
GLFramebuffer* GetCurrentTarget(); // invented name
|
||||||
|
uint32_t GetID();
|
||||||
|
GLShader* GetShader(GLShader::ShaderType shaderType);
|
||||||
|
const GLStates::VertexArrayObject& GetVertexArrayStates();
|
||||||
|
void GLSDLDraw(GLEnum mode, uint32_t start, uint32_t end, uint32_t a5, uint32_t a6, uint32_t count);
|
||||||
|
void Init(GLSDLWindow* a2, const char* a3, uint32_t a4);
|
||||||
|
void LoadDefaultStates();
|
||||||
|
void ResetBackbuffer(uint32_t width, uint32_t height, GLTextureFormat colorFormat, GLTextureFormat depthFormat,uint32_t sampleCount);
|
||||||
|
void Resize(uint32_t width, uint32_t height);
|
||||||
|
void RestoreTextures();
|
||||||
|
void SetActiveTexture(uint32_t a2);
|
||||||
|
void SetAlphaBlend(GLEnum srcBlend, GLEnum dstBlend, GLEnum blendOp);
|
||||||
|
void SetAlphaBlendEnable(bool enable);
|
||||||
|
void SetAlphaTest(GLEnum func, float ref);
|
||||||
|
void SetAlphaTestEnable(bool enable);
|
||||||
|
void SetClearColor(const GLColor4f& clearColor);
|
||||||
|
void SetClearDepth(double clearDepth);
|
||||||
|
void SetClearStencil(int32_t clearStencil);
|
||||||
|
void SetColorWriteMask(bool red, bool green, bool blue, bool alpha, uint32_t index);
|
||||||
|
void SetCullMode(GLEnum cullMode);
|
||||||
|
void SetDepthBias(float constantBias, float slopeScaledBias);
|
||||||
|
void SetDepthTestEnable(bool enable);
|
||||||
|
void SetDepthTestFunc(GLEnum func);
|
||||||
|
void SetDepthWriteMask(bool enable);
|
||||||
|
void SetDisplay(uint32_t width, uint32_t height, GLTextureFormat colorFormat, GLTextureFormat depthFormat, uint32_t refreshRate, bool windowed, bool captureDisplay, uint32_t sampleCount);
|
||||||
|
void SetFogColor(float r, float g, float b, float a);
|
||||||
|
void SetFogEnable(bool enable);
|
||||||
|
void SetFogParam(GLEnum param, float value);
|
||||||
|
void SetIndexBuffer(GLBuffer* buffer);
|
||||||
|
void SetLightingEnable(bool enable);
|
||||||
|
void SetModelView(GLEnum transform);
|
||||||
|
void SetScissor(bool enable, const GLRect& rect);
|
||||||
|
void SetShader(GLShader::ShaderType shaderType, GLShader* shader);
|
||||||
|
void SetShaderConstants(GLShader::ShaderType shaderType, uint32_t index, const float* constants, uint32_t count);
|
||||||
|
void SetShaderConstantsInternal(GLShader::ShaderType shaderType, uint32_t index, const float* constants, uint32_t count);
|
||||||
|
void SetTexture(uint32_t stage, GLTexture* texture);
|
||||||
|
void SetTransform(GLEnum transform, const float* a3);
|
||||||
|
void SetUnpackClientStorage(bool enable);
|
||||||
|
void SetVertexBuffer(uint32_t index, GLBuffer* buffer, uint32_t offset, uint32_t stride);
|
||||||
|
void SetVertexFormat(GLVertexFormat* format);
|
||||||
|
void SetViewport(const GLRect& viewport, double zNear, double zFar);
|
||||||
|
void Sub34BB0(GLEnum a2, GLMipmap* a3, uint32_t index);
|
||||||
|
void Sub38460(bool a2);
|
||||||
|
void Swap();
|
||||||
|
void UpdateFFPTexturing();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
389
src/gx/glsdl/GLSDLWindow.cpp
Normal file
389
src/gx/glsdl/GLSDLWindow.cpp
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
#include "gx/glsdl/GLSDLWindow.hpp"
|
||||||
|
#include "event/Types.hpp"
|
||||||
|
#include "event/Input.hpp"
|
||||||
|
#include "event/Event.hpp"
|
||||||
|
#include "gx/Window.hpp"
|
||||||
|
#include "gx/Device.hpp"
|
||||||
|
#include "gx/glsdl/CGxDeviceGLSDL.hpp"
|
||||||
|
|
||||||
|
#include <bc/Debug.hpp>
|
||||||
|
#include <storm/Unicode.hpp>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
static bool s_GLSDL_Initialized = false;
|
||||||
|
|
||||||
|
static const std::map<SDL_Scancode, KEY> s_keyConversion = {
|
||||||
|
{SDL_SCANCODE_LSHIFT, KEY_LSHIFT},
|
||||||
|
{SDL_SCANCODE_RSHIFT, KEY_RSHIFT},
|
||||||
|
{SDL_SCANCODE_LCTRL, KEY_LCONTROL},
|
||||||
|
{SDL_SCANCODE_RCTRL, KEY_RCONTROL},
|
||||||
|
{SDL_SCANCODE_LALT, KEY_LALT},
|
||||||
|
{SDL_SCANCODE_RALT, KEY_RALT},
|
||||||
|
{SDL_SCANCODE_SPACE, KEY_SPACE},
|
||||||
|
{SDL_SCANCODE_0, KEY_0},
|
||||||
|
{SDL_SCANCODE_1, KEY_1},
|
||||||
|
{SDL_SCANCODE_2, KEY_2},
|
||||||
|
{SDL_SCANCODE_3, KEY_3},
|
||||||
|
{SDL_SCANCODE_4, KEY_4},
|
||||||
|
{SDL_SCANCODE_5, KEY_5},
|
||||||
|
{SDL_SCANCODE_6, KEY_6},
|
||||||
|
{SDL_SCANCODE_7, KEY_7},
|
||||||
|
{SDL_SCANCODE_8, KEY_8},
|
||||||
|
{SDL_SCANCODE_9, KEY_9},
|
||||||
|
{SDL_SCANCODE_A, KEY_A},
|
||||||
|
{SDL_SCANCODE_B, KEY_B},
|
||||||
|
{SDL_SCANCODE_C, KEY_C},
|
||||||
|
{SDL_SCANCODE_D, KEY_D},
|
||||||
|
{SDL_SCANCODE_E, KEY_E},
|
||||||
|
{SDL_SCANCODE_F, KEY_F},
|
||||||
|
{SDL_SCANCODE_G, KEY_G},
|
||||||
|
{SDL_SCANCODE_H, KEY_H},
|
||||||
|
{SDL_SCANCODE_I, KEY_I},
|
||||||
|
{SDL_SCANCODE_J, KEY_J},
|
||||||
|
{SDL_SCANCODE_K, KEY_K},
|
||||||
|
{SDL_SCANCODE_L, KEY_L},
|
||||||
|
{SDL_SCANCODE_M, KEY_M},
|
||||||
|
{SDL_SCANCODE_N, KEY_N},
|
||||||
|
{SDL_SCANCODE_O, KEY_O},
|
||||||
|
{SDL_SCANCODE_P, KEY_P},
|
||||||
|
{SDL_SCANCODE_Q, KEY_Q},
|
||||||
|
{SDL_SCANCODE_R, KEY_R},
|
||||||
|
{SDL_SCANCODE_S, KEY_S},
|
||||||
|
{SDL_SCANCODE_T, KEY_T},
|
||||||
|
{SDL_SCANCODE_U, KEY_U},
|
||||||
|
{SDL_SCANCODE_V, KEY_V},
|
||||||
|
{SDL_SCANCODE_W, KEY_W},
|
||||||
|
{SDL_SCANCODE_X, KEY_X},
|
||||||
|
{SDL_SCANCODE_Y, KEY_Y},
|
||||||
|
{SDL_SCANCODE_Z, KEY_Z},
|
||||||
|
{SDL_SCANCODE_GRAVE, KEY_TILDE},
|
||||||
|
{SDL_SCANCODE_KP_0, KEY_NUMPAD0},
|
||||||
|
{SDL_SCANCODE_KP_1, KEY_NUMPAD1},
|
||||||
|
{SDL_SCANCODE_KP_2, KEY_NUMPAD2},
|
||||||
|
{SDL_SCANCODE_KP_3, KEY_NUMPAD3},
|
||||||
|
{SDL_SCANCODE_KP_4, KEY_NUMPAD4},
|
||||||
|
{SDL_SCANCODE_KP_5, KEY_NUMPAD5},
|
||||||
|
{SDL_SCANCODE_KP_6, KEY_NUMPAD6},
|
||||||
|
{SDL_SCANCODE_KP_7, KEY_NUMPAD7},
|
||||||
|
{SDL_SCANCODE_KP_8, KEY_NUMPAD8},
|
||||||
|
{SDL_SCANCODE_KP_9, KEY_NUMPAD9},
|
||||||
|
{SDL_SCANCODE_KP_PLUS, KEY_NUMPAD_PLUS},
|
||||||
|
{SDL_SCANCODE_KP_MINUS, KEY_NUMPAD_MINUS},
|
||||||
|
{SDL_SCANCODE_KP_MULTIPLY, KEY_NUMPAD_MULTIPLY},
|
||||||
|
{SDL_SCANCODE_KP_DIVIDE, KEY_NUMPAD_DIVIDE},
|
||||||
|
{SDL_SCANCODE_KP_DECIMAL, KEY_NUMPAD_DECIMAL},
|
||||||
|
{SDL_SCANCODE_KP_EQUALS, KEY_NUMPAD_EQUALS},
|
||||||
|
{SDL_SCANCODE_EQUALS, KEY_PLUS},
|
||||||
|
{SDL_SCANCODE_MINUS, KEY_MINUS},
|
||||||
|
{SDL_SCANCODE_LEFTBRACKET, KEY_BRACKET_OPEN},
|
||||||
|
{SDL_SCANCODE_RIGHTBRACKET, KEY_BRACKET_CLOSE},
|
||||||
|
{SDL_SCANCODE_SLASH, KEY_SLASH},
|
||||||
|
{SDL_SCANCODE_BACKSLASH, KEY_BACKSLASH},
|
||||||
|
{SDL_SCANCODE_SEMICOLON, KEY_SEMICOLON},
|
||||||
|
{SDL_SCANCODE_APOSTROPHE, KEY_APOSTROPHE},
|
||||||
|
{SDL_SCANCODE_COMMA, KEY_COMMA},
|
||||||
|
{SDL_SCANCODE_PERIOD, KEY_PERIOD},
|
||||||
|
{SDL_SCANCODE_ESCAPE, KEY_ESCAPE},
|
||||||
|
{SDL_SCANCODE_RETURN, KEY_ENTER},
|
||||||
|
{SDL_SCANCODE_BACKSPACE, KEY_BACKSPACE},
|
||||||
|
{SDL_SCANCODE_TAB, KEY_TAB},
|
||||||
|
{SDL_SCANCODE_LEFT, KEY_LEFT},
|
||||||
|
{SDL_SCANCODE_UP, KEY_UP},
|
||||||
|
{SDL_SCANCODE_RIGHT, KEY_RIGHT},
|
||||||
|
{SDL_SCANCODE_DOWN, KEY_DOWN},
|
||||||
|
{SDL_SCANCODE_INSERT, KEY_INSERT},
|
||||||
|
{SDL_SCANCODE_DELETE, KEY_DELETE},
|
||||||
|
{SDL_SCANCODE_HOME, KEY_HOME},
|
||||||
|
{SDL_SCANCODE_END, KEY_END},
|
||||||
|
{SDL_SCANCODE_PAGEUP, KEY_PAGEUP},
|
||||||
|
{SDL_SCANCODE_PAGEDOWN, KEY_PAGEDOWN},
|
||||||
|
{SDL_SCANCODE_CAPSLOCK, KEY_CAPSLOCK},
|
||||||
|
{SDL_SCANCODE_NUMLOCKCLEAR, KEY_NUMLOCK},
|
||||||
|
{SDL_SCANCODE_SCROLLLOCK, KEY_SCROLLLOCK},
|
||||||
|
{SDL_SCANCODE_PAUSE, KEY_PAUSE},
|
||||||
|
{SDL_SCANCODE_PRINTSCREEN, KEY_PRINTSCREEN},
|
||||||
|
{SDL_SCANCODE_F1, KEY_F1},
|
||||||
|
{SDL_SCANCODE_F2, KEY_F2},
|
||||||
|
{SDL_SCANCODE_F3, KEY_F3},
|
||||||
|
{SDL_SCANCODE_F4, KEY_F4},
|
||||||
|
{SDL_SCANCODE_F5, KEY_F5},
|
||||||
|
{SDL_SCANCODE_F6, KEY_F6},
|
||||||
|
{SDL_SCANCODE_F7, KEY_F7},
|
||||||
|
{SDL_SCANCODE_F8, KEY_F8},
|
||||||
|
{SDL_SCANCODE_F9, KEY_F9},
|
||||||
|
{SDL_SCANCODE_F10, KEY_F10},
|
||||||
|
{SDL_SCANCODE_F11, KEY_F11},
|
||||||
|
{SDL_SCANCODE_F12, KEY_F12},
|
||||||
|
{SDL_SCANCODE_F13, KEY_F13},
|
||||||
|
{SDL_SCANCODE_F14, KEY_F14},
|
||||||
|
{SDL_SCANCODE_F15, KEY_F15},
|
||||||
|
{SDL_SCANCODE_F16, KEY_F16},
|
||||||
|
{SDL_SCANCODE_F17, KEY_F17},
|
||||||
|
{SDL_SCANCODE_F18, KEY_F18},
|
||||||
|
{SDL_SCANCODE_F19, KEY_F19}
|
||||||
|
};
|
||||||
|
|
||||||
|
static MOUSEBUTTON s_buttonConversion[16] = {
|
||||||
|
MOUSE_BUTTON_NONE,
|
||||||
|
MOUSE_BUTTON_LEFT,
|
||||||
|
MOUSE_BUTTON_MIDDLE,
|
||||||
|
MOUSE_BUTTON_RIGHT,
|
||||||
|
MOUSE_BUTTON_XBUTTON1,
|
||||||
|
MOUSE_BUTTON_XBUTTON2,
|
||||||
|
MOUSE_BUTTON_XBUTTON3,
|
||||||
|
MOUSE_BUTTON_XBUTTON4,
|
||||||
|
MOUSE_BUTTON_XBUTTON5,
|
||||||
|
MOUSE_BUTTON_XBUTTON6,
|
||||||
|
MOUSE_BUTTON_XBUTTON7,
|
||||||
|
MOUSE_BUTTON_XBUTTON8,
|
||||||
|
MOUSE_BUTTON_XBUTTON9,
|
||||||
|
MOUSE_BUTTON_XBUTTON10,
|
||||||
|
MOUSE_BUTTON_XBUTTON11,
|
||||||
|
MOUSE_BUTTON_XBUTTON12
|
||||||
|
};
|
||||||
|
|
||||||
|
void GLSDLWindow::Create(const char* title, const GLSDLWindowRect& rect, GLTextureFormat depthFormat, uint32_t sampleCount) {
|
||||||
|
BLIZZARD_ASSERT(this->m_sdlWindow == nullptr);
|
||||||
|
|
||||||
|
if (!s_GLSDL_Initialized) {
|
||||||
|
// Initialize SDL video context
|
||||||
|
SDL_Init(SDL_INIT_VIDEO);
|
||||||
|
|
||||||
|
// Set GL version profile
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||||
|
|
||||||
|
s_GLSDL_Initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set depth and stencil size according to format
|
||||||
|
uint32_t depthSize = 0;
|
||||||
|
uint32_t stencilSize = 0;
|
||||||
|
|
||||||
|
switch (depthFormat) {
|
||||||
|
case GLTF_INVALID:
|
||||||
|
break;
|
||||||
|
case GLTF_D32:
|
||||||
|
depthSize = 32;
|
||||||
|
break;
|
||||||
|
case GLTF_D24:
|
||||||
|
depthSize = 24;
|
||||||
|
break;
|
||||||
|
case GLTF_D16:
|
||||||
|
depthSize = 16;
|
||||||
|
break;
|
||||||
|
case GLTF_D24S8:
|
||||||
|
depthSize = 24;
|
||||||
|
stencilSize = 8;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BLIZZARD_ASSERT(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, depthSize);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencilSize);
|
||||||
|
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
|
||||||
|
|
||||||
|
// Set multisampling
|
||||||
|
if (sampleCount >= 1) {
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, sampleCount);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->m_sdlWindow = SDL_CreateWindow(
|
||||||
|
title,
|
||||||
|
static_cast<int>(rect.size.width), static_cast<int>(rect.size.height),
|
||||||
|
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE
|
||||||
|
);
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT(this->m_sdlWindow != nullptr);
|
||||||
|
|
||||||
|
SDL_StartTextInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLSDLWindow::Swap() {
|
||||||
|
SDL_GL_SwapWindow(this->m_sdlWindow);
|
||||||
|
|
||||||
|
SDL_Event event;
|
||||||
|
while (SDL_PollEvent(&event)) {
|
||||||
|
this->DispatchSDLEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLSDLWindow::Destroy() {
|
||||||
|
SDL_DestroyWindow(this->m_sdlWindow);
|
||||||
|
this->m_sdlWindow = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLSDLWindowRect GLSDLWindow::GetRect() {
|
||||||
|
// Default rectangle
|
||||||
|
GLSDLWindowRect rect;
|
||||||
|
|
||||||
|
int origin_x = 0;
|
||||||
|
int origin_y = 0;
|
||||||
|
if (SDL_GetWindowPosition(this->m_sdlWindow, &origin_x, &origin_y) == 0) {
|
||||||
|
rect.origin.x = static_cast<int32_t>(origin_x);
|
||||||
|
rect.origin.y = static_cast<int32_t>(origin_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
if (SDL_GetWindowSize(this->m_sdlWindow, &width, &height) == 0) {
|
||||||
|
rect.size.width = static_cast<int32_t>(width);
|
||||||
|
rect.size.height = static_cast<int32_t>(height);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLSDLWindowRect GLSDLWindow::GetBackingRect() {
|
||||||
|
// Default rectangle
|
||||||
|
GLSDLWindowRect rect;
|
||||||
|
|
||||||
|
// Query backing width/height
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
if (SDL_GetWindowSizeInPixels(this->m_sdlWindow, &width, &height) == 0) {
|
||||||
|
rect.size.width = static_cast<int32_t>(width);
|
||||||
|
rect.size.height = static_cast<int32_t>(height);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLSDLWindow::Resize(const GLSDLWindowRect& rect) {
|
||||||
|
auto current = this->GetBackingRect();
|
||||||
|
|
||||||
|
if (current.size.width != rect.size.width || current.size.height != rect.size.width) {
|
||||||
|
auto status = SDL_SetWindowSize(this->m_sdlWindow, rect.size.width, rect.size.height);
|
||||||
|
BLIZZARD_ASSERT(status == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t GLSDLWindow::GetWidth() {
|
||||||
|
return this->GetBackingRect().size.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t GLSDLWindow::GetHeight() {
|
||||||
|
return this->GetBackingRect().size.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLSDLWindow::DispatchSDLEvent(const SDL_Event& event) {
|
||||||
|
switch (event.type) {
|
||||||
|
case SDL_EVENT_KEY_DOWN:
|
||||||
|
case SDL_EVENT_KEY_UP:
|
||||||
|
this->DispatchSDLKeyboardEvent(event);
|
||||||
|
break;
|
||||||
|
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||||
|
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||||
|
this->DispatchSDLMouseButtonEvent(event);
|
||||||
|
break;
|
||||||
|
case SDL_EVENT_MOUSE_MOTION:
|
||||||
|
this->DispatchSDLMouseMotionEvent(event);
|
||||||
|
break;
|
||||||
|
case SDL_EVENT_TEXT_INPUT:
|
||||||
|
this->DispatchSDLTextInputEvent(event);
|
||||||
|
break;
|
||||||
|
case SDL_EVENT_WINDOW_RESIZED:
|
||||||
|
this->DispatchSDLWindowResizedEvent(event);
|
||||||
|
break;
|
||||||
|
case SDL_EVENT_QUIT:
|
||||||
|
EventPostClose();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLSDLWindow::DispatchSDLKeyboardEvent(const SDL_Event& event) {
|
||||||
|
// Is this an up or down keypress?
|
||||||
|
OSINPUT inputclass = event.type == SDL_EVENT_KEY_UP ? OS_INPUT_KEY_UP : OS_INPUT_KEY_DOWN;
|
||||||
|
|
||||||
|
// What key does this SDL scancode correspond to?
|
||||||
|
auto lookup = s_keyConversion.find(event.key.keysym.scancode);
|
||||||
|
if (lookup != s_keyConversion.end()) {
|
||||||
|
// Scancode was found
|
||||||
|
KEY key = lookup->second;
|
||||||
|
|
||||||
|
// Push key event into input queue
|
||||||
|
OsQueuePut(inputclass, key, 0, 0, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLSDLWindow::DispatchSDLMouseMotionEvent(const SDL_Event& event) {
|
||||||
|
auto x = static_cast<int32_t>(event.motion.x);
|
||||||
|
auto y = static_cast<int32_t>(event.motion.y);
|
||||||
|
|
||||||
|
OsQueuePut(OS_INPUT_MOUSE_MOVE, 0, x, y, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLSDLWindow::DispatchSDLMouseButtonEvent(const SDL_Event& event) {
|
||||||
|
// Is this an up or down mouse click?
|
||||||
|
OSINPUT inputclass = event.type == SDL_EVENT_MOUSE_BUTTON_UP ? OS_INPUT_MOUSE_UP : OS_INPUT_MOUSE_DOWN;
|
||||||
|
|
||||||
|
// XY click coordinates
|
||||||
|
auto x = static_cast<int32_t>(event.button.x);
|
||||||
|
auto y = static_cast<int32_t>(event.button.y);
|
||||||
|
|
||||||
|
// Convert SDL button index into internal MOUSEBUTTON ID
|
||||||
|
auto buttonIndex = event.button.button;
|
||||||
|
if (buttonIndex > 15) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto button = s_buttonConversion[buttonIndex];
|
||||||
|
|
||||||
|
// Push mousebutton event into input queue
|
||||||
|
OsQueuePut(inputclass, button, x, y, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLSDLWindow::DispatchSDLTextInputEvent(const SDL_Event& event) {
|
||||||
|
// text input string holding one or more UTF-8 characters
|
||||||
|
auto text = reinterpret_cast<const uint8_t*>(event.text.text);
|
||||||
|
|
||||||
|
// Because SDL_TextInputEvent can hold multiple UTF-8 characters
|
||||||
|
// explode variable number of these characters into
|
||||||
|
// individual OS_INPUT_CHAR events
|
||||||
|
while (*text != '\0') {
|
||||||
|
// byte size of current UTF-8 character
|
||||||
|
int32_t charactersize = 0;
|
||||||
|
|
||||||
|
// Read UTF-8 character
|
||||||
|
auto character = static_cast<int32_t>(SUniSGetUTF8(text, &charactersize));
|
||||||
|
if (character < 0) {
|
||||||
|
// Cancel in case of invalid input
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push character to input queue
|
||||||
|
OsQueuePut(OS_INPUT_CHAR, character, 1, 0, 0);
|
||||||
|
|
||||||
|
// Advance text pointer
|
||||||
|
text += charactersize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLSDLWindow::DispatchSDLWindowResizedEvent(const SDL_Event& event) {
|
||||||
|
auto width = static_cast<int32_t>(event.window.data1);
|
||||||
|
auto height = static_cast<int32_t>(event.window.data2);
|
||||||
|
|
||||||
|
static_cast<CGxDeviceGLSDL*>(g_theGxDevicePtr)->Resize(width, height);
|
||||||
|
|
||||||
|
OsQueuePut(OS_INPUT_SIZE, width, height, 0, 0);
|
||||||
|
|
||||||
|
auto bounds = GetSavedWindowBounds();
|
||||||
|
Rect newBounds = {
|
||||||
|
bounds->top,
|
||||||
|
bounds->left,
|
||||||
|
static_cast<int16_t>(bounds->top + height),
|
||||||
|
static_cast<int16_t>(bounds->left + width)
|
||||||
|
};
|
||||||
|
SetSavedWindowBounds(newBounds);
|
||||||
|
}
|
||||||
50
src/gx/glsdl/GLSDLWindow.hpp
Normal file
50
src/gx/glsdl/GLSDLWindow.hpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_SDL_WINDOW_HPP
|
||||||
|
#define GX_GL_SDL_GL_SDL_WINDOW_HPP
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
#include "gx/glsdl/GLTypes.hpp"
|
||||||
|
|
||||||
|
class GLSDLWindowRect {
|
||||||
|
public:
|
||||||
|
struct Point {
|
||||||
|
int32_t x = 0;
|
||||||
|
int32_t y = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Size {
|
||||||
|
int32_t width = 0;
|
||||||
|
int32_t height = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
Point origin;
|
||||||
|
Size size;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GLSDLWindow {
|
||||||
|
public:
|
||||||
|
SDL_Window* m_sdlWindow = nullptr;
|
||||||
|
|
||||||
|
// Create an SDL window with the requested OpenGL attributes
|
||||||
|
void Create(const char* title, const GLSDLWindowRect& rect, GLTextureFormat depthFormat, uint32_t sampleCount);
|
||||||
|
void Destroy();
|
||||||
|
void Swap();
|
||||||
|
void DispatchSDLEvent(const SDL_Event& event);
|
||||||
|
void DispatchSDLKeyboardEvent(const SDL_Event& event);
|
||||||
|
void DispatchSDLMouseMotionEvent(const SDL_Event& event);
|
||||||
|
void DispatchSDLMouseButtonEvent(const SDL_Event& event);
|
||||||
|
void DispatchSDLTextInputEvent(const SDL_Event& event);
|
||||||
|
void DispatchSDLWindowResizedEvent(const SDL_Event& event);
|
||||||
|
void Resize(const GLSDLWindowRect& rect);
|
||||||
|
|
||||||
|
GLSDLWindowRect GetRect();
|
||||||
|
GLSDLWindowRect GetBackingRect();
|
||||||
|
|
||||||
|
int32_t GetWidth();
|
||||||
|
int32_t GetHeight();
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
136
src/gx/glsdl/GLShader.cpp
Normal file
136
src/gx/glsdl/GLShader.cpp
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
#include "gx/glsdl/GLShader.hpp"
|
||||||
|
#include "gx/glsdl/GLSDLDevice.hpp"
|
||||||
|
#include "gx/glsdl/GLPixelShader.hpp"
|
||||||
|
#include "gx/glsdl/GLPool.hpp"
|
||||||
|
#include "gx/glsdl/GLVertexShader.hpp"
|
||||||
|
#include "gx/glsdl/GL.hpp"
|
||||||
|
#include <bc/Debug.hpp>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// - threaded compiler support
|
||||||
|
// - glsl support
|
||||||
|
// - hybrid support
|
||||||
|
GLShader* GLShader::Create(ShaderType shaderType, bool hybrid, bool usingCG, const char* a4, const void* buf, int32_t codeLen, const char* a7, const char* name, GLShaderLogInfo* logInfo) {
|
||||||
|
const char* shaderCode = reinterpret_cast<const char*>(buf);
|
||||||
|
|
||||||
|
if (*reinterpret_cast<const int32_t*>(buf) == 'GSL1') {
|
||||||
|
BLIZZARD_ASSERT(!usingCG);
|
||||||
|
|
||||||
|
const ShaderDataHeader header = *reinterpret_cast<const ShaderDataHeader*>(buf);
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT(header.shaderType == shaderType);
|
||||||
|
BLIZZARD_ASSERT(header.size == codeLen);
|
||||||
|
BLIZZARD_ASSERT(header.codePos >= sizeof(ShaderDataHeader));
|
||||||
|
BLIZZARD_ASSERT(header.codeSize > 0);
|
||||||
|
|
||||||
|
shaderCode = &reinterpret_cast<const char*>(buf)[header.codePos];
|
||||||
|
}
|
||||||
|
|
||||||
|
GLShader* shader = nullptr;
|
||||||
|
|
||||||
|
if (shaderType == ePixelShader) {
|
||||||
|
shader = GLPixelShader::Create();
|
||||||
|
} else if (shaderType == eVertexShader) {
|
||||||
|
shader = GLVertexShader::Create();
|
||||||
|
} else {
|
||||||
|
// TODO
|
||||||
|
// sub_1C5E0(&v38, "Unknown shader type %d!", shaderType);
|
||||||
|
}
|
||||||
|
|
||||||
|
shader->m_UsingCG = usingCG;
|
||||||
|
|
||||||
|
if (usingCG) {
|
||||||
|
shader->CompileCG(a4, shaderCode, codeLen, a7, logInfo);
|
||||||
|
} else {
|
||||||
|
shader->m_Code.assign(shaderCode, codeLen);
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// sub_5CD10(shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GLShader::CheckErrorsARB(GLShaderLogInfo* logInfo) {
|
||||||
|
GLint errorPos;
|
||||||
|
|
||||||
|
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
|
||||||
|
const GLubyte* errorStr = glGetString(GL_PROGRAM_ERROR_STRING_ARB);
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// Blizzard::Debug::VAssert(logInfo != 0 || errorPos == -1, errorStr);
|
||||||
|
|
||||||
|
return errorPos == -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLShader::Compile(GLShaderLogInfo* logInfo) {
|
||||||
|
this->ImmediateCompile(logInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLShader::CompileCG(const char* a2, const void* shaderCode, int32_t codeLen, const char* a5, GLShaderLogInfo* logInfo) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLShader::FlushUniforms(GLGLSLProgram* program) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string& GLShader::GetCode() {
|
||||||
|
return this->m_Code;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t GLShader::GetShaderType() {
|
||||||
|
return this->m_ShaderType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLShader::ImmediateCompile(GLShaderLogInfo* logInfo) {
|
||||||
|
BLIZZARD_ASSERT(!this->GetCode().empty());
|
||||||
|
|
||||||
|
this->m_Device = GLSDLDevice::Get();
|
||||||
|
|
||||||
|
if (!this->m_UsingGLSL) {
|
||||||
|
if (!this->m_ShaderID) {
|
||||||
|
if (this->m_ShaderType == eVertexShader) {
|
||||||
|
this->m_ShaderID = GLPool<GLVertexShader>::Get()->GetNextName();
|
||||||
|
} else {
|
||||||
|
this->m_ShaderID = GLPool<GLPixelShader>::Get()->GetNextName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->m_Device->BindShader(this);
|
||||||
|
|
||||||
|
const char* arbCode = this->GetCode().c_str();
|
||||||
|
size_t arbLen = strlen(arbCode);
|
||||||
|
|
||||||
|
glProgramStringARB(this->var5, GL_PROGRAM_FORMAT_ASCII_ARB, arbLen, arbCode);
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT(this->CheckErrorsARB(logInfo));
|
||||||
|
} else {
|
||||||
|
// TODO
|
||||||
|
// - handle GLSL shaders
|
||||||
|
// - handle hybrid shaders
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logInfo) {
|
||||||
|
// TODO
|
||||||
|
// this->var20 = logInfo[0];
|
||||||
|
} else {
|
||||||
|
this->var20 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// this->m_TimeStamp = Blizzard::Time::GetTimestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GLShader::IsEnabled() {
|
||||||
|
return this->m_Enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLShader::ReleaseObject() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLShader::SetShaderConstants(ShaderType shaderType, uint32_t index, const float* constants, uint32_t count) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
75
src/gx/glsdl/GLShader.hpp
Normal file
75
src/gx/glsdl/GLShader.hpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_SHADER_HPP
|
||||||
|
#define GX_GL_SDL_GL_SHADER_HPP
|
||||||
|
|
||||||
|
#include "gx/glsdl/GLObject.hpp"
|
||||||
|
#include "gx/glsdl/GLShaderInput.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class GLSDLDevice;
|
||||||
|
class GLGLSLProgram;
|
||||||
|
class GLShaderLogInfo;
|
||||||
|
|
||||||
|
class GLShader : public GLObject {
|
||||||
|
public:
|
||||||
|
// Types
|
||||||
|
enum ShaderType {
|
||||||
|
eVertexShader = 1,
|
||||||
|
ePixelShader = 2,
|
||||||
|
eShaderTypeCount = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ShaderDataHeader {
|
||||||
|
uint32_t signature;
|
||||||
|
uint32_t size;
|
||||||
|
ShaderType shaderType;
|
||||||
|
uint32_t codePos;
|
||||||
|
uint32_t codeSize;
|
||||||
|
uint32_t unk1;
|
||||||
|
uint32_t unk2;
|
||||||
|
uint32_t unk3;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Static functions
|
||||||
|
static GLShader* Create(ShaderType, bool, bool, const char*, const void*, int32_t, const char*, const char*, GLShaderLogInfo*);
|
||||||
|
|
||||||
|
// Member variables
|
||||||
|
int32_t m_ShaderType = 0;
|
||||||
|
int32_t var5 = 0;
|
||||||
|
uint32_t m_ShaderID = 0;
|
||||||
|
bool m_UsingCG = false;
|
||||||
|
bool m_UsingGLSL = false;
|
||||||
|
uint32_t m_UniformRegisterCount = 0;
|
||||||
|
GLShaderInput** var10 = nullptr;
|
||||||
|
float* var11 = nullptr;
|
||||||
|
bool var12 = false;
|
||||||
|
uint32_t var13 = 0;
|
||||||
|
uint32_t var14 = 0;
|
||||||
|
std::vector<GLShaderInput*, std::allocator<GLShaderInput*>> var15;
|
||||||
|
std::vector<GLShaderInput*, std::allocator<GLShaderInput*>> var16;
|
||||||
|
std::vector<GLShaderInput*, std::allocator<GLShaderInput*>> var17;
|
||||||
|
GLShader* var18 = nullptr;
|
||||||
|
GLSDLDevice* m_Device = nullptr;
|
||||||
|
bool var20 = 0;
|
||||||
|
bool m_Enabled = true;
|
||||||
|
std::basic_string<char, std::char_traits<char>, std::allocator<char>> m_Code;
|
||||||
|
std::basic_string<char, std::char_traits<char>, std::allocator<char>> var23;
|
||||||
|
|
||||||
|
// Virtual member functions
|
||||||
|
virtual void ReleaseObject();
|
||||||
|
|
||||||
|
// Member functions
|
||||||
|
bool CheckErrorsARB(GLShaderLogInfo*);
|
||||||
|
bool CheckErrorsGLSL(GLShaderLogInfo*);
|
||||||
|
void Compile(GLShaderLogInfo*);
|
||||||
|
void CompileCG(const char*, const void*, int32_t, const char*, GLShaderLogInfo*);
|
||||||
|
void FlushUniforms(GLGLSLProgram*);
|
||||||
|
std::string& GetCode(void);
|
||||||
|
int32_t GetShaderType(void);
|
||||||
|
void ImmediateCompile(GLShaderLogInfo*);
|
||||||
|
bool IsEnabled(void);
|
||||||
|
void SetShaderConstants(ShaderType, uint32_t, const float*, uint32_t);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
33
src/gx/glsdl/GLShaderInput.hpp
Normal file
33
src/gx/glsdl/GLShaderInput.hpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_SHADER_INPUT_HPP
|
||||||
|
#define GX_GL_SDL_GL_SHADER_INPUT_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class GLShader;
|
||||||
|
|
||||||
|
class GLShaderInput {
|
||||||
|
public:
|
||||||
|
// Member variables
|
||||||
|
GLShader *m_Shader;
|
||||||
|
std::basic_string<char, std::char_traits<char>, std::allocator<char>> m_Name;
|
||||||
|
std::basic_string<char, std::char_traits<char>, std::allocator<char>> var2;
|
||||||
|
int16_t m_MapIndex;
|
||||||
|
int16_t var4;
|
||||||
|
int16_t var5;
|
||||||
|
int16_t m_UsedSize;
|
||||||
|
int16_t var7;
|
||||||
|
int16_t var8;
|
||||||
|
GLShaderInput *m_Parent;
|
||||||
|
int32_t var10;
|
||||||
|
int32_t var11;
|
||||||
|
int32_t var12;
|
||||||
|
int8_t m_ChildrenCount;
|
||||||
|
int8_t var14;
|
||||||
|
uint16_t var15;
|
||||||
|
int8_t var16;
|
||||||
|
int8_t m_Variability;
|
||||||
|
int8_t var18;
|
||||||
|
int8_t var19;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
632
src/gx/glsdl/GLTexture.cpp
Normal file
632
src/gx/glsdl/GLTexture.cpp
Normal file
@ -0,0 +1,632 @@
|
|||||||
|
#include "gx/glsdl/GLTexture.hpp"
|
||||||
|
#include "gx/glsdl/GLSDLDevice.hpp"
|
||||||
|
#include "gx/glsdl/GLPool.hpp"
|
||||||
|
#include "gx/glsdl/GLUtil.hpp"
|
||||||
|
#include "gx/texture/CGxTex.hpp"
|
||||||
|
#include <deque>
|
||||||
|
#include <bc/Debug.hpp>
|
||||||
|
#include <bc/Memory.hpp>
|
||||||
|
|
||||||
|
Blizzard::Thread::TLSSlot GLTexture::m_Bindings[4];
|
||||||
|
|
||||||
|
void* GLTexture::CreateBindings(void* ptr) {
|
||||||
|
return new std::deque<std::vector<Binding>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::DestroyBindings(void* ptr) {
|
||||||
|
delete static_cast<std::deque<std::vector<Binding>>*>(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::Bind(GLSDLDevice* device, bool force) {
|
||||||
|
BLIZZARD_ASSERT(!this->IsSystemBuffer());
|
||||||
|
BLIZZARD_ASSERT(this->m_Depth != 0);
|
||||||
|
|
||||||
|
if (!device) {
|
||||||
|
device = GLSDLDevice::Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT(device != nullptr);
|
||||||
|
|
||||||
|
auto& bindings = this->GetBindings();
|
||||||
|
uint32_t deviceID = device->GetID();
|
||||||
|
|
||||||
|
if (deviceID >= bindings.size()) {
|
||||||
|
bindings.resize(deviceID + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bindings[deviceID].device = device;
|
||||||
|
|
||||||
|
uint32_t currentActiveTexture = device->m_States.binding.currentActiveTexture;
|
||||||
|
|
||||||
|
if (bindings[deviceID].boundStages[currentActiveTexture]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force) {
|
||||||
|
bindings[deviceID].boundStages[currentActiveTexture] = 1;
|
||||||
|
device->BindTexture(this->m_TextureType, this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < 16; i++) {
|
||||||
|
if (bindings[deviceID].boundStages[i]) {
|
||||||
|
device->SetActiveTexture(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bindings[deviceID].boundStages[currentActiveTexture] = 1;
|
||||||
|
device->BindTexture(this->m_TextureType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::FreeTexture() {
|
||||||
|
auto device = GLSDLDevice::Get();
|
||||||
|
|
||||||
|
int32_t numFace = this->m_TextureType == GL_TEXTURE_CUBE_MAP ? 6 : 1;
|
||||||
|
for (int32_t face = 0; face < numFace; face++) {
|
||||||
|
if (this->m_Mipmaps[face]) {
|
||||||
|
delete[] this->m_Mipmaps[face];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->m_Mipmaps) {
|
||||||
|
delete[] this->m_Mipmaps;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->m_Mipmaps = nullptr;
|
||||||
|
this->m_Depth = 0;
|
||||||
|
|
||||||
|
// TODO this->Sub690D0();
|
||||||
|
|
||||||
|
glDeleteTextures(1, &this->m_TextureID);
|
||||||
|
|
||||||
|
this->m_GenerateMipmaps = 0;
|
||||||
|
this->m_MaxMipmapLevel = 1000;
|
||||||
|
this->m_BaseMipmapLevel = 0;
|
||||||
|
this->m_CompareMode = 0;
|
||||||
|
|
||||||
|
this->m_Sampler.mipmapBias = 0.0f;
|
||||||
|
this->m_Sampler.borderColor = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
this->m_Sampler.addressModeS = GL_REPEAT;
|
||||||
|
this->m_Sampler.addressModeT = GL_REPEAT;
|
||||||
|
this->m_Sampler.addressModeR = GL_REPEAT;
|
||||||
|
this->m_Sampler.magFilterMode = GL_LINEAR;
|
||||||
|
this->m_Sampler.minFilterMode = GL_NEAREST_MIPMAP_LINEAR;
|
||||||
|
this->m_Sampler.maxAnisotropy = 1.0f;
|
||||||
|
|
||||||
|
Blizzard::Memory::Free(this->m_Data);
|
||||||
|
this->m_Data = nullptr;
|
||||||
|
|
||||||
|
switch (this->m_TextureType) {
|
||||||
|
case GL_TEXTURE_3D:
|
||||||
|
// TODO GLPool<GLTexture3D>::GLObjectPool::Push(GLPool<GLTexture3D>::m_pool + 264, this);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_TEXTURE_CUBE_MAP:
|
||||||
|
// TODO GLPool<GLTextureCubeMap>::GLObjectPool::Push(GLPool<GLTextureCubeMap>::m_pool + 520, this);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_TEXTURE_2D:
|
||||||
|
// TODO GLPool<GLTexture2D>::GLObjectPool::Push(GLPool<GLTexture2D>::m_pool + 131080, this);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<GLTexture::Binding>& GLTexture::GetBindings() {
|
||||||
|
uint32_t index = GLSDLTextureTypeToIndex(this->m_TextureType);
|
||||||
|
|
||||||
|
uint32_t id;
|
||||||
|
|
||||||
|
if (index == 0) {
|
||||||
|
id = this->m_TextureID - 33;
|
||||||
|
} else if (index == 1) {
|
||||||
|
id = this->m_TextureID - 32801;
|
||||||
|
} else if (index == 2) {
|
||||||
|
id = this->m_TextureID - 32865;
|
||||||
|
} else if (index == 3) {
|
||||||
|
id = this->m_TextureID - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto target = static_cast<std::deque<std::vector<Binding>>*>(
|
||||||
|
Blizzard::Thread::RegisterLocalStorage(
|
||||||
|
&GLTexture::m_Bindings[index],
|
||||||
|
GLTexture::CreateBindings,
|
||||||
|
nullptr,
|
||||||
|
GLTexture::DestroyBindings
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (id >= target->size()) {
|
||||||
|
target->resize(id + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (*target)[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
GLTextureFormat GLTexture::GetFormat() {
|
||||||
|
return this->m_Format;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureFormatInfo& GLTexture::GetFormatInfo() {
|
||||||
|
return k_TextureFormatInfo[this->m_Format];
|
||||||
|
}
|
||||||
|
|
||||||
|
GLMipmap* GLTexture::GetMipmap(uint32_t level, GLEnum face) {
|
||||||
|
BLIZZARD_ASSERT(face >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
|
||||||
|
BLIZZARD_ASSERT(level < this->m_NumMipmap);
|
||||||
|
BLIZZARD_ASSERT(this->m_Mipmaps != nullptr);
|
||||||
|
BLIZZARD_ASSERT(this->m_Mipmaps[face - GL_TEXTURE_CUBE_MAP_POSITIVE_X] != nullptr);
|
||||||
|
|
||||||
|
return &this->m_Mipmaps[face - GL_TEXTURE_CUBE_MAP_POSITIVE_X][level];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GLTexture::IsRenderTarget() {
|
||||||
|
return this->m_Flags & GLTFLAG_RENDERTARGET;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GLTexture::IsSystemBuffer() {
|
||||||
|
return this->m_Flags & GLTFLAG_SYSTEM_BUFFER;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GLTexture::IsValid() {
|
||||||
|
return this->m_Depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* GLTexture::Map(uint32_t level, const GLRect* a3, uint32_t& a4, GLEnum a5) {
|
||||||
|
BLIZZARD_ASSERT(this->m_TextureType != GL_TEXTURE_3D);
|
||||||
|
|
||||||
|
auto mipmap = this->GetMipmap(level, GL_TEXTURE_CUBE_MAP_POSITIVE_X);
|
||||||
|
a4 = mipmap->GetPitch();
|
||||||
|
return mipmap->Map(a5, a3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::RecreateGLTexture() {
|
||||||
|
if (this->m_TextureType == GL_TEXTURE_RECTANGLE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isCubeMap = this->m_TextureType == GL_TEXTURE_CUBE_MAP;
|
||||||
|
int32_t numFace = isCubeMap ? 6 : 1;
|
||||||
|
|
||||||
|
for (int32_t face = 0; face < numFace; face++) {
|
||||||
|
for (int32_t level = 0; level < this->m_NumMipmap; level++) {
|
||||||
|
this->m_Mipmaps[face][level].Map(GL_WRITE_ONLY, static_cast<GLBox*>(nullptr));
|
||||||
|
this->m_Mipmaps[face][level].Unmap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glTexParameterf(this->m_TextureType, GL_TEXTURE_LOD_BIAS, this->m_Sampler.mipmapBias);
|
||||||
|
glTexParameteri(this->m_TextureType, GL_TEXTURE_WRAP_S, this->m_Sampler.addressModeS);
|
||||||
|
glTexParameteri(this->m_TextureType, GL_TEXTURE_WRAP_T, this->m_Sampler.addressModeT);
|
||||||
|
glTexParameteri(this->m_TextureType, GL_TEXTURE_WRAP_R, this->m_Sampler.addressModeR);
|
||||||
|
glTexParameteri(this->m_TextureType, GL_TEXTURE_MIN_FILTER, this->m_Sampler.minFilterMode);
|
||||||
|
glTexParameteri(this->m_TextureType, GL_TEXTURE_MAG_FILTER, this->m_Sampler.magFilterMode);
|
||||||
|
glTexParameterf(this->m_TextureType, GL_TEXTURE_MAX_ANISOTROPY_EXT, this->m_Sampler.maxAnisotropy);
|
||||||
|
glTexParameterfv(this->m_TextureType, GL_TEXTURE_BORDER_COLOR, reinterpret_cast<GLfloat*>(&this->m_Sampler.borderColor));
|
||||||
|
glTexParameteri(this->m_TextureType, GL_TEXTURE_MAX_LEVEL, this->m_MaxMipmapLevel);
|
||||||
|
glTexParameteri(this->m_TextureType, GL_TEXTURE_BASE_LEVEL, this->m_BaseMipmapLevel);
|
||||||
|
glTexParameteri(this->m_TextureType, GL_GENERATE_MIPMAP, this->m_GenerateMipmaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::ResizeMipmaps() {
|
||||||
|
BLIZZARD_ASSERT(this->m_Mipmaps == nullptr);
|
||||||
|
|
||||||
|
int32_t numFace = this->m_TextureType == GL_TEXTURE_CUBE_MAP ? 6 : 1;
|
||||||
|
|
||||||
|
this->m_Mipmaps = new GLMipmap*[numFace];
|
||||||
|
|
||||||
|
for (int32_t face = 0; face < numFace; face++) {
|
||||||
|
this->m_Mipmaps[face] = new GLMipmap[this->m_NumMipmap];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::SetAddressModeR(GLEnum mode) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::SetAddressModeS(GLEnum mode) {
|
||||||
|
if (this->m_Sampler.addressModeS == mode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == GL_CLAMP_TO_EDGE) {
|
||||||
|
this->Bind(nullptr, 0);
|
||||||
|
glTexParameteri(this->m_TextureType, GL_TEXTURE_WRAP_S, mode);
|
||||||
|
this->m_Sampler.addressModeS = mode;
|
||||||
|
} else {
|
||||||
|
// Workaround for buggy GPU (possibly ATI Radeon X1900)
|
||||||
|
if (GLSDLDevice::GetRendererInfo().renderer_id == 0x21900) {
|
||||||
|
if (this->m_Width & (this->m_Width - 1)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->m_Height & (this->m_Height - 1)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->Bind(nullptr, 0);
|
||||||
|
glTexParameteri(this->m_TextureType, GL_TEXTURE_WRAP_S, mode);
|
||||||
|
this->m_Sampler.addressModeS = mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::SetAddressModeT(GLEnum mode) {
|
||||||
|
if (this->m_Sampler.addressModeT == mode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == GL_CLAMP_TO_EDGE) {
|
||||||
|
this->Bind(nullptr, 0);
|
||||||
|
glTexParameteri(this->m_TextureType, GL_TEXTURE_WRAP_T, mode);
|
||||||
|
this->m_Sampler.addressModeT = mode;
|
||||||
|
} else {
|
||||||
|
// Workaround for buggy GPU (possibly ATI Radeon X1900)
|
||||||
|
if (GLSDLDevice::GetRendererInfo().renderer_id == 0x21900) {
|
||||||
|
if (this->m_Width & (this->m_Width - 1)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->m_Height & (this->m_Height - 1)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->Bind(nullptr, 0);
|
||||||
|
glTexParameteri(this->m_TextureType, GL_TEXTURE_WRAP_T, mode);
|
||||||
|
this->m_Sampler.addressModeT = mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::SetBorderColor(const GLColor4f& color) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::SetCompareMode(GLEnum compareMode) {
|
||||||
|
BLIZZARD_ASSERT(
|
||||||
|
this->GetFormatInfo().m_DataFormat == GL_DEPTH_COMPONENT
|
||||||
|
|| this->GetFormatInfo().m_DataFormat == GL_DEPTH_STENCIL_EXT
|
||||||
|
|| compareMode == GL_NONE
|
||||||
|
);
|
||||||
|
|
||||||
|
if (this->m_CompareMode != compareMode) {
|
||||||
|
this->Bind(nullptr, 0);
|
||||||
|
glTexParameteri(this->m_TextureType, GL_TEXTURE_COMPARE_MODE, compareMode);
|
||||||
|
this->m_CompareMode = compareMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::SetMagFilterMode(GLEnum mode) {
|
||||||
|
if (this->m_Sampler.magFilterMode == mode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GLSDLDevice::GetRendererInfo().vendor_id == 2 && this->IsRenderTarget() && mode != GL_LINEAR) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->Bind(nullptr, 0);
|
||||||
|
glTexParameteri(this->m_TextureType, GL_TEXTURE_MAG_FILTER, mode);
|
||||||
|
this->m_Sampler.magFilterMode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::SetMaxAnisotropy(int32_t maxAnisotropy) {
|
||||||
|
if (this->m_Sampler.maxAnisotropy == maxAnisotropy) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->Bind(nullptr, 0);
|
||||||
|
glTexParameterf(this->m_TextureType, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
|
||||||
|
this->m_Sampler.maxAnisotropy = maxAnisotropy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::SetMinFilterMode(GLEnum mode) {
|
||||||
|
if (this->m_Sampler.minFilterMode == mode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GLSDLDevice::GetRendererInfo().vendor_id == 2 && this->IsRenderTarget() && mode != GL_LINEAR) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->Bind(nullptr, 0);
|
||||||
|
glTexParameteri(this->m_TextureType, GL_TEXTURE_MIN_FILTER, mode);
|
||||||
|
this->m_Sampler.minFilterMode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::SetupTexture() {
|
||||||
|
BLIZZARD_ASSERT(this->m_NumMipmap == 1 || (this->m_Flags & GLTFLAG_AUTOGEN_MIPMAP) == 0);
|
||||||
|
BLIZZARD_ASSERT(!this->IsRenderTarget() || this->m_NumMipmap == 1);
|
||||||
|
BLIZZARD_ASSERT(!this->IsRenderTarget() || (this->m_Flags & GLTFLAG_READ_ACCESS) == 0);
|
||||||
|
|
||||||
|
GLSDLDevice* device = GLSDLDevice::Get();
|
||||||
|
|
||||||
|
if (this->GetFormatInfo().m_IsCompressed) {
|
||||||
|
int32_t smallestDim = std::min(this->m_Width, this->m_Height);
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT(smallestDim >= 4);
|
||||||
|
|
||||||
|
if (smallestDim == 4) {
|
||||||
|
this->m_NumMipmap = 1;
|
||||||
|
} else if (smallestDim == 8) {
|
||||||
|
this->m_NumMipmap = 2;
|
||||||
|
} else if (smallestDim == 16) {
|
||||||
|
this->m_NumMipmap = 3;
|
||||||
|
} else if (smallestDim == 32) {
|
||||||
|
this->m_NumMipmap = 4;
|
||||||
|
} else if (smallestDim == 64) {
|
||||||
|
this->m_NumMipmap = 5;
|
||||||
|
} else if (smallestDim == 128) {
|
||||||
|
this->m_NumMipmap = 6;
|
||||||
|
} else if (smallestDim == 256) {
|
||||||
|
this->m_NumMipmap = 7;
|
||||||
|
} else if (smallestDim == 512) {
|
||||||
|
this->m_NumMipmap = 8;
|
||||||
|
} else if (smallestDim == 1024) {
|
||||||
|
this->m_NumMipmap = 9;
|
||||||
|
} else if (smallestDim == 2048) {
|
||||||
|
this->m_NumMipmap = 10;
|
||||||
|
} else if (smallestDim == 4096) {
|
||||||
|
this->m_NumMipmap = 11;
|
||||||
|
} else {
|
||||||
|
int32_t i = smallestDim >> 1;
|
||||||
|
int32_t n = 0;
|
||||||
|
|
||||||
|
while (i) {
|
||||||
|
i >>= 1;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->m_NumMipmap = n - 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int32_t largestDim = std::max(this->m_Width, this->m_Height);
|
||||||
|
|
||||||
|
if (largestDim == 1) {
|
||||||
|
this->m_NumMipmap = 1;
|
||||||
|
} else if (largestDim == 2) {
|
||||||
|
this->m_NumMipmap = 2;
|
||||||
|
} else if (largestDim == 4) {
|
||||||
|
this->m_NumMipmap = 3;
|
||||||
|
} else if (largestDim == 8) {
|
||||||
|
this->m_NumMipmap = 4;
|
||||||
|
} else if (largestDim == 16) {
|
||||||
|
this->m_NumMipmap = 5;
|
||||||
|
} else if (largestDim == 32) {
|
||||||
|
this->m_NumMipmap = 6;
|
||||||
|
} else if (largestDim == 64) {
|
||||||
|
this->m_NumMipmap = 7;
|
||||||
|
} else if (largestDim == 128) {
|
||||||
|
this->m_NumMipmap = 8;
|
||||||
|
} else if (largestDim == 256) {
|
||||||
|
this->m_NumMipmap = 9;
|
||||||
|
} else if (largestDim == 512) {
|
||||||
|
this->m_NumMipmap = 10;
|
||||||
|
} else if (largestDim == 1024) {
|
||||||
|
this->m_NumMipmap = 11;
|
||||||
|
} else if (largestDim == 2048) {
|
||||||
|
this->m_NumMipmap = 12;
|
||||||
|
} else if (largestDim == 4096) {
|
||||||
|
this->m_NumMipmap = 13;
|
||||||
|
} else {
|
||||||
|
int32_t i = largestDim >> 1;
|
||||||
|
int32_t n = 0;
|
||||||
|
|
||||||
|
while (i) {
|
||||||
|
i >>= 1;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->m_NumMipmap = n + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(this->m_Flags & GLTFLAG_SYSTEM_BUFFER)) {
|
||||||
|
BLIZZARD_ASSERT(this->m_RequestedNumMipmaps != 0);
|
||||||
|
|
||||||
|
this->m_NumMipmap = std::min(this->m_NumMipmap, this->m_RequestedNumMipmaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->var12 = this->GetFormatInfo().m_BytePerPixel * this->m_Width;
|
||||||
|
if (this->GetFormatInfo().m_IsCompressed) {
|
||||||
|
this->var12 >>= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->ResizeMipmaps();
|
||||||
|
|
||||||
|
bool isCubeMap = this->m_TextureType == GL_TEXTURE_CUBE_MAP;
|
||||||
|
|
||||||
|
this->m_Size = 0;
|
||||||
|
|
||||||
|
int32_t numFace = isCubeMap ? 6 : 1;
|
||||||
|
|
||||||
|
for (int32_t face = 0; face < numFace; face++) {
|
||||||
|
for (int32_t level = 0; level < this->m_NumMipmap; level++) {
|
||||||
|
GLMipmap* mip = this->GetMipmap(level, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face);
|
||||||
|
|
||||||
|
mip->m_Level = level;
|
||||||
|
mip->m_Texture = this;
|
||||||
|
mip->ResetSize(this->m_Width >> level, this->m_Height >> level, this->m_Depth >> level);
|
||||||
|
|
||||||
|
this->m_Size += mip->m_Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->var7 = GLSDLDevice::m_Devices[0]->m_TextureList.begin();
|
||||||
|
|
||||||
|
if (this->m_Flags & GLTFLAG_SYSTEM_BUFFER) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT(this->m_Data == nullptr);
|
||||||
|
|
||||||
|
if (!this->IsRenderTarget()) {
|
||||||
|
this->m_Data = static_cast<char*>(Blizzard::Memory::Allocate(this->m_Size));
|
||||||
|
}
|
||||||
|
|
||||||
|
this->Bind(nullptr, 0);
|
||||||
|
|
||||||
|
if (this->IsRenderTarget()) {
|
||||||
|
this->SetAddressModeR(GL_CLAMP_TO_EDGE);
|
||||||
|
this->SetAddressModeS(GL_CLAMP_TO_EDGE);
|
||||||
|
this->SetAddressModeT(GL_CLAMP_TO_EDGE);
|
||||||
|
this->SetMinFilterMode(GL_LINEAR);
|
||||||
|
this->SetMagFilterMode(GL_LINEAR);
|
||||||
|
|
||||||
|
// glTexParameteri(this->m_TextureType, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE);
|
||||||
|
} else {
|
||||||
|
this->SetAddressModeR(GL_REPEAT);
|
||||||
|
this->SetAddressModeS(GL_REPEAT);
|
||||||
|
this->SetAddressModeT(GL_REPEAT);
|
||||||
|
this->SetMinFilterMode(GL_NEAREST_MIPMAP_NEAREST);
|
||||||
|
this->SetMagFilterMode(GL_NEAREST);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->GetFormatInfo().m_DataFormat == GL_DEPTH_COMPONENT || this->GetFormatInfo().m_DataFormat == GL_DEPTH_STENCIL) {
|
||||||
|
this->SetCompareMode(GLSDLDevice::m_ExtARBShadow >= 1 ? GL_COMPARE_R_TO_TEXTURE : 0);
|
||||||
|
glTexParameteri(this->m_TextureType, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
||||||
|
glTexParameteri(this->m_TextureType, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
|
||||||
|
} else {
|
||||||
|
this->SetCompareMode(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->SetMaxAnisotropy(1);
|
||||||
|
|
||||||
|
this->SetBorderColor(GLColor4f::ZERO);
|
||||||
|
|
||||||
|
int32_t autogenMipmap = this->m_Flags & GLTFLAG_AUTOGEN_MIPMAP;
|
||||||
|
if (autogenMipmap != this->m_GenerateMipmaps) {
|
||||||
|
this->Bind(nullptr, 0);
|
||||||
|
glTexParameteri(this->m_TextureType, GL_GENERATE_MIPMAP, autogenMipmap);
|
||||||
|
this->m_GenerateMipmaps = autogenMipmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t maxMipmapLevel = this->m_NumMipmap - 1;
|
||||||
|
if (maxMipmapLevel != this->m_MaxMipmapLevel) {
|
||||||
|
this->Bind(nullptr, 0);
|
||||||
|
glTexParameteri(this->m_TextureType, GL_TEXTURE_MAX_LEVEL, maxMipmapLevel);
|
||||||
|
this->m_MaxMipmapLevel = maxMipmapLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->m_TextureType == GL_TEXTURE_RECTANGLE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->IsRenderTarget()) {
|
||||||
|
device->SetUnpackClientStorage(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* data = reinterpret_cast<unsigned char*>(this->m_Data);
|
||||||
|
|
||||||
|
for (int32_t face = 0; face < numFace; face++) {
|
||||||
|
for (int32_t level = 0; level < this->m_NumMipmap; level++) {
|
||||||
|
GLMipmap* mip = this->GetMipmap(level, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face);
|
||||||
|
|
||||||
|
if (this->m_TextureType == GL_TEXTURE_CUBE_MAP) {
|
||||||
|
mip->ResetData(face, level, data);
|
||||||
|
} else {
|
||||||
|
mip->ResetData(this->m_TextureType, level, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
data += mip->m_Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// this->m_TimeStamp = Blizzard::Time::GetTimestamp();
|
||||||
|
|
||||||
|
if (this->IsRenderTarget()) {
|
||||||
|
device->SetUnpackClientStorage(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::Unbind(GLSDLDevice* device, uint32_t stage) {
|
||||||
|
auto& bindings = this->GetBindings();
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT(device->GetID() < bindings.size());
|
||||||
|
BLIZZARD_ASSERT(bindings[device->GetID()].device == device);
|
||||||
|
BLIZZARD_ASSERT(bindings[device->GetID()].boundStages[stage]);
|
||||||
|
|
||||||
|
bindings[device->GetID()].boundStages[stage] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::Unmap(uint32_t level, GLEnum face) {
|
||||||
|
auto mipmap = this->GetMipmap(level, face);
|
||||||
|
mipmap->Unmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLTexture2D* GLTexture2D::Create(uint32_t width, uint32_t height, uint32_t numMipMap, GLTextureFormat format, uint32_t flags) {
|
||||||
|
GLTexture2D* tex;
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// tex = GLPool<GLTexture2D>::GLObjectPool::Pop(GLPool<GLTexture2D>::m_pool + 131080);
|
||||||
|
tex = nullptr;
|
||||||
|
|
||||||
|
if (!tex) {
|
||||||
|
tex = new GLTexture2D();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// Blizzard::Debug::Assert(tex->m_refCount == 0);
|
||||||
|
|
||||||
|
tex->m_RefCount = 1;
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// Blizzard::Debug::Assert(tex->m_TextureID >= PoolStats<GLTexture2D>::NAME_POOL_FIRST_NAME);
|
||||||
|
|
||||||
|
tex->m_TextureType = GL_TEXTURE_2D;
|
||||||
|
tex->m_Width = width;
|
||||||
|
tex->m_Depth = 1;
|
||||||
|
tex->m_Height = height;
|
||||||
|
tex->m_Format = format;
|
||||||
|
tex->m_NumMipmap = numMipMap;
|
||||||
|
tex->m_RequestedNumMipmaps = numMipMap;
|
||||||
|
tex->m_Flags = flags;
|
||||||
|
|
||||||
|
tex->SetupTexture();
|
||||||
|
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLTexture2D::GLTexture2D() : GLTexture() {
|
||||||
|
this->m_TextureType = GL_TEXTURE_2D;
|
||||||
|
this->m_TextureID = GLPool<GLTexture2D>::Get()->GetNextName();
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// Blizzard::Debug::Assert(this->m_TextureID >= PoolStats<GLTexture2D>::NAME_POOL_FIRST_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture2D::ReleaseObject() {
|
||||||
|
BLIZZARD_ASSERT(this->m_TextureType == GL_TEXTURE_2D);
|
||||||
|
this->FreeTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLSDLTexSetFlags(CGxTex* texId, GLTexture* a2) {
|
||||||
|
static GLEnum convertMagFilterToOgl[] = {
|
||||||
|
GL_NEAREST,
|
||||||
|
GL_LINEAR,
|
||||||
|
GL_NEAREST,
|
||||||
|
GL_LINEAR,
|
||||||
|
GL_LINEAR,
|
||||||
|
GL_LINEAR
|
||||||
|
};
|
||||||
|
|
||||||
|
static GLEnum convertMinFilterToOgl[] = {
|
||||||
|
GL_NEAREST,
|
||||||
|
GL_LINEAR,
|
||||||
|
GL_NEAREST_MIPMAP_NEAREST,
|
||||||
|
GL_LINEAR_MIPMAP_NEAREST,
|
||||||
|
GL_LINEAR_MIPMAP_LINEAR,
|
||||||
|
GL_LINEAR_MIPMAP_LINEAR
|
||||||
|
};
|
||||||
|
|
||||||
|
a2->SetMagFilterMode(convertMagFilterToOgl[texId->m_flags.m_filter]);
|
||||||
|
a2->SetMinFilterMode(convertMinFilterToOgl[texId->m_flags.m_filter]);
|
||||||
|
|
||||||
|
a2->SetAddressModeS(texId->m_flags.m_wrapU ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
||||||
|
a2->SetAddressModeT(texId->m_flags.m_wrapV ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
a2->SetMaxAnisotropy(texId->m_flags.m_maxAnisotropy);
|
||||||
|
}
|
||||||
101
src/gx/glsdl/GLTexture.hpp
Normal file
101
src/gx/glsdl/GLTexture.hpp
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_TEXTURE_HPP
|
||||||
|
#define GX_GL_SDL_GL_TEXTURE_HPP
|
||||||
|
|
||||||
|
#include "gx/glsdl/GL.hpp"
|
||||||
|
#include "gx/glsdl/GLObject.hpp"
|
||||||
|
#include "gx/glsdl/GLTypes.hpp"
|
||||||
|
#include <list>
|
||||||
|
#include <vector>
|
||||||
|
#include <atomic>
|
||||||
|
#include <bc/Thread.hpp>
|
||||||
|
|
||||||
|
#define GLTFLAG_RENDERTARGET 0x1
|
||||||
|
#define GLTFLAG_DEPTH 0x2
|
||||||
|
#define GLTFLAG_STENCIL 0x4
|
||||||
|
#define GLTFLAG_AUTOGEN_MIPMAP 0x8
|
||||||
|
#define GLTFLAG_READ_ACCESS 0x10
|
||||||
|
#define GLTFLAG_SYSTEM_BUFFER 0x20
|
||||||
|
|
||||||
|
class CGxTex;
|
||||||
|
class GLMipmap;
|
||||||
|
class GLSDLDevice;
|
||||||
|
|
||||||
|
class GLTexture : public GLObject {
|
||||||
|
public:
|
||||||
|
// Types
|
||||||
|
struct Binding {
|
||||||
|
uint8_t boundStages[16];
|
||||||
|
GLSDLDevice* device;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Static variables
|
||||||
|
static Blizzard::Thread::TLSSlot m_Bindings[4];
|
||||||
|
|
||||||
|
// Static functions
|
||||||
|
static void* CreateBindings(void*);
|
||||||
|
static void DestroyBindings(void*);
|
||||||
|
|
||||||
|
// Member variables
|
||||||
|
uint32_t m_TextureID = 0;
|
||||||
|
GLEnum m_TextureType = 0;
|
||||||
|
GLMipmap** m_Mipmaps = nullptr;
|
||||||
|
std::list<GLTexture*>::iterator var7;
|
||||||
|
uint32_t m_LastFrameUsed;
|
||||||
|
uint32_t m_Width = 0;
|
||||||
|
uint32_t m_Height = 0;
|
||||||
|
uint32_t m_Depth = 0;
|
||||||
|
uint32_t var12 = 0;
|
||||||
|
uint32_t m_Size = 0;
|
||||||
|
GLTextureFormat m_Format = GLTF_INVALID;
|
||||||
|
uint32_t m_Flags = 0;
|
||||||
|
uint32_t m_NumMipmap = 0;
|
||||||
|
uint32_t m_RequestedNumMipmaps;
|
||||||
|
char* m_Data = nullptr;
|
||||||
|
std::atomic<int32_t> m_MappedMipmaps = { 0 };
|
||||||
|
GLStates::Sampler m_Sampler;
|
||||||
|
bool m_GenerateMipmaps = 0;
|
||||||
|
int32_t m_MaxMipmapLevel = 1000;
|
||||||
|
int32_t m_BaseMipmapLevel = 0;
|
||||||
|
int32_t m_CompareMode = 0;
|
||||||
|
|
||||||
|
// Member functions
|
||||||
|
void Bind(GLSDLDevice*, bool);
|
||||||
|
void FreeTexture();
|
||||||
|
std::vector<Binding>& GetBindings(void); // invented name
|
||||||
|
GLTextureFormat GetFormat(void);
|
||||||
|
TextureFormatInfo& GetFormatInfo(void);
|
||||||
|
GLMipmap* GetMipmap(uint32_t, GLEnum);
|
||||||
|
bool IsRenderTarget(void);
|
||||||
|
bool IsSystemBuffer(void);
|
||||||
|
bool IsValid(void);
|
||||||
|
void* Map(uint32_t, const GLRect*, uint32_t&, GLEnum);
|
||||||
|
void RecreateGLTexture(void);
|
||||||
|
void ResizeMipmaps(void);
|
||||||
|
void SetAddressModeR(GLEnum);
|
||||||
|
void SetAddressModeS(GLEnum);
|
||||||
|
void SetAddressModeT(GLEnum);
|
||||||
|
void SetBorderColor(const GLColor4f&);
|
||||||
|
void SetCompareMode(GLEnum);
|
||||||
|
void SetMagFilterMode(GLEnum);
|
||||||
|
void SetMaxAnisotropy(int32_t);
|
||||||
|
void SetMinFilterMode(GLEnum);
|
||||||
|
void SetupTexture(void);
|
||||||
|
void Unbind(GLSDLDevice*, uint32_t); // invented name
|
||||||
|
void Unmap(uint32_t level, GLEnum face);
|
||||||
|
};
|
||||||
|
|
||||||
|
class GLTexture2D : public GLTexture {
|
||||||
|
public:
|
||||||
|
// Static functions
|
||||||
|
static GLTexture2D* Create(uint32_t, uint32_t, uint32_t, GLTextureFormat, uint32_t);
|
||||||
|
|
||||||
|
// Virtual member functions
|
||||||
|
virtual void ReleaseObject();
|
||||||
|
|
||||||
|
// Member functions
|
||||||
|
GLTexture2D();
|
||||||
|
};
|
||||||
|
|
||||||
|
void GLSDLTexSetFlags(CGxTex*, GLTexture*);
|
||||||
|
|
||||||
|
#endif
|
||||||
58
src/gx/glsdl/GLTypes.cpp
Normal file
58
src/gx/glsdl/GLTypes.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include "gx/glsdl/GLTypes.hpp"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
GLColor4f GLColor4f::ZERO = { 0.0, 0.0, 0.0, 0.0 };
|
||||||
|
GLColor4f GLColor4f::WHITE = { 1.0, 1.0, 1.0, 1.0 };
|
||||||
|
GLColor4f GLColor4f::BLACK = { 0.0, 0.0, 0.0, 1.0 };
|
||||||
|
|
||||||
|
bool GLTransform::operator==(const float m[16]) const {
|
||||||
|
return this->m[0] == m[0]
|
||||||
|
&& this->m[1] == m[1]
|
||||||
|
&& this->m[2] == m[2]
|
||||||
|
&& this->m[3] == m[3]
|
||||||
|
&& this->m[4] == m[4]
|
||||||
|
&& this->m[5] == m[5]
|
||||||
|
&& this->m[6] == m[6]
|
||||||
|
&& this->m[7] == m[7]
|
||||||
|
&& this->m[8] == m[8]
|
||||||
|
&& this->m[9] == m[9]
|
||||||
|
&& this->m[10] == m[10]
|
||||||
|
&& this->m[11] == m[11]
|
||||||
|
&& this->m[12] == m[12]
|
||||||
|
&& this->m[13] == m[13]
|
||||||
|
&& this->m[14] == m[14]
|
||||||
|
&& this->m[15] == m[15];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GLTransform::operator!=(const float m[16]) const {
|
||||||
|
return !(*this == m);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTransform::Set(const float m[16]) {
|
||||||
|
memcpy(this->m, m, sizeof(this->m));
|
||||||
|
this->isDirty = true;
|
||||||
|
this->isIdentity = this->a0 == 1.0f
|
||||||
|
&& this->a1 == 0.0f
|
||||||
|
&& this->a2 == 0.0f
|
||||||
|
&& this->a3 == 0.0f
|
||||||
|
&& this->b0 == 0.0f
|
||||||
|
&& this->b1 == 1.0f
|
||||||
|
&& this->b2 == 0.0f
|
||||||
|
&& this->b3 == 0.0f
|
||||||
|
&& this->c0 == 0.0f
|
||||||
|
&& this->c1 == 0.0f
|
||||||
|
&& this->c2 == 1.0f
|
||||||
|
&& this->c3 == 0.0f
|
||||||
|
&& this->d0 == 0.0f
|
||||||
|
&& this->d1 == 0.0f
|
||||||
|
&& this->d2 == 0.0f
|
||||||
|
&& this->d3 == 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTransform::SetIdentity() {
|
||||||
|
memset(this->m, 0, sizeof(this->m));
|
||||||
|
this->a0 = 1.0f;
|
||||||
|
this->b1 = 1.0f;
|
||||||
|
this->c2 = 1.0f;
|
||||||
|
this->d3 = 1.0f;
|
||||||
|
}
|
||||||
376
src/gx/glsdl/GLTypes.hpp
Normal file
376
src/gx/glsdl/GLTypes.hpp
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_TYPES_HPP
|
||||||
|
#define GX_GL_SDL_GL_TYPES_HPP
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
|
||||||
|
class GLBuffer;
|
||||||
|
class GLFramebuffer;
|
||||||
|
|
||||||
|
enum GLTextureFormat {
|
||||||
|
GLTF_INVALID = 0,
|
||||||
|
GLTF_ARGB8888 = 1,
|
||||||
|
GLTF_XRGB8888 = 2,
|
||||||
|
GLTF_RGBA8888 = 3,
|
||||||
|
GLTF_ABGR8888 = 4,
|
||||||
|
GLTF_ARGB0888 = 5,
|
||||||
|
GLTF_RGB888 = 6,
|
||||||
|
GLTF_BGR888 = 7,
|
||||||
|
GLTF_RGBA32F = 8,
|
||||||
|
GLTF_RGBA16F = 9,
|
||||||
|
GLTF_RG16F = 10,
|
||||||
|
GLTF_D32 = 11,
|
||||||
|
GLTF_D24 = 12,
|
||||||
|
GLTF_D16 = 13,
|
||||||
|
GLTF_DF = 14,
|
||||||
|
GLTF_D24S8 = 15,
|
||||||
|
GLTF_S8 = 16,
|
||||||
|
GLTF_ARGB4444 = 17,
|
||||||
|
GLTF_ARGB1555 = 18,
|
||||||
|
GLTF_ARGB0555 = 19,
|
||||||
|
GLTF_RGB565 = 20,
|
||||||
|
GLTF_A2RGB10 = 21,
|
||||||
|
GLTF_RGB16 = 22,
|
||||||
|
GLTF_L8 = 23,
|
||||||
|
GLTF_A8 = 24,
|
||||||
|
GLTF_A8L8 = 25,
|
||||||
|
GLTF_DXT1 = 26,
|
||||||
|
GLTF_DXT3 = 27,
|
||||||
|
GLTF_DXT5 = 28,
|
||||||
|
GLTF_NUM_TEXTURE_FORMATS = 29
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GLVertexType {
|
||||||
|
GLVT_INVALID = 0,
|
||||||
|
GLVT_FLOAT1 = 1,
|
||||||
|
GLVT_FLOAT2 = 2,
|
||||||
|
GLVT_FLOAT3 = 3,
|
||||||
|
GLVT_FLOAT4 = 4,
|
||||||
|
GLVT_UBYTE4 = 5,
|
||||||
|
GLVT_UBYTE4N = 6,
|
||||||
|
GLVT_SHORT = 7,
|
||||||
|
GLVT_SHORT2 = 8,
|
||||||
|
GLVT_SHORT4 = 9,
|
||||||
|
GLVT_SHORT2N = 10,
|
||||||
|
GLVT_SHORT4N = 11,
|
||||||
|
GLVT_USHORT2N = 12,
|
||||||
|
GLVT_USHORT4N = 13,
|
||||||
|
GLVT_NUM_VERTEX_TYPES = 14
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GLBufferType {
|
||||||
|
eGLBT_PIXEL_UNPACK = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLAttachPoint {
|
||||||
|
GLFramebuffer* framebuffer;
|
||||||
|
int32_t point; // TODO GLenum?
|
||||||
|
int32_t zOffset; // TODO check type
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLBox {
|
||||||
|
int32_t left;
|
||||||
|
int32_t top;
|
||||||
|
int32_t front;
|
||||||
|
int32_t width;
|
||||||
|
int32_t height;
|
||||||
|
int32_t depth;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLColor4f {
|
||||||
|
float r;
|
||||||
|
float g;
|
||||||
|
float b;
|
||||||
|
float a;
|
||||||
|
|
||||||
|
static GLColor4f ZERO;
|
||||||
|
static GLColor4f WHITE;
|
||||||
|
static GLColor4f BLACK;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLDirtyRange {
|
||||||
|
uint16_t start;
|
||||||
|
uint16_t end;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLfloat4 {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
float w;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLRect {
|
||||||
|
int32_t left;
|
||||||
|
int32_t top;
|
||||||
|
int32_t width;
|
||||||
|
int32_t height;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLTransform {
|
||||||
|
bool isDirty;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
float a0;
|
||||||
|
float a1;
|
||||||
|
float a2;
|
||||||
|
float a3;
|
||||||
|
float b0;
|
||||||
|
float b1;
|
||||||
|
float b2;
|
||||||
|
float b3;
|
||||||
|
float c0;
|
||||||
|
float c1;
|
||||||
|
float c2;
|
||||||
|
float c3;
|
||||||
|
float d0;
|
||||||
|
float d1;
|
||||||
|
float d2;
|
||||||
|
float d3;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
float rows[4][4];
|
||||||
|
};
|
||||||
|
|
||||||
|
float m[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
bool isIdentity;
|
||||||
|
|
||||||
|
bool operator==(const float m[16]) const;
|
||||||
|
bool operator!=(const float m[16]) const;
|
||||||
|
void Set(const float m[16]);
|
||||||
|
void SetIdentity();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLStates {
|
||||||
|
struct Depth {
|
||||||
|
bool testEnable;
|
||||||
|
int32_t compareFunc;
|
||||||
|
bool writeMask;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Stencil {
|
||||||
|
struct StencilFace {
|
||||||
|
int32_t compareFunc;
|
||||||
|
int32_t opFail;
|
||||||
|
int32_t opZFail;
|
||||||
|
int32_t opZPass;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool testEnable;
|
||||||
|
int32_t ref;
|
||||||
|
uint32_t mask;
|
||||||
|
uint32_t writeMask;
|
||||||
|
bool useTwoSidedStencil;
|
||||||
|
StencilFace front;
|
||||||
|
StencilFace back;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Rasterizer {
|
||||||
|
struct ClipPlane {
|
||||||
|
double plane[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
int32_t cullMode;
|
||||||
|
int32_t cullFaceMode;
|
||||||
|
int32_t fillMode;
|
||||||
|
float constantDepthBias;
|
||||||
|
float slopeScaledDepthBias;
|
||||||
|
GLRect viewport;
|
||||||
|
double zNear;
|
||||||
|
double zFar;
|
||||||
|
bool scissorEnable;
|
||||||
|
GLRect scissor;
|
||||||
|
uint32_t clipPlaneMask;
|
||||||
|
ClipPlane clipPlanes[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Blend {
|
||||||
|
struct ColorMask {
|
||||||
|
bool red;
|
||||||
|
bool green;
|
||||||
|
bool blue;
|
||||||
|
bool alpha;
|
||||||
|
};
|
||||||
|
|
||||||
|
ColorMask colorMask[4];
|
||||||
|
bool alphaBlend;
|
||||||
|
int32_t srcBlendFactor;
|
||||||
|
int32_t destBlendFactor;
|
||||||
|
int32_t blendOp;
|
||||||
|
GLColor4f blendColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Clear {
|
||||||
|
GLColor4f clearColor;
|
||||||
|
double clearDepth;
|
||||||
|
int32_t clearStencil;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FixedFunc {
|
||||||
|
struct TexOp {
|
||||||
|
int32_t texturing;
|
||||||
|
GLColor4f constant;
|
||||||
|
int32_t colorOp;
|
||||||
|
float colorScale;
|
||||||
|
int32_t colorArg0;
|
||||||
|
int32_t colorArg1;
|
||||||
|
int32_t colorArg2;
|
||||||
|
int32_t alphaOp;
|
||||||
|
float alphaScale;
|
||||||
|
int32_t alphaArg0;
|
||||||
|
int32_t alphaArg1;
|
||||||
|
int32_t alphaArg2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Light {
|
||||||
|
bool enable;
|
||||||
|
GLfloat4 position;
|
||||||
|
GLTransform view;
|
||||||
|
float constantAttenuation;
|
||||||
|
float linearAttenuation;
|
||||||
|
float quadraticAttenuation;
|
||||||
|
GLColor4f ambient;
|
||||||
|
GLColor4f diffuse;
|
||||||
|
GLColor4f specular;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Material {
|
||||||
|
bool colorTracking;
|
||||||
|
int32_t materialSource;
|
||||||
|
GLColor4f ambient;
|
||||||
|
GLColor4f diffuse;
|
||||||
|
GLColor4f specular;
|
||||||
|
float shininess;
|
||||||
|
GLColor4f emission;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Lighting {
|
||||||
|
bool enable;
|
||||||
|
GLColor4f sceneAmbient;
|
||||||
|
Light lights[8];
|
||||||
|
Material material;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Transforms {
|
||||||
|
int32_t matrixMode;
|
||||||
|
int32_t modelviewStatus;
|
||||||
|
GLTransform modelView;
|
||||||
|
GLTransform world;
|
||||||
|
GLTransform view;
|
||||||
|
GLTransform projection;
|
||||||
|
GLTransform texture[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TexGen {
|
||||||
|
int32_t S;
|
||||||
|
int32_t T;
|
||||||
|
int32_t R;
|
||||||
|
int32_t Q;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PointSprite {
|
||||||
|
bool enable;
|
||||||
|
float size;
|
||||||
|
float attenuation[3];
|
||||||
|
float min;
|
||||||
|
float max;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool fogEnable;
|
||||||
|
GLColor4f fogColor;
|
||||||
|
int32_t fogMode;
|
||||||
|
float fogStart;
|
||||||
|
float fogEnd;
|
||||||
|
float fogDensity;
|
||||||
|
bool alphaTestEnable;
|
||||||
|
int32_t alphaTestFunc;
|
||||||
|
float alphaTestRef;
|
||||||
|
TexOp texOp[8];
|
||||||
|
Lighting lighting;
|
||||||
|
Transforms transforms;
|
||||||
|
int32_t texCoordIndex[8];
|
||||||
|
TexGen texGen[8];
|
||||||
|
PointSprite pointSprite;
|
||||||
|
bool normalizeNormal;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Sampler {
|
||||||
|
float mipmapBias;
|
||||||
|
int32_t addressModeS;
|
||||||
|
int32_t addressModeT;
|
||||||
|
int32_t addressModeR;
|
||||||
|
int32_t magFilterMode;
|
||||||
|
int32_t minFilterMode;
|
||||||
|
float maxAnisotropy;
|
||||||
|
GLColor4f borderColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Shader {
|
||||||
|
bool vertexShaderEnable;
|
||||||
|
GLfloat4 vertexShaderConst[256];
|
||||||
|
bool pixelShaderEnable;
|
||||||
|
GLfloat4 pixelShaderConst[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Binding {
|
||||||
|
uint32_t currentActiveTexture;
|
||||||
|
uint32_t texture[4][16];
|
||||||
|
uint32_t framebuffer;
|
||||||
|
uint32_t renderbuffer;
|
||||||
|
uint32_t vertexProgram;
|
||||||
|
uint32_t pixelProgram;
|
||||||
|
uint32_t glslProgram;
|
||||||
|
uint32_t vertexArrayObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Misc {
|
||||||
|
bool unpackClientStorage;
|
||||||
|
int32_t drawBuffers[4];
|
||||||
|
int32_t readBuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertexArrayObject {
|
||||||
|
struct VertexAttrib {
|
||||||
|
bool enable = 0;
|
||||||
|
uint32_t size = 4;
|
||||||
|
int32_t type = GL_FLOAT;
|
||||||
|
bool normalized = 0;
|
||||||
|
uint32_t stride = 0;
|
||||||
|
void* offset = nullptr;
|
||||||
|
GLBuffer* buffer = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t buffers[4] = {};
|
||||||
|
VertexAttrib vertexAttribs[16];
|
||||||
|
VertexAttrib position;
|
||||||
|
VertexAttrib normal;
|
||||||
|
VertexAttrib color0;
|
||||||
|
VertexAttrib color1;
|
||||||
|
VertexAttrib texCoord[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
Depth depth;
|
||||||
|
Stencil stencil;
|
||||||
|
Rasterizer rasterizer;
|
||||||
|
Blend blend;
|
||||||
|
Clear clear;
|
||||||
|
FixedFunc fixedFunc;
|
||||||
|
Sampler samplers[16];
|
||||||
|
Shader shader;
|
||||||
|
Binding binding;
|
||||||
|
Misc misc;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLVertexAttrib {
|
||||||
|
uint32_t stream;
|
||||||
|
int32_t slot;
|
||||||
|
int32_t type;
|
||||||
|
uint32_t offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
22
src/gx/glsdl/GLUtil.cpp
Normal file
22
src/gx/glsdl/GLUtil.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include "gx/glsdl/GLUtil.hpp"
|
||||||
|
#include <bc/Debug.hpp>
|
||||||
|
|
||||||
|
uint32_t GLSDLTextureTypeToIndex(GLEnum textureType) {
|
||||||
|
uint32_t index;
|
||||||
|
|
||||||
|
if (textureType == GL_TEXTURE_2D) {
|
||||||
|
index = 0;
|
||||||
|
} else if (textureType == GL_TEXTURE_3D) {
|
||||||
|
index = 1;
|
||||||
|
} else if (textureType == GL_TEXTURE_CUBE_MAP) {
|
||||||
|
index = 2;
|
||||||
|
} else if (textureType == GL_TEXTURE_RECTANGLE) {
|
||||||
|
index = 3;
|
||||||
|
} else {
|
||||||
|
index = 5;
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
9
src/gx/glsdl/GLUtil.hpp
Normal file
9
src/gx/glsdl/GLUtil.hpp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_UTIL_HPP
|
||||||
|
#define GX_GL_SDL_GL_UTIL_HPP
|
||||||
|
|
||||||
|
#include "gx/glsdl/GL.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
uint32_t GLSDLTextureTypeToIndex(GLEnum textureType);
|
||||||
|
|
||||||
|
#endif
|
||||||
316
src/gx/glsdl/GLVertexArray.cpp
Normal file
316
src/gx/glsdl/GLVertexArray.cpp
Normal file
@ -0,0 +1,316 @@
|
|||||||
|
#include "gx/glsdl/GLVertexArray.hpp"
|
||||||
|
#include "gx/glsdl/GLSDLDevice.hpp"
|
||||||
|
#include <bc/Debug.hpp>
|
||||||
|
|
||||||
|
bool GLVertexArray::s_VertexArrayEnable = false;
|
||||||
|
|
||||||
|
GLVertexArray::GLVertexArray(bool a2) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLVertexArray::FindVertexArray(GLSDLDevice* a1, GLVertexArray& a2) {
|
||||||
|
if (GLVertexArray::s_VertexArrayEnable) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
a2.ApplyVertexFormat(a1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLVertexArray::ApplyGLStates(GLStates::VertexArrayObject& vao) {
|
||||||
|
GLSDLDevice* device = GLSDLDevice::Get();
|
||||||
|
|
||||||
|
device->BindVertexArray(this);
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < kMAX_VERTEX_ATTRIBS; i++) {
|
||||||
|
auto& attrib = vao.vertexAttribs[i];
|
||||||
|
|
||||||
|
if (attrib.enable) {
|
||||||
|
glBindBuffer(attrib.buffer->m_Type, attrib.buffer->m_BufferID);
|
||||||
|
|
||||||
|
glVertexAttribPointerARB(
|
||||||
|
i,
|
||||||
|
attrib.size,
|
||||||
|
attrib.type,
|
||||||
|
attrib.normalized,
|
||||||
|
attrib.stride,
|
||||||
|
reinterpret_cast<void*>(attrib.offset)
|
||||||
|
);
|
||||||
|
|
||||||
|
glEnableVertexAttribArrayARB(i);
|
||||||
|
} else {
|
||||||
|
glDisableVertexAttribArrayARB(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vao.position.enable) {
|
||||||
|
glBindBuffer(vao.position.buffer->m_Type, vao.position.buffer->m_BufferID);
|
||||||
|
glVertexPointer(vao.position.size, vao.position.type, vao.position.stride, vao.position.offset);
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
} else {
|
||||||
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vao.normal.enable) {
|
||||||
|
glBindBuffer(vao.normal.buffer->m_Type, vao.normal.buffer->m_BufferID);
|
||||||
|
glNormalPointer(vao.normal.type, vao.normal.stride, vao.normal.offset);
|
||||||
|
glEnableClientState(GL_NORMAL_ARRAY);
|
||||||
|
} else {
|
||||||
|
glDisableClientState(GL_NORMAL_ARRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vao.color0.enable) {
|
||||||
|
glBindBuffer(vao.color0.buffer->m_Type, vao.color0.buffer->m_BufferID);
|
||||||
|
glColorPointer(vao.color0.size, vao.color0.type, vao.color0.stride, vao.color0.offset);
|
||||||
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
|
} else {
|
||||||
|
glDisableClientState(GL_COLOR_ARRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vao.color1.enable) {
|
||||||
|
glBindBuffer(vao.color1.buffer->m_Type, vao.color1.buffer->m_BufferID);
|
||||||
|
glColorPointer(vao.color1.size, vao.color1.type, vao.color1.stride, vao.color1.offset);
|
||||||
|
glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
|
||||||
|
} else {
|
||||||
|
glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < 8; i++) {
|
||||||
|
glClientActiveTextureARB(GL_TEXTURE0 + i);
|
||||||
|
|
||||||
|
if (vao.texCoord[i].enable) {
|
||||||
|
glBindBuffer(vao.texCoord[i].buffer->m_Type, vao.texCoord[0].buffer->m_BufferID);
|
||||||
|
glTexCoordPointer(vao.texCoord[i].size, vao.texCoord[i].type, vao.texCoord[i].stride, vao.texCoord[i].offset);
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
} else {
|
||||||
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vao.buffers[0]);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vao.buffers[1]);
|
||||||
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, vao.buffers[2]);
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, vao.buffers[3]);
|
||||||
|
|
||||||
|
this->m_GLStates = vao;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLVertexArray::ApplyVertexFormat(GLSDLDevice* device) {
|
||||||
|
if (GLVertexArray::s_VertexArrayEnable) {
|
||||||
|
device->BindVertexArray(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto indexBuffer = this->m_Properties.m_IndexBuffer;
|
||||||
|
uint32_t indexBufferID = indexBuffer ? indexBuffer->m_BufferID : 0;
|
||||||
|
|
||||||
|
if (this->m_GLStates.buffers[1] != indexBufferID) {
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
|
||||||
|
this->m_GLStates.buffers[1] = indexBufferID;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT(this->GetProperties().m_VertexBufferFormat != nullptr);
|
||||||
|
|
||||||
|
auto& properties = this->GetProperties();
|
||||||
|
bool attribEnable[16] = {};
|
||||||
|
|
||||||
|
bool useVertexShader = device->GetShader(GLShader::eVertexShader) != nullptr;
|
||||||
|
|
||||||
|
for (int32_t index = 0; index < this->GetProperties().m_VertexBufferFormat->m_Size; index++) {
|
||||||
|
BLIZZARD_ASSERT(index < kMAX_VERTEX_ATTRIBS);
|
||||||
|
|
||||||
|
auto& attrib = this->GetProperties().m_VertexBufferFormat->m_Attribs[index];
|
||||||
|
|
||||||
|
BLIZZARD_ASSERT(attrib.type != GLVT_INVALID);
|
||||||
|
BLIZZARD_ASSERT(attrib.type < GLVT_NUM_VERTEX_TYPES);
|
||||||
|
|
||||||
|
auto vertexBuffer = this->GetProperties().m_VertexBuffer[attrib.stream];
|
||||||
|
|
||||||
|
if (useVertexShader || static_cast<uint32_t>(attrib.slot - 1) > 1) {
|
||||||
|
if (this->m_GLStates.buffers[0] != vertexBuffer->m_BufferID) {
|
||||||
|
glBindBuffer(vertexBuffer->m_Type, vertexBuffer->m_BufferID);
|
||||||
|
this->m_GLStates.buffers[0] = vertexBuffer->m_BufferID;
|
||||||
|
}
|
||||||
|
|
||||||
|
attribEnable[attrib.slot] = 1;
|
||||||
|
|
||||||
|
int32_t stride = properties.m_VertexBufferStride[attrib.stream];
|
||||||
|
int32_t offset = attrib.offset
|
||||||
|
+ properties.m_VertexBufferOffset[attrib.stream]
|
||||||
|
+ properties.m_VertexBase * stride;
|
||||||
|
|
||||||
|
if (useVertexShader) {
|
||||||
|
glVertexAttribPointerARB(
|
||||||
|
attrib.slot,
|
||||||
|
k_VertexTypeInfo[attrib.type].m_Size,
|
||||||
|
k_VertexTypeInfo[attrib.type].m_Type,
|
||||||
|
k_VertexTypeInfo[attrib.type].m_Normalized,
|
||||||
|
stride,
|
||||||
|
reinterpret_cast<void*>(offset)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
switch (attrib.slot) {
|
||||||
|
case 0: {
|
||||||
|
glVertexPointer(
|
||||||
|
k_VertexTypeInfo[attrib.type].m_Size,
|
||||||
|
k_VertexTypeInfo[attrib.type].m_Type,
|
||||||
|
stride,
|
||||||
|
reinterpret_cast<void*>(offset)
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3: {
|
||||||
|
glNormalPointer(
|
||||||
|
k_VertexTypeInfo[attrib.type].m_Type,
|
||||||
|
stride,
|
||||||
|
reinterpret_cast<void*>(offset)
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 4: {
|
||||||
|
glColorPointer(
|
||||||
|
k_VertexTypeInfo[attrib.type].m_Size,
|
||||||
|
k_VertexTypeInfo[attrib.type].m_Type,
|
||||||
|
stride,
|
||||||
|
reinterpret_cast<void*>(offset)
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 5: {
|
||||||
|
glSecondaryColorPointer(
|
||||||
|
k_VertexTypeInfo[attrib.type].m_Size,
|
||||||
|
k_VertexTypeInfo[attrib.type].m_Type,
|
||||||
|
stride,
|
||||||
|
reinterpret_cast<void*>(offset)
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
case 7:
|
||||||
|
case 8:
|
||||||
|
case 9:
|
||||||
|
case 10:
|
||||||
|
case 11:
|
||||||
|
case 12:
|
||||||
|
case 13: {
|
||||||
|
auto tmu = attrib.slot - 6;
|
||||||
|
auto texCoordIndex = device->m_States.fixedFunc.texCoordIndex[tmu];
|
||||||
|
glClientActiveTextureARB(GL_TEXTURE0 + texCoordIndex);
|
||||||
|
glTexCoordPointer(
|
||||||
|
k_VertexTypeInfo[attrib.type].m_Size,
|
||||||
|
k_VertexTypeInfo[attrib.type].m_Type,
|
||||||
|
stride,
|
||||||
|
reinterpret_cast<void*>(offset)
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int32_t s = 0; s < 16; s++) {
|
||||||
|
// Shader
|
||||||
|
if (useVertexShader) {
|
||||||
|
auto prevAttribEnable = &this->m_GLStates.vertexAttribs[s].enable;
|
||||||
|
|
||||||
|
if (*prevAttribEnable != attribEnable[s]) {
|
||||||
|
if (attribEnable[s]) {
|
||||||
|
glEnableVertexAttribArrayARB(s);
|
||||||
|
} else {
|
||||||
|
glDisableVertexAttribArrayARB(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*prevAttribEnable = attribEnable[s];
|
||||||
|
|
||||||
|
// FFP
|
||||||
|
} else {
|
||||||
|
bool* prevAttribEnable = nullptr;
|
||||||
|
GLenum glArray = GL_NONE;
|
||||||
|
|
||||||
|
switch (s) {
|
||||||
|
case 0: {
|
||||||
|
prevAttribEnable = &this->m_GLStates.position.enable;
|
||||||
|
glArray = GL_VERTEX_ARRAY;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3: {
|
||||||
|
prevAttribEnable = &this->m_GLStates.normal.enable;
|
||||||
|
glArray = GL_NORMAL_ARRAY;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 4: {
|
||||||
|
prevAttribEnable = &this->m_GLStates.color0.enable;
|
||||||
|
glArray = GL_COLOR_ARRAY;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 5: {
|
||||||
|
prevAttribEnable = &this->m_GLStates.color1.enable;
|
||||||
|
glArray = GL_SECONDARY_COLOR_ARRAY;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
case 7:
|
||||||
|
case 8:
|
||||||
|
case 9:
|
||||||
|
case 10:
|
||||||
|
case 11:
|
||||||
|
case 12:
|
||||||
|
case 13: {
|
||||||
|
auto tmu = s - 6;
|
||||||
|
auto texCoordIndex = device->m_States.fixedFunc.texCoordIndex[tmu];
|
||||||
|
|
||||||
|
prevAttribEnable = &this->m_GLStates.texCoord[texCoordIndex].enable;
|
||||||
|
glArray = GL_TEXTURE_COORD_ARRAY;
|
||||||
|
|
||||||
|
glClientActiveTextureARB(GL_TEXTURE0 + texCoordIndex);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevAttribEnable) {
|
||||||
|
if (*prevAttribEnable != attribEnable[s]) {
|
||||||
|
if (attribEnable[s]) {
|
||||||
|
glEnableClientState(glArray);
|
||||||
|
} else {
|
||||||
|
glDisableClientState(glArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*prevAttribEnable = attribEnable[s];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!useVertexShader) {
|
||||||
|
// TODO device->SetColorMaterial(this->m_GLStates.color0.enable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLVertexArray::Properties& GLVertexArray::GetProperties() {
|
||||||
|
return this->m_Properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLVertexArray::ReleaseObject() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
46
src/gx/glsdl/GLVertexArray.hpp
Normal file
46
src/gx/glsdl/GLVertexArray.hpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_VERTEX_ARRAY_HPP
|
||||||
|
#define GX_GL_SDL_GL_VERTEX_ARRAY_HPP
|
||||||
|
|
||||||
|
#include "gx/glsdl/GLBuffer.hpp"
|
||||||
|
#include "gx/glsdl/GLObject.hpp"
|
||||||
|
#include "gx/glsdl/GLVertexFormat.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
class GLSDLDevice;
|
||||||
|
|
||||||
|
class GLVertexArray : public GLObject {
|
||||||
|
public:
|
||||||
|
// Types
|
||||||
|
struct Properties {
|
||||||
|
GLVertexFormat* m_VertexBufferFormat = nullptr;
|
||||||
|
GLBuffer* m_IndexBuffer = nullptr;
|
||||||
|
GLBuffer* m_PixelPackBuffer = nullptr;
|
||||||
|
GLBuffer* m_PixelUnpackBuffer = nullptr;
|
||||||
|
GLBuffer* m_VertexBuffer[4] = {};
|
||||||
|
uint32_t m_VertexBase = 0;
|
||||||
|
uint32_t m_VertexBufferOffset[4] = {};
|
||||||
|
uint32_t m_VertexBufferStride[4] = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Static variables
|
||||||
|
static bool s_VertexArrayEnable;
|
||||||
|
|
||||||
|
// Static functions
|
||||||
|
static void FindVertexArray(GLSDLDevice*, GLVertexArray&);
|
||||||
|
|
||||||
|
// Member variables
|
||||||
|
Properties m_Properties;
|
||||||
|
GLStates::VertexArrayObject m_GLStates;
|
||||||
|
uint32_t m_VertexArrayID = 0;
|
||||||
|
|
||||||
|
// Virtual member functions
|
||||||
|
virtual void ReleaseObject();
|
||||||
|
|
||||||
|
// Member functions
|
||||||
|
GLVertexArray(bool);
|
||||||
|
void ApplyGLStates(GLStates::VertexArrayObject&);
|
||||||
|
void ApplyVertexFormat(GLSDLDevice*);
|
||||||
|
Properties& GetProperties(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
13
src/gx/glsdl/GLVertexFormat.hpp
Normal file
13
src/gx/glsdl/GLVertexFormat.hpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_VERTEX_FORMAT_HPP
|
||||||
|
#define GX_GL_SDL_GL_VERTEX_FORMAT_HPP
|
||||||
|
|
||||||
|
#include "gx/glsdl/GLTypes.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
class GLVertexFormat {
|
||||||
|
public:
|
||||||
|
uint32_t m_Size;
|
||||||
|
GLVertexAttrib m_Attribs[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
17
src/gx/glsdl/GLVertexShader.cpp
Normal file
17
src/gx/glsdl/GLVertexShader.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include "gx/glsdl/GLVertexShader.hpp"
|
||||||
|
#include "gx/glsdl/GL.hpp"
|
||||||
|
|
||||||
|
GLVertexShader* GLVertexShader::Create() {
|
||||||
|
// TODO
|
||||||
|
// GLPool stuff
|
||||||
|
|
||||||
|
GLVertexShader* shader = new GLVertexShader();
|
||||||
|
|
||||||
|
shader->m_ShaderID = 0;
|
||||||
|
shader->m_RefCount = 1;
|
||||||
|
shader->m_ShaderType = eVertexShader;
|
||||||
|
shader->m_UsingGLSL = 0;
|
||||||
|
shader->var5 = GL_VERTEX_PROGRAM_ARB;
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
12
src/gx/glsdl/GLVertexShader.hpp
Normal file
12
src/gx/glsdl/GLVertexShader.hpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef GX_GL_SDL_GL_VERTEX_SHADER_HPP
|
||||||
|
#define GX_GL_SDL_GL_VERTEX_SHADER_HPP
|
||||||
|
|
||||||
|
#include "gx/glsdl/GLShader.hpp"
|
||||||
|
|
||||||
|
class GLVertexShader : public GLShader {
|
||||||
|
public:
|
||||||
|
// Static functions
|
||||||
|
static GLVertexShader* Create(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -26,6 +26,7 @@ target_link_libraries(util
|
|||||||
freetype-2.0
|
freetype-2.0
|
||||||
lua-5.1
|
lua-5.1
|
||||||
stormlib-9
|
stormlib-9
|
||||||
|
bc
|
||||||
common
|
common
|
||||||
storm
|
storm
|
||||||
tempest
|
tempest
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user