mirror of
				https://github.com/thunderbrewhq/thunderbrew
				synced 2025-10-30 07:46:03 +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 | ||||
| 	url = https://github.com/whoahq/common.git | ||||
| [submodule "lib/squall"] | ||||
| 	path = lib/squall | ||||
| 	url = https://github.com/whoahq/squall.git | ||||
| [submodule "lib/typhoon"] | ||||
| 	url = https://github.com/thunderbrewhq/common.git | ||||
| [submodule "lib/squall"] | ||||
| 	path = lib/squall | ||||
| 	url = https://github.com/thunderbrewhq/squall.git | ||||
| [submodule "lib/typhoon"] | ||||
| 	path = lib/typhoon | ||||
| 	url = https://github.com/whoahq/typhoon.git | ||||
| [submodule "lib/system"] | ||||
| 	path = lib/system | ||||
| 	url = https://github.com/whoahq/system.git | ||||
| [submodule "lib/bc"] | ||||
| 	url = https://github.com/thunderbrewhq/typhoon.git | ||||
| [submodule "lib/system"] | ||||
| 	path = lib/system | ||||
| 	url = https://github.com/thunderbrewhq/system.git | ||||
| [submodule "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 "bc/os/CommandLine.hpp" | ||||
| 
 | ||||
| int main(int argc, char* argv[]) { | ||||
|     // TODO
 | ||||
| 
 | ||||
|     OsSetCommandLine(argc, argv); | ||||
| 
 | ||||
|     CommonMain(); | ||||
| 
 | ||||
|     // TODO
 | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| #include "app/mac/WoWApplication.h" | ||||
| #include "app/mac/MacClient.h" | ||||
| #include "client/Client.hpp" | ||||
| #include "bc/os/CommandLine.hpp" | ||||
| #include <AppKit/AppKit.h> | ||||
| #include <Foundation/Foundation.h> | ||||
| 
 | ||||
| @ -8,6 +9,8 @@ int32_t main(int32_t argc, char* argv[]) { | ||||
|     // TODO | ||||
|     // MacClient::SetupCommandLine(argc, argv, v10); | ||||
| 
 | ||||
|     OsSetCommandLine(argc, argv); | ||||
| 
 | ||||
|     if (MacClient::IsUsingGLLayer()) { | ||||
|         // TODO | ||||
|         // GxSetRequestedApi(3); | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| #include "client/Client.hpp" | ||||
| #include "async/AsyncFile.hpp" | ||||
| #include "client/ClientServices.hpp" | ||||
| #include "client/CmdLine.hpp" | ||||
| #include "console/CVar.hpp" | ||||
| #include "console/Client.hpp" | ||||
| #include "console/Device.hpp" | ||||
| @ -18,6 +19,7 @@ | ||||
| #include <bc/Debug.hpp> | ||||
| #include <common/Prop.hpp> | ||||
| #include <storm/Error.hpp> | ||||
| #include <bc/os/Path.hpp> | ||||
| 
 | ||||
| CVar* Client::g_accountListVar; | ||||
| HEVENTCONTEXT Client::g_clientEventContext; | ||||
| @ -136,12 +138,28 @@ int32_t InitializeEngineCallback(const void* a1, void* a2) { | ||||
|     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() { | ||||
|     // TODO
 | ||||
| 
 | ||||
|     // SCmdRegisterArgList(&ProcessCommandLine(void)::s_wowArgList, 17u);
 | ||||
| 
 | ||||
|     // CmdLineProcess();
 | ||||
|     ProcessCommandLine(); | ||||
| 
 | ||||
|     // sub_403600("WoW.mfil");
 | ||||
| 
 | ||||
| @ -159,10 +177,16 @@ int32_t InitializeGlobal() { | ||||
| 
 | ||||
|     OpenArchives(); | ||||
| 
 | ||||
|     SetPaths(); | ||||
| 
 | ||||
|     ConsoleInitializeClientCommand(); | ||||
| 
 | ||||
|     ConsoleInitializeClientCVar("Config.wtf"); | ||||
| 
 | ||||
|     // TODO
 | ||||
|     // replace enUS with detected locale
 | ||||
|     ClientServices::InitLoginServerCVars(1, "enUS"); | ||||
| 
 | ||||
|     // sub_7663F0();
 | ||||
| 
 | ||||
|     // v18 = 0;
 | ||||
|  | ||||
| @ -3,7 +3,9 @@ | ||||
| #include "glue/CGlueMgr.hpp" | ||||
| #include "net/Connection.hpp" | ||||
| #include "net/Login.hpp" | ||||
| #include "console/Client.hpp" | ||||
| #include "console/CVar.hpp" | ||||
| #include "console/Types.hpp" | ||||
| #include <storm/Memory.hpp> | ||||
| #include <storm/String.hpp> | ||||
| #include <new> | ||||
| @ -16,10 +18,16 @@ ClientConnection* ClientServices::s_currentConnection; | ||||
| ClientServices* ClientServices::s_instance; | ||||
| Login* ClientServices::s_loginObj; | ||||
| bool ClientServices::s_newLogin; | ||||
| CVar* ClientServices::s_realmNameVar; | ||||
| REALM_INFO ClientServices::s_selectRealmInfo; | ||||
| 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() { | ||||
|     if (!ClientServices::s_selectRealmInfoValid && !ClientServices::SetSelectedRealmInfo(0)) { | ||||
|         ClientServices::Connection()->Complete(0, 39); | ||||
| @ -138,9 +146,19 @@ void ClientServices::Logon(const char* accountName, const char* 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
 | ||||
| 
 | ||||
|     ClientServices::s_loginObj->Logon(nullptr, nullptr); | ||||
|     ClientServices::s_loginObj->Logon(realmList, portal); | ||||
| } | ||||
| 
 | ||||
| void ClientServices::SelectRealm(const char* realmName) { | ||||
| @ -229,3 +247,107 @@ void ClientServices::RealmEnumCallback(uint32_t a2) { | ||||
| 
 | ||||
|     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 Login* s_loginObj; | ||||
|         static bool s_newLogin; | ||||
|         static CVar* s_realmNameVar; | ||||
|         static REALM_INFO s_selectRealmInfo; | ||||
|         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 void ConnectToSelectedServer(); | ||||
|         static ClientConnection* Connection(); | ||||
| @ -34,6 +42,9 @@ class ClientServices : public LoginResponse { | ||||
|         static void SelectRealm(const char* realmName); | ||||
|         static void SetAccountName(const char* accountName); | ||||
|         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 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 | ||||
|     "*.cpp" | ||||
|     "command/*/*.cpp" | ||||
| ) | ||||
| 
 | ||||
| add_library(console STATIC | ||||
|  | ||||
| @ -1,6 +1,13 @@ | ||||
| #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> | ||||
| 
 | ||||
| const char* s_filename = nullptr; | ||||
| bool CVar::m_needsSave; | ||||
| 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; | ||||
|         } | ||||
| 
 | ||||
|         // TODO
 | ||||
|         // ConsoleCommandRegister(var->m_key.GetString(), &CvarCommandHandler, category, help);
 | ||||
|         ConsoleCommandRegister(name, CvarCommandHandler, CATEGORY(category), help); | ||||
|     } | ||||
| 
 | ||||
|     return var; | ||||
| @ -147,6 +153,26 @@ bool CVar::Set(const char* value, bool setValue, bool setReset, bool setDefault, | ||||
|     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() { | ||||
|     if (!(this->m_flags & 0x2)) { | ||||
|         return 0; | ||||
| @ -161,3 +187,221 @@ int32_t CVar::Update() { | ||||
| 
 | ||||
|     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 <common/String.hpp> | ||||
| #include <storm/Hash.hpp> | ||||
| #include <bc/os/File.hpp> | ||||
| 
 | ||||
| class CVar : public TSHashObject<CVar, HASHKEY_STRI> { | ||||
|     public: | ||||
| @ -14,7 +15,9 @@ class CVar : public TSHashObject<CVar, HASHKEY_STRI> { | ||||
|         // Static functions
 | ||||
|         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 void  Initialize(const char* filename); | ||||
|         static int32_t Load(const char* filename); | ||||
|         static int32_t Load(HOSFILE fileHandle); | ||||
|         // Member variables
 | ||||
|         uint32_t m_category = 0; | ||||
|         uint32_t m_flags = 0; | ||||
| @ -35,7 +38,16 @@ class CVar : public TSHashObject<CVar, HASHKEY_STRI> { | ||||
|         const char* GetString(void); | ||||
|         void InternalSet(const char*, bool, bool, bool, bool); | ||||
|         bool Set(const char*, bool, bool, bool, bool); | ||||
|         bool Reset(); | ||||
|         bool Default(); | ||||
|         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 | ||||
|  | ||||
| @ -1,9 +1,17 @@ | ||||
| #include "console/Client.hpp" | ||||
| #include "console/Command.hpp" | ||||
| #include "console/CVar.hpp" | ||||
| 
 | ||||
| void ConsoleInitializeClientCommand() { | ||||
|     // TODO
 | ||||
|     ConsoleCommandInitialize(); | ||||
|     ConsoleInitializeCommonCommand(); | ||||
|     ConsoleInitializeDebugCommand(); | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
| #define CONSOLE_CLIENT_HPP | ||||
| 
 | ||||
| #include <cstdint> | ||||
| 
 | ||||
| void ConsoleInitializeClientCommand(); | ||||
| 
 | ||||
| void ConsoleInitializeClientCVar(const char* a1); | ||||
| 
 | ||||
| int32_t ConsoleLoadClientCVar(const char* a1); | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
| @ -1,5 +1,11 @@ | ||||
| #include "console/Command.hpp" | ||||
| #include "console/Line.hpp" | ||||
| 
 | ||||
| #include <storm/Error.hpp> | ||||
| #include <storm/Unicode.hpp> | ||||
| 
 | ||||
| #include <cctype> | ||||
| #include <algorithm> | ||||
| 
 | ||||
| int32_t ValidateFileName(const char* filename) { | ||||
|     if (SStrStr(filename, "..") || SStrStr(filename, "\\")) { | ||||
| @ -20,8 +26,49 @@ int32_t ValidateFileName(const char* filename) { | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| 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() { | ||||
|     g_consoleCommandHash.Clear(); | ||||
| @ -29,33 +76,33 @@ void ConsoleCommandDestroy() { | ||||
| 
 | ||||
| char* ConsoleCommandHistory(uint32_t 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() { | ||||
|     return HISTORY_DEPTH; | ||||
|     return CONSOLE_HISTORY_DEPTH; | ||||
| } | ||||
| 
 | ||||
| void ConsoleCommandInitialize() { | ||||
|     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) { | ||||
| int32_t ConsoleCommandRegister(const char* command, COMMANDHANDLER handler, CATEGORY category, const char* helpText) { | ||||
|     STORM_ASSERT(command); | ||||
|     STORM_ASSERT(handler); | ||||
| 
 | ||||
|     if (SStrLen(command) > (MAX_CMD_LENGTH - 1) || g_consoleCommandHash.Ptr(command)) { | ||||
|         // The command name exceeds MAX_CMD_LENGTH, minus the null terminator
 | ||||
|     if (SStrLen(command) > (CONSOLE_MAX_CMD_LENGTH - 1) || g_consoleCommandHash.Ptr(command)) { | ||||
|         // The command name exceeds CONSOLE_MAX_CMD_LENGTH, minus the null terminator
 | ||||
|         // or it has already been registered
 | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     // Register the new command
 | ||||
|     auto commandPtr = g_consoleCommandHash.New(command, 0, 0); | ||||
|     commandPtr->command = command; | ||||
|     commandPtr->handler = handler; | ||||
|     commandPtr->helpText = helpText; | ||||
|     commandPtr->category = category; | ||||
|     commandPtr->m_handler = handler; | ||||
|     commandPtr->m_helpText = helpText; | ||||
|     commandPtr->m_category = category; | ||||
| 
 | ||||
|     return 1; | ||||
| } | ||||
| @ -69,18 +116,162 @@ void ConsoleCommandUnregister(const char* command) { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int32_t ConsoleCommand_Help(const char* command, const char* arguments) { | ||||
|     // TODO
 | ||||
|     return 0; | ||||
| CONSOLECOMMAND* ParseCommand(const char* commandLine, const char** command, char* arguments, size_t argsize) { | ||||
|     STORM_ASSERT(commandLine); | ||||
| 
 | ||||
|     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) { | ||||
|     // TODO
 | ||||
|     // ConsolePostClose()
 | ||||
|     return 0; | ||||
| void MakeCommandCurrent(CONSOLELINE* lineptr, char* command) { | ||||
|     auto len = lineptr->inputstart; | ||||
|     lineptr->inputpos = len; | ||||
|     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) { | ||||
|     // TODO
 | ||||
|     return 0; | ||||
| void ConsoleCommandExecute(char* commandLine, int32_t addToHistory) { | ||||
|     auto em = g_ExecCreateMode; | ||||
| 
 | ||||
|     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 | ||||
| #define CONSOLE_COMMAND_HPP | ||||
| 
 | ||||
| #include "console/Types.hpp" | ||||
| 
 | ||||
| #include <storm/Hash.hpp> | ||||
| #include <cstdint> | ||||
| 
 | ||||
| #define EXEC_BUFFER_SIZE 8192 | ||||
| #define CMD_BUFFER_SIZE 1024 | ||||
| #define MAX_CMD_LENGTH 64 | ||||
| #define HISTORY_DEPTH 32 | ||||
| #define NOHELP nullptr | ||||
| #define CONSOLE_REGISTER_LIST(category, list) RegisterConsoleCommandList(category, list, sizeof(list) / sizeof(ConsoleCommandList)) | ||||
| 
 | ||||
| enum CATEGORY { | ||||
|     DEBUG, | ||||
|     GRAPHICS, | ||||
|     CONSOLE, | ||||
|     COMBAT, | ||||
|     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; | ||||
| }; | ||||
| #define CONSOLE_EXEC_BUFFER_SIZE 8192 | ||||
| #define CONSOLE_CMD_BUFFER_SIZE 1024 | ||||
| #define CONSOLE_MAX_CMD_LENGTH 64 | ||||
| #define CONSOLE_HISTORY_DEPTH 32 | ||||
| #define CONSOLE_NOHELP nullptr | ||||
| 
 | ||||
| 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 char g_ExecBuffer[EXEC_BUFFER_SIZE]; | ||||
| extern char g_ExecBuffer[CONSOLE_EXEC_BUFFER_SIZE]; | ||||
| 
 | ||||
| void ConsoleCommandDestroy(); | ||||
| 
 | ||||
| @ -42,16 +25,44 @@ char* ConsoleCommandHistory(uint32_t index); | ||||
| 
 | ||||
| uint32_t ConsoleCommandHistoryDepth(); | ||||
| 
 | ||||
| int32_t ConsoleCommandRegister(const char* command, COMMANDHANDLER handler, CATEGORY category, const char* helpText); | ||||
| 
 | ||||
| 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); | ||||
| 
 | ||||
| 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_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 | ||||
|  | ||||
| @ -1,8 +1,13 @@ | ||||
| #include "console/Console.hpp" | ||||
| #include "event/Context.hpp" | ||||
| #include "event/Event.hpp" | ||||
| 
 | ||||
| static int32_t s_active; | ||||
| static int32_t s_consoleAccessEnabled; | ||||
| 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; | ||||
| 
 | ||||
| int32_t ConsoleAccessGetEnabled() { | ||||
| @ -17,6 +22,18 @@ int32_t ConsoleGetActive() { | ||||
|     return s_active; | ||||
| } | ||||
| 
 | ||||
| float ConsoleGetFontHeight() { | ||||
|     return s_fontHeight; | ||||
| } | ||||
| 
 | ||||
| float ConsoleGetHeight() { | ||||
|     return s_consoleHeight; | ||||
| } | ||||
| 
 | ||||
| float ConsoleGetLines() { | ||||
|     return s_consoleLines; | ||||
| } | ||||
| 
 | ||||
| KEY ConsoleGetHotKey() { | ||||
|     return s_consoleKey; | ||||
| } | ||||
| @ -36,3 +53,11 @@ void ConsoleSetHotKey(KEY hotkey) { | ||||
| void ConsoleSetResizeState(CONSOLERESIZESTATE state) { | ||||
|     s_consoleResizeState = state; | ||||
| } | ||||
| 
 | ||||
| void ConsoleSetHeight(float height) { | ||||
|     s_consoleHeight = height; | ||||
| } | ||||
| 
 | ||||
| void ConsolePostClose() { | ||||
|     EventPostCloseEx(EventGetCurrentContext()); | ||||
| } | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| #ifndef CONSOLE_CONSOLE_HPP | ||||
| #define CONSOLE_CONSOLE_HPP | ||||
| 
 | ||||
| #include "console/Line.hpp" | ||||
| #include "console/Types.hpp" | ||||
| #include "event/Types.hpp" | ||||
| #include <cstdint> | ||||
| @ -11,6 +12,12 @@ void ConsoleAccessSetEnabled(int32_t enable); | ||||
| 
 | ||||
| int32_t ConsoleGetActive(); | ||||
| 
 | ||||
| float ConsoleGetFontHeight(); | ||||
| 
 | ||||
| float ConsoleGetLines(); | ||||
| 
 | ||||
| float ConsoleGetHeight(); | ||||
| 
 | ||||
| KEY ConsoleGetHotKey(); | ||||
| 
 | ||||
| CONSOLERESIZESTATE ConsoleGetResizeState(); | ||||
| @ -19,6 +26,10 @@ void ConsoleSetActive(int32_t active); | ||||
| 
 | ||||
| void ConsoleSetHotKey(KEY hotkey); | ||||
| 
 | ||||
| void ConsoleSetHeight(float height); | ||||
| 
 | ||||
| void ConsoleSetResizeState(CONSOLERESIZESTATE state); | ||||
| 
 | ||||
| void ConsolePostClose(); | ||||
| 
 | ||||
| #endif  // ifndef CONSOLE_CONSOLE_HPP
 | ||||
|  | ||||
| @ -1,4 +1,5 @@ | ||||
| #include "console/Device.hpp" | ||||
| #include "client/CmdLine.hpp" | ||||
| #include "client/Gui.hpp" | ||||
| #include "console/Console.hpp" | ||||
| #include "console/CVar.hpp" | ||||
| @ -10,17 +11,49 @@ CVar* s_cvGxMaximize; | ||||
| CVar* s_cvGxResolution; | ||||
| CVar* s_cvGxWidescreen; | ||||
| CVar* s_cvGxWindow; | ||||
| CVar* s_cvGxApi; | ||||
| DefaultSettings s_defaults; | ||||
| bool s_hwDetect; | ||||
| bool s_hwChanged; | ||||
| 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*) { | ||||
|     // TODO
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| bool CVGxResolutionCallback(CVar*, const char*, const char*, void*) { | ||||
|     // static C2iVector legalSizes[] = {
 | ||||
|     //     {}
 | ||||
|     // }
 | ||||
| 
 | ||||
|     // TODO
 | ||||
|     return true; | ||||
| } | ||||
| @ -30,6 +63,49 @@ bool CVGxWindowCallback(CVar*, const char*, const char*, void*) { | ||||
|     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() { | ||||
|     auto& format = s_defaults.format; | ||||
| 
 | ||||
| @ -92,6 +168,19 @@ void RegisterGxCVars() { | ||||
|     // TODO s_cvGxRefresh
 | ||||
|     // TODO s_cvGxTripleBuffer
 | ||||
|     // 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_cvGxAspect
 | ||||
|     // TODO s_cvGxCursor
 | ||||
| @ -148,8 +237,7 @@ void ConsoleDeviceInitialize(const char* title) { | ||||
|     // TODO proper logic
 | ||||
|     s_hwDetect = true; | ||||
| 
 | ||||
|     // TODO ConsoleAccessSetEnabled(CmdLineGetBool(35));
 | ||||
|     ConsoleAccessSetEnabled(1); | ||||
|     ConsoleAccessSetEnabled(CmdLineGetBool(WOWCMD_CONSOLE)); | ||||
| 
 | ||||
|     // TODO
 | ||||
| 
 | ||||
| @ -190,13 +278,28 @@ void ConsoleDeviceInitialize(const char* title) { | ||||
|     CGxFormat format; | ||||
|     memcpy(&format, &s_requestedFormat, sizeof(s_requestedFormat)); | ||||
| 
 | ||||
|     // TODO proper api selection
 | ||||
|     EGxApi api = GxApi_OpenGl; | ||||
| #if defined(WHOA_SYSTEM_WIN) | ||||
|     api = GxApi_D3d9; | ||||
| #elif defined(WHOA_SYSTEM_MAC) | ||||
|     api = GxApi_GLL; | ||||
| #endif | ||||
|     // Select gxApi based on user CVars and command-line parameters
 | ||||
|     EGxApi api = GxApiDefault(); | ||||
| 
 | ||||
|     auto gxApiName = s_cvGxApi->GetString(); | ||||
| 
 | ||||
|     auto gxOverride = CmdLineGetString(WOWCMD_GX_OVERRIDE); | ||||
|     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); | ||||
| 
 | ||||
|  | ||||
| @ -1,13 +1,34 @@ | ||||
| #include "console/Handlers.hpp" | ||||
| #include "console/Line.hpp" | ||||
| #include "console/Console.hpp" | ||||
| #include "console/Command.hpp" | ||||
| #include "console/Screen.hpp" | ||||
| #include "event/Event.hpp" | ||||
| #include <cstdint> | ||||
| 
 | ||||
| static int32_t s_historyIndex = 0; | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
| @ -27,7 +48,7 @@ int32_t OnKeyDown(const EVENT_DATA_KEY* data, void* param) { | ||||
| 
 | ||||
|         // Reset the highlight when toggled off
 | ||||
|         if (!ConsoleGetActive()) { | ||||
|             // TODO ResetHighlight();
 | ||||
|             ResetHighlight(); | ||||
|         } | ||||
| 
 | ||||
|         return 0; | ||||
| @ -37,12 +58,111 @@ int32_t OnKeyDown(const EVENT_DATA_KEY* data, void* param) { | ||||
|         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
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
| @ -52,17 +172,79 @@ int32_t OnKeyUp(const EVENT_DATA_KEY* 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; | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										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/Console.hpp" | ||||
| #include "console/Command.hpp" | ||||
| #include "console/Handlers.hpp" | ||||
| #include "console/Line.hpp" | ||||
| #include "console/Types.hpp" | ||||
| #include "gx/Buffer.hpp" | ||||
| #include "gx/Coordinate.hpp" | ||||
| @ -10,23 +12,34 @@ | ||||
| #include "gx/Gx.hpp" | ||||
| #include "gx/RenderState.hpp" | ||||
| #include "gx/Screen.hpp" | ||||
| #include <bc/Debug.hpp> | ||||
| #include <storm/String.hpp> | ||||
| #include <tempest/Rect.hpp> | ||||
| #include <algorithm> | ||||
| 
 | ||||
| static CGxStringBatch* s_batch; | ||||
| static uint32_t s_baseTextFlags = 0x8; | ||||
| static int32_t s_caret = 0; | ||||
| static float s_caretpixwidth; | ||||
| static float s_caretpixheight; | ||||
| static float s_consoleLines = 10.0f; | ||||
| static float s_fontHeight = 0.02f; | ||||
| static float s_consoleHeight = s_consoleLines * s_fontHeight; | ||||
| static float s_charSpacing = 0.0f; | ||||
| static CGxString* s_inputString = nullptr; | ||||
| 
 | ||||
| static char s_fontName[STORM_MAX_PATH]; | ||||
| static int32_t s_highlightState; | ||||
| static HLAYER s_layerBackground; | ||||
| static HLAYER s_layerText; | ||||
| static RECTF s_rect = { 0.0f, 1.0f, 1.0f, 1.0f }; | ||||
| 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[] = { | ||||
|     { 0xFF, 0xFF, 0xFF, 0xFF }, // DEFAULT_COLOR
 | ||||
|     { 0xFF, 0xFF, 0xFF, 0xFF }, // INPUT_COLOR
 | ||||
| @ -70,7 +83,64 @@ void DrawBackground() { | ||||
| } | ||||
| 
 | ||||
| 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) { | ||||
| @ -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) { | ||||
|     // 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) { | ||||
|     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); | ||||
| 
 | ||||
|     if (s_rect.bottom == finalPos) { | ||||
| @ -120,7 +430,7 @@ void ConsoleScreenInitialize(const char* title) { | ||||
|     s_caretpixheight = height == 0.0f ? 1.0f : 1.0f / height; | ||||
| 
 | ||||
|     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, 7.0f, 0x1 | 0x2, nullptr, PaintText, &s_layerText); | ||||
| @ -128,10 +438,11 @@ void ConsoleScreenInitialize(const char* title) { | ||||
|     RegisterHandlers(); | ||||
| 
 | ||||
|     // TODO register commands
 | ||||
|     ConsoleInitializeScreenCommand(); | ||||
| 
 | ||||
|     // TODO EventSetConfirmCloseCallback(EventCloseCallback, 0);
 | ||||
| 
 | ||||
|     // TODO ConsoleCommandExecute("ver", 1);
 | ||||
|     ConsoleCommandExecute("ver", 1); | ||||
| 
 | ||||
|     s_batch = GxuFontCreateBatch(false, false); | ||||
| } | ||||
|  | ||||
| @ -1,8 +1,46 @@ | ||||
| #ifndef 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 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 | ||||
|  | ||||
| @ -1,6 +1,11 @@ | ||||
| #ifndef CONSOLE_TYPES_HPP | ||||
| #define CONSOLE_TYPES_HPP | ||||
| 
 | ||||
| #include "gx/Font.hpp" | ||||
| 
 | ||||
| #include <storm/Hash.hpp> | ||||
| #include <storm/List.hpp> | ||||
| 
 | ||||
| enum COLOR_T { | ||||
|     DEFAULT_COLOR, | ||||
|     INPUT_COLOR, | ||||
| @ -14,10 +19,63 @@ enum COLOR_T { | ||||
|     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 { | ||||
|     CS_NONE, | ||||
|     CS_STRETCH, | ||||
|     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 | ||||
|  | ||||
							
								
								
									
										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) { | ||||
|     // 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; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -3,11 +3,89 @@ | ||||
| #include "event/EvtHandler.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) { | ||||
|     STORM_ASSERT(context); | ||||
| 
 | ||||
|     // TODO
 | ||||
|     // UpdateSyncState(data, &id, context, v3);
 | ||||
|     UpdateSyncState(context, id, data); | ||||
| 
 | ||||
|     // TODO
 | ||||
|     // if (SErrIsDisplayingError()) {
 | ||||
| @ -65,3 +143,24 @@ void IEvtQueueRegister(EvtContext* context, EVENTID id, int32_t (*handler)(const | ||||
| 
 | ||||
|     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); | ||||
| 
 | ||||
| int32_t IEvtQueueCheckSyncKeyState(EvtContext* context, KEY key); | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
| @ -112,7 +112,7 @@ void IEvtSchedulerInitialize(int32_t threadCount, int32_t netServer) { | ||||
| } | ||||
| 
 | ||||
| void IEvtSchedulerProcess() { | ||||
|     #if defined(WHOA_SYSTEM_WIN) | ||||
|     #if defined(WHOA_SYSTEM_WIN) || defined(WHOA_SYSTEM_LINUX) | ||||
|         Event::s_startEvent.Set(); | ||||
| 
 | ||||
|         SchedulerThreadProc(reinterpret_cast<void*>(1)); | ||||
|  | ||||
| @ -3,9 +3,17 @@ | ||||
| #include "event/Queue.hpp" | ||||
| #include <common/Time.hpp> | ||||
| 
 | ||||
| #if defined(WHOA_SYSTEM_WIN) | ||||
| #include <windows.h> | ||||
| #endif | ||||
| 
 | ||||
| void SynthesizeDestroy(EvtContext* context) { | ||||
|     // TODO
 | ||||
| #if defined(WHOA_SYSTEM_WIN) | ||||
|     ExitProcess(0); | ||||
| #else | ||||
|     exit(0); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void SynthesizeIdle(EvtContext* context, uint32_t currTime, float elapsedSec) { | ||||
|  | ||||
| @ -1,8 +1,14 @@ | ||||
| #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) { | ||||
|     // TODO
 | ||||
|     return 0; | ||||
|     if (Input::s_queueTail == Input::s_queueHead) { | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     OsQueueSetParam(3, OsGetAsyncTimeMs()); | ||||
| 
 | ||||
|     return OsQueueGet(id, param0, param1, param2, param3); | ||||
| } | ||||
| 
 | ||||
| void OsInputSetMouseMode(OS_MOUSE_MODE mode) { | ||||
|  | ||||
| @ -14,6 +14,10 @@ | ||||
|     #include "gx/d3d/CGxDeviceD3d.hpp" | ||||
| #endif | ||||
| 
 | ||||
| #if defined(WHOA_SYSTEM_LINUX) || defined(WHOA_SYSTEM_WIN) | ||||
|     #include "gx/glsdl/CGxDeviceGLSDL.hpp" | ||||
| #endif | ||||
| 
 | ||||
| #if defined(WHOA_SYSTEM_MAC) | ||||
|     #include "gx/gll/CGxDeviceGLL.hpp" | ||||
| #endif | ||||
| @ -120,13 +124,16 @@ CGxDevice* CGxDevice::NewGLL() { | ||||
| #endif | ||||
| 
 | ||||
| CGxDevice* CGxDevice::NewOpenGl() { | ||||
|     // TODO
 | ||||
|     // auto m = SMemAlloc(sizeof(CGxDeviceOpenGl), __FILE__, __LINE__, 0x0);
 | ||||
|     // return new (m) CGxDeviceOpenGl();
 | ||||
| 
 | ||||
|     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) { | ||||
|     auto div = CGxDevice::s_primVtxDiv[primType]; | ||||
|     if (div != 1) { | ||||
|  | ||||
| @ -56,6 +56,9 @@ class CGxDevice { | ||||
| #endif | ||||
| #if defined(WHOA_SYSTEM_MAC) | ||||
|         static CGxDevice* NewGLL(); | ||||
| #endif | ||||
| #if defined(WHOA_SYSTEM_LINUX) || defined(WHOA_SYSTEM_WIN) | ||||
|         static CGxDevice* NewGLSDL(); | ||||
| #endif | ||||
|         static CGxDevice* NewOpenGl(); | ||||
|         static uint32_t PrimCalcCount(EGxPrim primType, uint32_t count); | ||||
|  | ||||
| @ -19,6 +19,12 @@ if(WHOA_SYSTEM_MAC) | ||||
|     list(APPEND GX_SOURCES ${GLL_SOURCES}) | ||||
| 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}) | ||||
| 
 | ||||
| target_include_directories(gx | ||||
| @ -47,6 +53,15 @@ if(WHOA_SYSTEM_WIN) | ||||
|     ) | ||||
| 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) | ||||
|     target_link_libraries(gx | ||||
|         PRIVATE | ||||
|  | ||||
| @ -14,6 +14,8 @@ CGxDevice* GxDevCreate(EGxApi api, int32_t (*windowProc)(void* window, uint32_t | ||||
|             device = CGxDevice::NewD3d(); | ||||
|         } else if (api == GxApi_D3d9Ex) { | ||||
|             device = CGxDevice::NewD3d9Ex(); | ||||
|         } else if (api == GxApi_GLSDL) { | ||||
|             device = CGxDevice::NewGLSDL(); | ||||
|         } else { | ||||
|             // Error
 | ||||
|         } | ||||
| @ -29,6 +31,14 @@ CGxDevice* GxDevCreate(EGxApi api, int32_t (*windowProc)(void* window, uint32_t | ||||
|         } | ||||
|     #endif | ||||
| 
 | ||||
|     #if defined(WHOA_SYSTEM_LINUX) | ||||
|         if (api == GxApi_GLSDL) { | ||||
|             device = CGxDevice::NewGLSDL(); | ||||
|         } else { | ||||
|             // Error
 | ||||
|         } | ||||
|     #endif | ||||
| 
 | ||||
|     g_theGxDevicePtr = device; | ||||
| 
 | ||||
|     if (g_theGxDevicePtr->DeviceCreate(windowProc, format)) { | ||||
|  | ||||
| @ -337,6 +337,16 @@ int32_t GxuFontDestroyBatch(CGxStringBatch* batch) { | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| int32_t GxuFontClearBatch(CGxStringBatch* batch) { | ||||
|     if (!batch) { | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     batch->m_fontBatch.Clear(); | ||||
| 
 | ||||
|     return batch != 0; | ||||
| } | ||||
| 
 | ||||
| void GxuFontDestroyFont(CGxFont*& font) { | ||||
|     if (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 GxuFontClearBatch(CGxStringBatch* batch); | ||||
| 
 | ||||
| void GxuFontDestroyFont(CGxFont*& font); | ||||
| 
 | ||||
| void GxuFontDestroyString(CGxString*&); | ||||
|  | ||||
| @ -35,7 +35,8 @@ enum EGxApi { | ||||
|     GxApi_D3d10 = 3, | ||||
|     GxApi_D3d11 = 4, | ||||
|     GxApi_GLL = 5, | ||||
|     GxApis_Last = 6 | ||||
|     GxApi_GLSDL = 6, | ||||
|     GxApis_Last = 7 | ||||
| }; | ||||
| 
 | ||||
| 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 | ||||
|         lua-5.1 | ||||
|         stormlib-9 | ||||
|         bc | ||||
|         common | ||||
|         storm | ||||
|         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
	 Phaneron
						Phaneron