From c58628d1bdb43b2f8a11b8b2b6d33b2537bcfe00 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 5 Jan 2023 19:19:39 -0800 Subject: [PATCH 01/32] Remove non TERRAIN offroad particles Fixes spectators generating offroad particles when touching the ground. --- src/k_terrain.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/src/k_terrain.c b/src/k_terrain.c index a702f53ad..5c161a14a 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -966,26 +966,13 @@ void K_HandleFootstepParticles(mobj_t *mo) return; } - if (!(mo->flags & MF_APPLYTERRAIN)) + if (!(mo->flags & MF_APPLYTERRAIN) || mo->terrain == NULL) { // No TERRAIN effects for this object. return; } - if (mo->terrain == NULL || mo->terrain->footstepID == SIZE_MAX) - { - // If no terrain, check for offroad. - // If we're in offroad, use the default particle. - - if (mo->player != NULL && mo->player->boostpower < FRACUNIT) - { - fs = K_GetFootstepByIndex(defaultOffroadFootstep); - } - } - else - { - fs = K_GetFootstepByIndex(mo->terrain->footstepID); - } + fs = K_GetFootstepByIndex(mo->terrain->footstepID); if (fs == NULL || fs->mobjType == MT_NULL || fs->frequency <= 0) { From b57c92efd3ae58659ba64544948e31dff5dd2eed Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sat, 7 Jan 2023 01:24:17 -0600 Subject: [PATCH 02/32] cxx: Convert sdl/i_video.cpp --- src/sdl/CMakeLists.txt | 2 +- src/sdl/{i_video.c => i_video.cpp} | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) rename src/sdl/{i_video.c => i_video.cpp} (98%) diff --git a/src/sdl/CMakeLists.txt b/src/sdl/CMakeLists.txt index 62e93a2d6..2994ba2e3 100644 --- a/src/sdl/CMakeLists.txt +++ b/src/sdl/CMakeLists.txt @@ -7,7 +7,7 @@ target_sources(SRB2SDL2 PRIVATE i_net.c i_system.c i_main.cpp - i_video.c + i_video.cpp dosstr.c endtxt.c hwsym_sdl.c diff --git a/src/sdl/i_video.c b/src/sdl/i_video.cpp similarity index 98% rename from src/sdl/i_video.c rename to src/sdl/i_video.cpp index bdb522efb..b015af04c 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.cpp @@ -946,7 +946,7 @@ void I_GetEvent(void) for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { - if (newcontroller && (!JoyInfo[i].dev || !SDL_GameControllerGetAttached(JoyInfo[i].dev))) + if (newcontroller && (!JoyInfo[i].dev || !SDL_GameControllerGetAttached(JoyInfo[i].dev))) { UINT8 j; @@ -1553,7 +1553,7 @@ boolean VID_CheckRenderer(void) if (setrenderneeded) { - rendermode = setrenderneeded; + rendermode = static_cast(setrenderneeded); rendererchanged = true; #ifdef HWRENDER @@ -1585,7 +1585,7 @@ boolean VID_CheckRenderer(void) } // Create a new window. - Impl_CreateWindow(USE_FULLSCREEN); + Impl_CreateWindow(static_cast(USE_FULLSCREEN)); // From there, the OpenGL context was already created. contextcreated = true; @@ -1602,7 +1602,7 @@ boolean VID_CheckRenderer(void) setrenderneeded = 0; } - SDLSetMode(vid.width, vid.height, USE_FULLSCREEN, (setmodeneeded ? SDL_TRUE : SDL_FALSE)); + SDLSetMode(vid.width, vid.height, static_cast(USE_FULLSCREEN), (setmodeneeded ? SDL_TRUE : SDL_FALSE)); Impl_VideoSetupBuffer(); if (rendermode == render_soft) @@ -1695,7 +1695,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) #endif // Create a window - window = SDL_CreateWindow("Dr. Robotnik's Ring Racers "VERSIONSTRING, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + window = SDL_CreateWindow("Dr. Robotnik's Ring Racers " VERSIONSTRING, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, realwidth, realheight, flags); @@ -1762,7 +1762,7 @@ static void Impl_VideoSetupBuffer(void) vid.direct = NULL; if (vid.buffer) free(vid.buffer); - vid.buffer = calloc(vid.rowbytes*vid.height, NUMSCREENS); + vid.buffer = static_cast(calloc(vid.rowbytes*vid.height, NUMSCREENS)); if (!vid.buffer) { I_Error("%s", M_GetText("Not enough memory for video buffer\n")); @@ -1786,8 +1786,8 @@ void I_StartupGraphics(void) CV_RegisterVar (&cv_vidwait); CV_RegisterVar (&cv_stretch); CV_RegisterVar (&cv_alwaysgrabmouse); - disable_mouse = M_CheckParm("-nomouse"); - disable_fullscreen = M_CheckParm("-win") ? 1 : 0; + disable_mouse = static_cast(M_CheckParm("-nomouse")); + disable_fullscreen = M_CheckParm("-win") ? SDL_TRUE : SDL_FALSE; keyboard_started = true; @@ -1822,7 +1822,7 @@ void I_StartupGraphics(void) { if (!stricmp(modeparm, renderer_list[i].strvalue)) { - chosenrendermode = renderer_list[i].value; + chosenrendermode = static_cast(renderer_list[i].value); break; } i++; @@ -1850,8 +1850,8 @@ void I_StartupGraphics(void) if (chosenrendermode != render_none) rendermode = chosenrendermode; - usesdl2soft = M_CheckParm("-softblit"); - borderlesswindow = M_CheckParm("-borderless"); + usesdl2soft = M_CheckParm("-softblit") ? SDL_TRUE : SDL_FALSE; + borderlesswindow = M_CheckParm("-borderless") ? SDL_TRUE : SDL_FALSE; //SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY>>1,SDL_DEFAULT_REPEAT_INTERVAL<<2); VID_Command_ModeList_f(); From 0b3d04bbfd6c5e9793265ce79c6f64ea45d78f7d Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 7 Jan 2023 06:43:42 -0800 Subject: [PATCH 03/32] Split k_menudef.c into menus subdirectory - src/menu contains files for each menu's definitions. - src/menu/transient contains menus which are reused in many places or are separate from Main Menu entirely. File names ending in "-1" are menus which contain a submenu. The suffix is added so that the parent menu sorts before all its children in directory lists. It's also done so Tab completion doesn't stop such that a hyphen (-) would need to be typed. For example (this is how I auto complete file names): "ex" completes to "extras" because the choices are "extras.c" or "extras-addons.c" etc. Now you need to reach away from the home row of a keyboard to type a "-" in order to complete any of the submenu file names. VS "ex" completes to "extras-". You only need to reach to type a "1" for one menu. There may be more than one submenu and submenu names start with letters, which are closer to the home row. --- src/CMakeLists.txt | 2 +- src/k_menudef.c | 1771 -------------------- src/menus/CMakeLists.txt | 41 + src/menus/extras-1.c | 37 + src/menus/extras-addons.c | 27 + src/menus/extras-challenges.c | 39 + src/menus/extras-replay-hut.c | 62 + src/menus/main-1.c | 34 + src/menus/main-profile-select.c | 24 + src/menus/options-1.c | 49 + src/menus/options-data-1.c | 45 + src/menus/options-data-addons.c | 53 + src/menus/options-data-discord.c | 42 + src/menus/options-data-erase-1.c | 42 + src/menus/options-data-erase-profile.c | 24 + src/menus/options-data-replays.c | 28 + src/menus/options-data-screenshots.c | 46 + src/menus/options-gameplay-1.c | 60 + src/menus/options-gameplay-item-toggles.c | 62 + src/menus/options-hud-1.c | 57 + src/menus/options-hud-online.c | 54 + src/menus/options-profiles-1.c | 25 + src/menus/options-profiles-edit-1.c | 37 + src/menus/options-profiles-edit-controls.c | 110 ++ src/menus/options-server-1.c | 64 + src/menus/options-server-advanced.c | 62 + src/menus/options-sound.c | 66 + src/menus/options-video-1.c | 68 + src/menus/options-video-gl.c | 60 + src/menus/options-video-modes.c | 26 + src/menus/play-1.c | 17 + src/menus/play-char-select.c | 24 + src/menus/play-local-1.c | 23 + src/menus/play-local-race-1.c | 20 + src/menus/play-local-race-difficulty.c | 47 + src/menus/play-local-race-time-attack.c | 116 ++ src/menus/play-online-1.c | 32 + src/menus/play-online-host.c | 41 + src/menus/play-online-join-ip.c | 43 + src/menus/play-online-server-browser.c | 53 + src/menus/transient/CMakeLists.txt | 6 + src/menus/transient/level-select.c | 44 + src/menus/transient/manual.c | 23 + src/menus/transient/pause-game.c | 70 + src/menus/transient/pause-replay.c | 40 + 45 files changed, 1944 insertions(+), 1772 deletions(-) delete mode 100644 src/k_menudef.c create mode 100644 src/menus/CMakeLists.txt create mode 100644 src/menus/extras-1.c create mode 100644 src/menus/extras-addons.c create mode 100644 src/menus/extras-challenges.c create mode 100644 src/menus/extras-replay-hut.c create mode 100644 src/menus/main-1.c create mode 100644 src/menus/main-profile-select.c create mode 100644 src/menus/options-1.c create mode 100644 src/menus/options-data-1.c create mode 100644 src/menus/options-data-addons.c create mode 100644 src/menus/options-data-discord.c create mode 100644 src/menus/options-data-erase-1.c create mode 100644 src/menus/options-data-erase-profile.c create mode 100644 src/menus/options-data-replays.c create mode 100644 src/menus/options-data-screenshots.c create mode 100644 src/menus/options-gameplay-1.c create mode 100644 src/menus/options-gameplay-item-toggles.c create mode 100644 src/menus/options-hud-1.c create mode 100644 src/menus/options-hud-online.c create mode 100644 src/menus/options-profiles-1.c create mode 100644 src/menus/options-profiles-edit-1.c create mode 100644 src/menus/options-profiles-edit-controls.c create mode 100644 src/menus/options-server-1.c create mode 100644 src/menus/options-server-advanced.c create mode 100644 src/menus/options-sound.c create mode 100644 src/menus/options-video-1.c create mode 100644 src/menus/options-video-gl.c create mode 100644 src/menus/options-video-modes.c create mode 100644 src/menus/play-1.c create mode 100644 src/menus/play-char-select.c create mode 100644 src/menus/play-local-1.c create mode 100644 src/menus/play-local-race-1.c create mode 100644 src/menus/play-local-race-difficulty.c create mode 100644 src/menus/play-local-race-time-attack.c create mode 100644 src/menus/play-online-1.c create mode 100644 src/menus/play-online-host.c create mode 100644 src/menus/play-online-join-ip.c create mode 100644 src/menus/play-online-server-browser.c create mode 100644 src/menus/transient/CMakeLists.txt create mode 100644 src/menus/transient/level-select.c create mode 100644 src/menus/transient/manual.c create mode 100644 src/menus/transient/pause-game.c create mode 100644 src/menus/transient/pause-replay.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fbf2d6f2a..5197ab3d6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -120,7 +120,6 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 k_grandprix.c k_boss.c k_hud.c - k_menudef.c k_menufunc.c k_menudraw.c k_terrain.c @@ -533,6 +532,7 @@ add_subdirectory(io) add_subdirectory(sdl) add_subdirectory(objects) add_subdirectory(tests) +add_subdirectory(menus) # strip debug symbols into separate file when using gcc. # to be consistent with Makefile, don't generate for OS X. diff --git a/src/k_menudef.c b/src/k_menudef.c deleted file mode 100644 index a4b8de7bd..000000000 --- a/src/k_menudef.c +++ /dev/null @@ -1,1771 +0,0 @@ -/// \file k_menudef.c -/// \brief SRB2Kart menu definitions - -#include "k_menu.h" -#include "screen.h" // BASEVIDWIDTH -#include "r_main.h" // cv_skybox -#include "v_video.h" // cv_globalgamma -#include "hardware/hw_main.h" // gl consvars -#include "s_sound.h" // sounds consvars -#include "g_game.h" // cv_chatnotifications -#include "console.h" // console cvars -#include "filesrch.h" // addons cvars -#include "m_misc.h" // screenshot cvars -#include "r_fps.h" // fps cvars -#include "discord.h" // discord rpc cvars - -// ========================================================================== -// ORGANIZATION START. -// ========================================================================== -// Note: Never should we be jumping from one category of menu options to another -// without first going to the Main Menu. -// Note: Ignore the above if you're working with the Pause menu. -// Note: (Prefix)_MainMenu should be the target of all Main Menu options that -// point to submenus. - -// --------- -// Main Menu -// --------- -menuitem_t MainMenu[] = -{ - {IT_STRING | IT_CALL, "Play", - "Cut to the chase and start the race!", NULL, - {.routine = M_CharacterSelect}, 0, 0}, - - {IT_STRING | IT_CALL, "Extras", - "Check out some bonus features.", "MENUI001", - {.routine = M_InitExtras}, 0, 0}, - - {IT_STRING, "Options", - "Configure your controls, settings, and preferences.", NULL, - {.routine = M_InitOptions}, 0, 0}, - - {IT_STRING | IT_CALL, "Quit", - "Exit \"Dr. Robotnik's Ring Racers\".", NULL, - {.routine = M_QuitSRB2}, 0, 0}, -}; - -menu_t MainDef = KARTGAMEMODEMENU(MainMenu, NULL); - -// --------- -// Play Menu -// --------- - -menuitem_t PLAY_CharSelect[] = -{ - {IT_NOTHING, NULL, NULL, NULL, {NULL}, 0, 0}, -}; - -menu_t PLAY_CharSelectDef = { - sizeof (PLAY_CharSelect) / sizeof (menuitem_t), - &MainDef, - 0, - PLAY_CharSelect, - 0, 0, - 0, 0, - 0, 0, - M_DrawCharacterSelect, - M_CharacterSelectTick, - M_CharacterSelectInit, - M_CharacterSelectQuit, - M_CharacterSelectHandler -}; - -menuitem_t PLAY_MainMenu[] = -{ - {IT_STRING | IT_CALL, "Local Play", "Play only on this computer.", - NULL, {.routine = M_SetupGametypeMenu}, 0, 0}, - - {IT_STRING | IT_CALL, "Online", "Connect to other computers.", - NULL, {.routine = M_MPOptSelectInit}, /*M_MPRoomSelectInit,*/ 0, 0}, - - {IT_STRING | IT_CALL, "Back", NULL, NULL, {.routine = M_GoBack}, 0, 0}, -}; - -menu_t PLAY_MainDef = KARTGAMEMODEMENU(PLAY_MainMenu, &PLAY_CharSelectDef); - -menuitem_t PLAY_GamemodesMenu[] = -{ - {IT_STRING | IT_CALL, "Race", "A contest to see who's the fastest of them all!", - NULL, {.routine = M_SetupRaceMenu}, 0, 0}, - - {IT_STRING | IT_CALL, "Battle", "It's last kart standing in this free-for-all!", - "MENIMG00", {.routine = M_LevelSelectInit}, 0, GT_BATTLE}, - - {IT_STRING | IT_CALL, "Capsules", "Bust up all of the capsules in record time!", - NULL, {.routine = M_LevelSelectInit}, 1, GT_BATTLE}, - - {IT_STRING | IT_CALL, "Special", "Strike your target and secure the prize!", - NULL, {.routine = M_LevelSelectInit}, 1, GT_SPECIAL}, - - {IT_STRING | IT_CALL, "Back", NULL, NULL, {.routine = M_GoBack}, 0, 0}, -}; - -menu_t PLAY_GamemodesDef = KARTGAMEMODEMENU(PLAY_GamemodesMenu, &PLAY_MainDef); - -// RACE - -menuitem_t PLAY_RaceGamemodesMenu[] = -{ - {IT_STRING | IT_CALL, "Grand Prix", "Compete for the best rank over five races!", - NULL, {.routine = M_SetupDifficultySelect}, 0, 0}, - - {IT_STRING | IT_CALL, "Match Race", "Play by your own rules in a specialized, single race!", - "MENIMG01", {.routine = M_SetupDifficultySelect}, 1, 0}, - - {IT_STRING | IT_CALL, "Time Attack", "Record your best time on any track!", - NULL, {.routine = M_LevelSelectInit}, 1, GT_RACE}, - - {IT_STRING | IT_CALL, "Back", NULL, NULL, {.routine = M_GoBack}, 0, 0}, -}; - -menu_t PLAY_RaceGamemodesDef = KARTGAMEMODEMENU(PLAY_RaceGamemodesMenu, &PLAY_GamemodesDef); - - -// difficulty selection -- see drace_e -menuitem_t PLAY_RaceDifficulty[] = -{ - // For GP - {IT_STRING | IT_CVAR, "Difficulty", "Select the game difficulty", - NULL, {.cvar = &cv_dummygpdifficulty}, 0, 0}, - - // Match Race - {IT_STRING | IT_CVAR, "Difficulty", "Select the game speed", - NULL, {.cvar = &cv_dummykartspeed}, 0, 0}, - - // DISABLE THAT OPTION OUTSIDE OF MATCH RACE - {IT_STRING2 | IT_CVAR, "CPU", "Set the difficulty of CPU players.", - NULL, {.cvar = &cv_dummymatchbots}, 0, 0}, - {IT_STRING2 | IT_CVAR, "Racers", "Sets the number of racers, including players and CPU.", - NULL, {.cvar = &cv_maxplayers}, 0, 0}, - - {IT_STRING2 | IT_CVAR, "Encore", "Enable or disable Encore mode", - NULL, {.cvar = &cv_dummygpencore}, 0, 0}, - - // For GP - {IT_STRING | IT_CALL, "Cup Select", "Go on and select a cup!", NULL, {.routine = M_LevelSelectInit}, 2, GT_RACE}, - - // Match Race - {IT_STRING | IT_CALL, "Map Select", "Go on and select a race track!", NULL, {.routine = M_LevelSelectInit}, 0, GT_RACE}, - - {IT_STRING | IT_CALL, "Back", NULL, NULL, {.routine = M_GoBack}, 0, 0}, -}; - -menu_t PLAY_RaceDifficultyDef = { - sizeof(PLAY_RaceDifficulty) / sizeof(menuitem_t), - &PLAY_RaceGamemodesDef, - 0, - PLAY_RaceDifficulty, - 0, 0, - 0, 0, - 1, 5, - M_DrawRaceDifficulty, - NULL, - NULL, - NULL, - NULL -}; - - -menuitem_t PLAY_CupSelect[] = -{ - {IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, {.routine = M_CupSelectHandler}, 0, 0}, -}; - -menu_t PLAY_CupSelectDef = { - sizeof(PLAY_CupSelect) / sizeof(menuitem_t), - &PLAY_RaceGamemodesDef, - 0, - PLAY_CupSelect, - 0, 0, - 0, 0, - 2, 5, - M_DrawCupSelect, - M_CupSelectTick, - NULL, - NULL, - NULL -}; - -menuitem_t PLAY_LevelSelect[] = -{ - {IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, {.routine = M_LevelSelectHandler}, 0, 0}, -}; - -menu_t PLAY_LevelSelectDef = { - sizeof(PLAY_LevelSelect) / sizeof(menuitem_t), - &PLAY_CupSelectDef, - 0, - PLAY_LevelSelect, - 0, 0, - 0, 0, - 2, 5, - M_DrawLevelSelect, - M_LevelSelectTick, - NULL, - NULL, - NULL -}; - -// see ta_e -menuitem_t PLAY_TimeAttack[] = -{ - {IT_STRING | IT_SUBMENU, "Replay...", NULL, NULL, {.submenu = &PLAY_TAReplayDef}, 0, 0}, - {IT_STRING | IT_SUBMENU, "Guest...", NULL, NULL, {.submenu = &PLAY_TAReplayGuestDef}, 0, 0}, - {IT_STRING | IT_SUBMENU, "Ghosts...", NULL, NULL, {.submenu = &PLAY_TAGhostsDef}, 0, 0}, - {IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_CALL, "Start", NULL, NULL, {.routine = M_StartTimeAttack}, 0, 0}, -}; - -menu_t PLAY_TimeAttackDef = { - sizeof(PLAY_TimeAttack) / sizeof(menuitem_t), - &PLAY_LevelSelectDef, - 0, - PLAY_TimeAttack, - 0, 0, - 0, 0, - 2, 5, - M_DrawTimeAttack, - NULL, - NULL, - NULL, - NULL -}; - - -menuitem_t PLAY_TAReplay[] = -{ - {IT_STRING | IT_CALL, "Replay Best Time", NULL, NULL, {.routine = M_ReplayTimeAttack}, 0, 0}, - {IT_STRING | IT_CALL, "Replay Best Lap", NULL, NULL, {.routine = M_ReplayTimeAttack}, 0, 0}, - {IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_CALL, "Replay Last", NULL, NULL, {.routine = M_ReplayTimeAttack}, 0, 0}, - {IT_STRING | IT_CALL, "Replay Guest", NULL, NULL, {.routine = M_ReplayTimeAttack}, 0, 0}, - {IT_STRING | IT_CALL, "Replay Staff", NULL, NULL, {.routine = M_HandleStaffReplay}, 0, 0}, - {IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_SUBMENU, "Back", NULL, NULL, {.submenu = &PLAY_TimeAttackDef}, 0, 0}, -}; - -menu_t PLAY_TAReplayDef = { - sizeof(PLAY_TAReplay) / sizeof(menuitem_t), - &PLAY_TimeAttackDef, - 0, - PLAY_TAReplay, - 0, 0, - 0, 0, - 2, 5, - M_DrawTimeAttack, - NULL, - NULL, - NULL, - NULL -}; - -menuitem_t PLAY_TAReplayGuest[] = -{ - {IT_HEADERTEXT|IT_HEADER, "Save as guest...", NULL, NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CALL, "Best Time", NULL, NULL, {.routine = M_SetGuestReplay}, 0, 0}, - {IT_STRING | IT_CALL, "Best Lap", NULL, NULL, {.routine = M_SetGuestReplay}, 0, 0}, - {IT_STRING | IT_CALL, "Last Run", NULL, NULL, {.routine = M_SetGuestReplay}, 0, 0}, - - {IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_CALL, "Delete Guest", NULL, NULL, {.routine = M_SetGuestReplay}, 0, 0}, - - {IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_SUBMENU, "Back", NULL, NULL, {.submenu = &PLAY_TimeAttackDef}, 0, 0}, - -}; - -menu_t PLAY_TAReplayGuestDef = { - sizeof(PLAY_TAReplayGuest) / sizeof(menuitem_t), - &PLAY_TimeAttackDef, - 0, - PLAY_TAReplayGuest, - 0, 0, - 0, 0, - 2, 5, - M_DrawTimeAttack, - NULL, - NULL, - NULL, - NULL -}; - -menuitem_t PLAY_TAGhosts[] = -{ - {IT_STRING | IT_CVAR, "Best Time", NULL, NULL, {.cvar = &cv_ghost_besttime}, 0, 0}, - {IT_STRING | IT_CVAR, "Best Lap", NULL, NULL, {.cvar = &cv_ghost_bestlap}, 0, 0}, - {IT_STRING | IT_CVAR, "Last", NULL, NULL, {.cvar = &cv_ghost_last}, 0, 0}, - {IT_DISABLED, "Guest", NULL, NULL, {.cvar = &cv_ghost_guest}, 0, 0}, - {IT_DISABLED, "Staff", NULL, NULL, {.cvar = &cv_ghost_staff}, 0, 0}, - - {IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_SUBMENU, "Back", NULL, NULL, {.submenu = &PLAY_TimeAttackDef}, 0, 0}, -}; - -menu_t PLAY_TAGhostsDef = { - sizeof(PLAY_TAGhosts) / sizeof(menuitem_t), - &PLAY_TimeAttackDef, - 0, - PLAY_TAGhosts, - 0, 0, - 0, 0, - 2, 5, - M_DrawTimeAttack, - NULL, - NULL, - NULL, - NULL -}; - -// MULTIPLAYER OPTION SELECT -menuitem_t PLAY_MP_OptSelect[] = -{ - //{IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, M_MPOptSelect, 0, 0}, - {IT_STRING | IT_CALL, "Host Game", "Start your own online game!", - NULL, {.routine = M_MPHostInit}, 0, 0}, - - {IT_STRING | IT_CALL, "Server Browser", "Search for game servers to play in.", - NULL, {.routine = M_MPRoomSelectInit}, 0, 0}, - - {IT_STRING | IT_CALL, "Join by IP", "Join an online game by its IP address.", - NULL, {.routine = M_MPJoinIPInit}, 0, 0}, -}; - -menu_t PLAY_MP_OptSelectDef = { - sizeof (PLAY_MP_OptSelect) / sizeof (menuitem_t), - &PLAY_MainDef, - 0, - PLAY_MP_OptSelect, - 0, 0, - 0, 0, - -1, 1, - M_DrawMPOptSelect, - M_MPOptSelectTick, - NULL, - NULL, - NULL -}; - -// MULTIPLAYER HOST SCREEN -- see mhost_e -menuitem_t PLAY_MP_Host[] = -{ - //{IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, M_MPOptSelect, 0, 0}, - - {IT_STRING | IT_CVAR | IT_CV_STRING, "Server Name", "Display name for your game online. Other players will see this.", - NULL, {.cvar = &cv_servername}, 0, 0}, - - {IT_STRING | IT_CVAR, "Public Server", "Display or not your game in the Server Browser for other players.", - NULL, {.cvar = &cv_advertise}, 0, 0}, - - {IT_STRING | IT_CVAR, "Max. Players", "Set how many players can play at once. Others will spectate.", - NULL, {.cvar = &cv_maxplayers}, 0, 0}, - - {IT_STRING | IT_KEYHANDLER, "Gamemode", "Choose the type of play on your server.", - NULL, {.routine = M_HandleHostMenuGametype}, 0, 0}, - - {IT_STRING | IT_CALL, "GO", "Select a map with the currently selected gamemode", - NULL, {.routine = M_MPSetupNetgameMapSelect}, 0, 0}, - -}; - -menu_t PLAY_MP_HostDef = { - sizeof (PLAY_MP_Host) / sizeof (menuitem_t), - &PLAY_MP_OptSelectDef, - 0, - PLAY_MP_Host, - 0, 0, - 0, 0, - -1, 1, // 1 frame transition.... This is really just because I don't want the black fade when we press esc, hehe - M_DrawMPHost, - M_MPOptSelectTick, // This handles the unfolding options - NULL, - M_MPResetOpts, - NULL -}; - -// MULTIPLAYER JOIN BY IP -menuitem_t PLAY_MP_JoinIP[] = -{ - //{IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, M_MPOptSelect, 0, 0}, - - {IT_STRING | IT_CVAR | IT_CV_STRING, "IP: ", "Type the IPv4 address of the server.", - NULL, {.cvar = &cv_dummyip}, 0, 0}, - - {IT_STRING, "CONNECT ", "Attempt to connect to the server you entered the IP for.", - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_SPACE, "LAST IPs JOINED:", "Kanade best waifu :)", - NULL, {NULL}, 0, 0}, - - {IT_STRING, "servip1", "The last 3 IPs you've succesfully joined are displayed here.", - NULL, {NULL}, 0, 0}, - - {IT_STRING, "servip2", "The last 3 IPs you've succesfully joined are displayed here.", - NULL, {NULL}, 0, 0}, - - {IT_STRING, "servip3", "The last 3 IPs you've succesfully joined are displayed here.", - NULL, {NULL}, 0, 0}, - -}; - -menu_t PLAY_MP_JoinIPDef = { - sizeof (PLAY_MP_JoinIP) / sizeof (menuitem_t), - &PLAY_MP_OptSelectDef, - 0, - PLAY_MP_JoinIP, - 0, 0, - 0, 0, - -1, 1, // 1 frame transition.... This is really just because I don't want the black fade when we press esc, hehe - M_DrawMPJoinIP, - M_MPOptSelectTick, // This handles the unfolding options - NULL, - M_MPResetOpts, - M_JoinIPInputs -}; - -// MULTIPLAYER ROOM SELECT (CORE / MODDED) -menuitem_t PLAY_MP_RoomSelect[] = -{ - {IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, {.routine = M_MPRoomSelect}, 0, 0}, -}; - -menu_t PLAY_MP_RoomSelectDef = { - sizeof (PLAY_MP_RoomSelect) / sizeof (menuitem_t), - &PLAY_MP_OptSelectDef, - 0, - PLAY_MP_RoomSelect, - 0, 0, - 0, 0, - 0, 0, - M_DrawMPRoomSelect, - M_MPRoomSelectTick, - NULL, - NULL, - NULL -}; - -// SERVER BROWSER -menuitem_t PLAY_MP_ServerBrowser[] = -{ - - {IT_STRING | IT_CVAR, "SORT BY", NULL, // tooltip MUST be null. - NULL, {.cvar = &cv_serversort}, 0, 0}, - - {IT_STRING, "REFRESH", NULL, - NULL, {NULL}, 0, 0}, - - {IT_NOTHING, NULL, NULL, NULL, {NULL}, 0, 0}, -}; - -menu_t PLAY_MP_ServerBrowserDef = { - sizeof (PLAY_MP_ServerBrowser) / sizeof (menuitem_t), - &PLAY_MP_RoomSelectDef, - 0, - PLAY_MP_ServerBrowser, - 32, 36, - 0, 0, - 0, 0, - M_DrawMPServerBrowser, - M_MPServerBrowserTick, - NULL, - NULL, - M_ServerBrowserInputs -}; - -// options menu -- see mopt_e -menuitem_t OPTIONS_Main[] = -{ - - {IT_STRING | IT_CALL, "Profile Setup", "Remap keys & buttons to your likings.", - NULL, {.routine = M_ProfileSelectInit}, 0, 0}, - - {IT_STRING | IT_SUBMENU, "Video Options", "Change video settings such as the resolution.", - NULL, {.submenu = &OPTIONS_VideoDef}, 0, 0}, - - {IT_STRING | IT_SUBMENU, "Sound Options", "Adjust various sound settings such as the volume.", - NULL, {.submenu = &OPTIONS_SoundDef}, 0, 0}, - - {IT_STRING | IT_SUBMENU, "HUD Options", "Options related to the Heads-Up Display.", - NULL, {.submenu = &OPTIONS_HUDDef}, 0, 0}, - - {IT_STRING | IT_SUBMENU, "Gameplay Options", "Change various game related options", - NULL, {.submenu = &OPTIONS_GameplayDef}, 0, 0}, - - {IT_STRING | IT_SUBMENU, "Server Options", "Change various specific options for your game server.", - NULL, {.submenu = &OPTIONS_ServerDef}, 0, 0}, - - {IT_STRING | IT_SUBMENU, "Data Options", "Miscellaneous data options such as the screenshot format.", - NULL, {.submenu = &OPTIONS_DataDef}, 0, 0}, - - {IT_STRING | IT_CALL, "Tricks & Secrets", "Those who bother reading a game manual always get the edge over those who don't!", - NULL, {.routine = M_Manual}, 0, 0}, -}; - -// For options menu, the 'extra1' field will determine the background colour to use for... the background! (What a concept!) -menu_t OPTIONS_MainDef = { - sizeof (OPTIONS_Main) / sizeof (menuitem_t), - &MainDef, - 0, - OPTIONS_Main, - 0, 0, - SKINCOLOR_SLATE, 0, - 2, 5, - M_DrawOptions, - M_OptionsTick, - NULL, - NULL, - M_OptionsInputs -}; - -// profiles menu -// profile select -menuitem_t OPTIONS_Profiles[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "Select a Profile.", - NULL, {.routine = M_HandleProfileSelect}, 0, 0}, // dummy menuitem for the control func -}; - -menu_t OPTIONS_ProfilesDef = { - sizeof (OPTIONS_Profiles) / sizeof (menuitem_t), - &OPTIONS_MainDef, - 0, - OPTIONS_Profiles, - 32, 80, - SKINCOLOR_ULTRAMARINE, 0, - 2, 5, - M_DrawProfileSelect, - M_OptionsTick, - NULL, - NULL, - NULL, -}; - -// Duplicate for main profile select. -menuitem_t MAIN_Profiles[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "Select a profile to use or create a new Profile.", - NULL, {.routine = M_HandleProfileSelect}, 0, 0}, // dummy menuitem for the control func -}; - -menu_t MAIN_ProfilesDef = { - sizeof (MAIN_Profiles) / sizeof (menuitem_t), - NULL, - 0, - MAIN_Profiles, - 32, 80, - SKINCOLOR_ULTRAMARINE, 0, - 2, 5, - M_DrawProfileSelect, - M_OptionsTick, - NULL, - NULL, - NULL, -}; - - -menuitem_t OPTIONS_EditProfile[] = { - {IT_STRING | IT_CVAR | IT_CV_STRING, "Profile Name", "6-character long name to identify this Profile.", - NULL, {.cvar = &cv_dummyprofilename}, 0, 0}, - - {IT_STRING | IT_CVAR | IT_CV_STRING, "Player Name", "Name displayed online when using this Profile.", - NULL, {.cvar = &cv_dummyprofileplayername}, 0, 0}, - - {IT_STRING | IT_CALL, "Character", "Default character and color for this Profile.", - NULL, {.routine = M_CharacterSelect}, 0, 0}, - - {IT_STRING | IT_CALL, "Controls", "Select the button mappings for this Profile.", - NULL, {.routine = M_ProfileDeviceSelect}, 0, 0}, - - {IT_STRING | IT_CALL, "Confirm", "Confirm changes.", - NULL, {.routine = M_ConfirmProfile}, 0, 0}, - -}; - -menu_t OPTIONS_EditProfileDef = { - sizeof (OPTIONS_EditProfile) / sizeof (menuitem_t), - &OPTIONS_ProfilesDef, - 0, - OPTIONS_EditProfile, - 32, 80, - SKINCOLOR_ULTRAMARINE, 0, - 2, 5, - M_DrawEditProfile, - M_HandleProfileEdit, - NULL, - NULL, - M_ProfileEditInputs, -}; - -menuitem_t OPTIONS_ProfileControls[] = { - - {IT_HEADER, "MAIN CONTROLS", "That's the stuff on the controller!!", - NULL, {NULL}, 0, 0}, - - {IT_CONTROL, "A", "Accelerate / Confirm", - "PR_BTA", {.routine = M_ProfileSetControl}, gc_a, 0}, - - {IT_CONTROL, "B", "Look backwards / Back", - "PR_BTB", {.routine = M_ProfileSetControl}, gc_b, 0}, - - {IT_CONTROL, "C", "Spindash / Extra", - "PR_BTC", {.routine = M_ProfileSetControl}, gc_c, 0}, - - {IT_CONTROL, "X", "Brake / Back", - "PR_BTX", {.routine = M_ProfileSetControl}, gc_x, 0}, - - // @TODO What does this do??? - {IT_CONTROL, "Y", "N/A ?", - "PR_BTY", {.routine = M_ProfileSetControl}, gc_y, 0}, - - {IT_CONTROL, "Z", "N/A ?", - "PR_BTZ", {.routine = M_ProfileSetControl}, gc_z, 0}, - - {IT_CONTROL, "L", "Use item", - "PR_BTL", {.routine = M_ProfileSetControl}, gc_l, 0}, - - {IT_CONTROL, "R", "Drift", - "PR_BTR", {.routine = M_ProfileSetControl}, gc_r, 0}, - - {IT_CONTROL, "Turn Left", "Turn left", - "PR_PADL", {.routine = M_ProfileSetControl}, gc_left, 0}, - - {IT_CONTROL, "Turn Right", "Turn right", - "PR_PADR", {.routine = M_ProfileSetControl}, gc_right, 0}, - - {IT_CONTROL, "Aim Forward", "Aim forwards", - "PR_PADU", {.routine = M_ProfileSetControl}, gc_up, 0}, - - {IT_CONTROL, "Aim Backwards", "Aim backwards", - "PR_PADD", {.routine = M_ProfileSetControl}, gc_down, 0}, - - {IT_CONTROL, "Start", "Open pause menu", - "PR_BTS", {.routine = M_ProfileSetControl}, gc_start, 0}, - - {IT_HEADER, "OPTIONAL CONTROLS", "Take a screenshot, chat...", - NULL, {NULL}, 0, 0}, - - {IT_CONTROL, "SCREENSHOT", "Also usable with F8 on Keyboard.", - NULL, {.routine = M_ProfileSetControl}, gc_screenshot, 0}, - - {IT_CONTROL, "GIF CAPTURE", "Also usable with F9 on Keyboard.", - NULL, {.routine = M_ProfileSetControl}, gc_recordgif, 0}, - - {IT_CONTROL, "OPEN CHAT", "Opens chatbox in online games.", - NULL, {.routine = M_ProfileSetControl}, gc_talk, 0}, - - {IT_CONTROL, "OPEN TEAM CHAT", "Do we even have team gamemodes?", - NULL, {.routine = M_ProfileSetControl}, gc_teamtalk, 0}, - - {IT_CONTROL, "SHOW RANKINGS", "Show mid-game rankings.", - NULL, {.routine = M_ProfileSetControl}, gc_rankings, 0}, - - {IT_CONTROL, "OPEN CONSOLE", "Opens the developer options console.", - NULL, {.routine = M_ProfileSetControl}, gc_console, 0}, - - {IT_CONTROL, "LUA/A", "May be used by add-ons.", - NULL, {.routine = M_ProfileSetControl}, gc_luaa, 0}, - - {IT_CONTROL, "LUA/B", "May be used by add-ons.", - NULL, {.routine = M_ProfileSetControl}, gc_luab, 0}, - - {IT_CONTROL, "LUA/C", "May be used by add-ons.", - NULL, {.routine = M_ProfileSetControl}, gc_luac, 0}, - - {IT_HEADER, "TOGGLES", "For per-player commands", - NULL, {NULL}, 0, 0}, - - {IT_CONTROL | IT_CVAR, "KICKSTART ACCEL", "Hold A to auto-accel. Tap it to cancel.", - NULL, {.cvar = &cv_dummyprofilekickstart}, 0, 0}, - - {IT_HEADER, "EXTRA", "", - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CALL, "TRY MAPPINGS", "Test your controls.", - NULL, {.routine = M_ProfileTryController}, 0, 0}, - - {IT_STRING | IT_CALL, "CONFIRM", "Go back to profile setup.", - NULL, {.routine = M_ProfileControlsConfirm}, 0, 0}, -}; - - - -menu_t OPTIONS_ProfileControlsDef = { - sizeof (OPTIONS_ProfileControls) / sizeof (menuitem_t), - &OPTIONS_EditProfileDef, - 0, - OPTIONS_ProfileControls, - 32, 80, - SKINCOLOR_ULTRAMARINE, 0, - 3, 5, - M_DrawProfileControls, - M_HandleProfileControls, - NULL, - NULL, - M_ProfileControlsInputs, -}; - -// video options menu... -// options menu -menuitem_t OPTIONS_Video[] = -{ - - {IT_STRING | IT_CALL, "Set Resolution...", "Change the screen resolution for the game.", - NULL, {.routine = M_VideoModeMenu}, 0, 0}, - -// A check to see if you're not running on a fucking antique potato powered stone i guess??????? - -#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) - {IT_STRING | IT_CVAR, "Fullscreen", "Set whether you want to use fullscreen or windowed mode.", - NULL, {.cvar = &cv_fullscreen}, 0, 0}, -#endif - - {IT_NOTHING|IT_SPACE, NULL, "Kanade best waifu! I promise!", - NULL, {NULL}, 0, 0}, - - // Everytime I see a screenshot at max gamma I die inside - {IT_STRING | IT_CVAR | IT_CV_SLIDER, "Gamma", "Adjusts the overall brightness of the game.", - NULL, {.cvar = &cv_globalgamma}, 0, 0}, - - {IT_STRING | IT_CVAR, "FPS Cap", "Handles the refresh rate of the game (does not affect gamelogic).", - NULL, {.cvar = &cv_fpscap}, 0, 0}, - - {IT_STRING | IT_CVAR, "Enable Skyboxes", "Turning this off will improve performance at the detriment of visuals for many maps.", - NULL, {.cvar = &cv_skybox}, 0, 0}, - - {IT_STRING | IT_CVAR, "Draw Distance", "How far objects can be drawn. Lower values may improve performance at the cost of visibility.", - NULL, {.cvar = &cv_drawdist}, 0, 0}, - - {IT_STRING | IT_CVAR, "Weather Draw Distance", "Affects how far weather visuals can be drawn. Lower values improve performance.", - NULL, {.cvar = &cv_drawdist_precip}, 0, 0}, - - {IT_STRING | IT_CVAR, "Show FPS", "Displays the game framerate at the lower right corner of the screen.", - NULL, {.cvar = &cv_ticrate}, 0, 0}, - - {IT_NOTHING|IT_SPACE, NULL, "Kanade best waifu! I promise!", - NULL, {NULL}, 0, 0}, - -#ifdef HWRENDER - {IT_STRING | IT_SUBMENU, "Hardware Options...", "For usage and configuration of the OpenGL renderer.", - NULL, {.submenu = &OPTIONS_VideoOGLDef}, 0, 0}, -#endif - -}; - -menu_t OPTIONS_VideoDef = { - sizeof (OPTIONS_Video) / sizeof (menuitem_t), - &OPTIONS_MainDef, - 0, - OPTIONS_Video, - 32, 80, - SKINCOLOR_PLAGUE, 0, - 2, 5, - M_DrawGenericOptions, - M_OptionsTick, - NULL, - NULL, - NULL, -}; - -menuitem_t OPTIONS_VideoModes[] = { - - {IT_KEYHANDLER | IT_NOTHING, NULL, "Select a resolution.", - NULL, {.routine = M_HandleVideoModes}, 0, 0}, // dummy menuitem for the control func - -}; - -menu_t OPTIONS_VideoModesDef = { - sizeof (OPTIONS_VideoModes) / sizeof (menuitem_t), - &OPTIONS_VideoDef, - 0, - OPTIONS_VideoModes, - 48, 80, - SKINCOLOR_PLAGUE, 0, - 2, 5, - M_DrawVideoModes, - M_OptionsTick, - NULL, - NULL, - NULL, -}; - -#ifdef HWRENDER -menuitem_t OPTIONS_VideoOGL[] = -{ - - {IT_STRING | IT_CVAR, "Renderer", "Change renderers between Software and OpenGL", - NULL, {.cvar = &cv_renderer}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_HEADER, "OPTIONS BELOW ARE OPENGL ONLY!", "Watch people get confused anyway!!", - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "3D Models", "Use 3D models instead of sprites when applicable.", - NULL, {.cvar = &cv_glmodels}, 0, 0}, - - {IT_STRING | IT_CVAR, "Shaders", "Use GLSL Shaders. Turning them off increases performance at the expanse of visual quality.", - NULL, {.cvar = &cv_glshaders}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Texture Quality", "Texture depth. Higher values are recommended.", - NULL, {.cvar = &cv_scr_depth}, 0, 0}, - - {IT_STRING | IT_CVAR, "Texture Filter", "Texture Filter. Nearest is recommended.", - NULL, {.cvar = &cv_glfiltermode}, 0, 0}, - - {IT_STRING | IT_CVAR, "Anisotropic", "Lower values will improve performance at a minor quality loss.", - NULL, {.cvar = &cv_glanisotropicmode}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Sprite Billboarding", "Adjusts sprites when viewed from above or below to not make them appear flat.", - NULL, {.cvar = &cv_glspritebillboarding}, 0, 0}, - - {IT_STRING | IT_CVAR, "Software Perspective", "Emulates Software shearing when looking up or down. Not recommended.", - NULL, {.cvar = &cv_glshearing}, 0, 0}, -}; - -menu_t OPTIONS_VideoOGLDef = { - sizeof (OPTIONS_VideoOGL) / sizeof (menuitem_t), - &OPTIONS_VideoDef, - 0, - OPTIONS_VideoOGL, - 32, 80, - SKINCOLOR_PLAGUE, 0, - 2, 5, - M_DrawGenericOptions, - M_OptionsTick, - NULL, - NULL, - NULL, -}; -#endif - -menuitem_t OPTIONS_Sound[] = -{ - - {IT_STRING | IT_CVAR, "SFX", "Enable or disable sound effect playback.", - NULL, {.cvar = &cv_gamesounds}, 0, 0}, - - {IT_STRING | IT_CVAR | IT_CV_SLIDER, "SFX Volume", "Adjust the volume of sound effects.", - NULL, {.cvar = &cv_soundvolume}, 0, 0}, - - {IT_STRING | IT_CVAR, "Music", "Enable or disable music playback.", - NULL, {.cvar = &cv_gamedigimusic}, 0, 0}, - - {IT_STRING | IT_CVAR | IT_CV_SLIDER, "Music Volume", "Adjust the volume of music playback.", - NULL, {.cvar = &cv_digmusicvolume}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Reverse L/R Channels", "Reverse left & right channels for Stereo playback.", - NULL, {.cvar = &stereoreverse}, 0, 0}, - - {IT_STRING | IT_CVAR, "Surround", "Enables or disable Surround sound playback.", - NULL, {.cvar = &surround}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Chat Notifications", "Set when to play notification sounds when chat messages are received.", - NULL, {.cvar = &cv_chatnotifications}, 0, 0}, - - {IT_STRING | IT_CVAR, "Character Voices", "Set how often to play character voices in game.", - NULL, {.cvar = &cv_kartvoices}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Play Music While Unfocused", "Keeps playing music even if the game is not the active window.", - NULL, {.cvar = &cv_playmusicifunfocused}, 0, 0}, - - {IT_STRING | IT_CVAR, "Play SFX While Unfocused", "Keeps playing sound effects even if the game is not the active window.", - NULL, {.cvar = &cv_playsoundifunfocused}, 0, 0}, - - // @TODO: Sound test (there's currently no space on this menu, might be better to throw it in extras?) -}; - -menu_t OPTIONS_SoundDef = { - sizeof (OPTIONS_Sound) / sizeof (menuitem_t), - &OPTIONS_MainDef, - 0, - OPTIONS_Sound, - 48, 80, - SKINCOLOR_THUNDER, 0, - 2, 5, - M_DrawGenericOptions, - M_OptionsTick, - NULL, - NULL, - NULL, -}; - -menuitem_t OPTIONS_HUD[] = -{ - - {IT_STRING | IT_CVAR, "Show HUD (F3)", "Toggles HUD display. Great for taking screenshots!", - NULL, {.cvar = &cv_showhud}, 0, 0}, - - {IT_STRING | IT_CVAR | IT_CV_SLIDER, "HUD Opacity", "Non opaque values may have performance impacts in software mode.", - NULL, {.cvar = &cv_translucenthud}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Speedometer", "Choose to what speed unit to display or toggle off the speedometer.", - NULL, {.cvar = &cv_kartspeedometer}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Console Text Size", "Size of the text within the console.", - NULL, {.cvar = &cv_constextsize}, 0, 0}, - - // we spell words properly here. - {IT_STRING | IT_CVAR, "Console Tint", "Change the background colour of the console.", - NULL, {.cvar = &cons_backcolor}, 0, 0}, - - {IT_STRING | IT_CVAR, "Show \"FOCUS LOST\"", "Displays \"FOCUS LOST\" when the game window isn't the active window.", - NULL, {.cvar = &cv_showfocuslost}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_SUBMENU, "Online HUD Options...", "HUD options related to the online chat box and other features.", - NULL, {.submenu = &OPTIONS_HUDOnlineDef}, 0, 0}, -}; - -menu_t OPTIONS_HUDDef = { - sizeof (OPTIONS_HUD) / sizeof (menuitem_t), - &OPTIONS_MainDef, - 0, - OPTIONS_HUD, - 48, 80, - SKINCOLOR_SUNSLAM, 0, - 2, 5, - M_DrawGenericOptions, - M_OptionsTick, - NULL, - NULL, - NULL, -}; - -menuitem_t OPTIONS_HUDOnline[] = -{ - - {IT_STRING | IT_CVAR, "Chat Mode", "Choose whether to display chat in its own window or the console.", - NULL, {.cvar = &cv_consolechat}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Chat Box Tint", "Changes the background colour of the chat box.", - NULL, {.cvar = &cv_chatbacktint}, 0, 0}, - - {IT_STRING | IT_CVAR | IT_CV_SLIDER, "Chat Box Width", "Change the width of the Chat Box", - NULL, {.cvar = &cv_chatwidth}, 0, 0}, - - {IT_STRING | IT_CVAR | IT_CV_SLIDER, "Chat Box Height", "Change the height of the Chat Box", - NULL, {.cvar = &cv_chatheight}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Message Fadeout Time", "How long chat messages stay displayed with the chat closed.", - NULL, {.cvar = &cv_chattime}, 0, 0}, - - {IT_STRING | IT_CVAR, "Spam Protection", "Prevents too many message from a single player from being displayed.", - NULL, {.cvar = &cv_chatspamprotection}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Local Ping Display", "In netgames, displays your ping at the lower right corner of the screen.", - NULL, {.cvar = &cv_showping}, 0, 0}, - -}; - -menu_t OPTIONS_HUDOnlineDef = { - sizeof (OPTIONS_HUDOnline) / sizeof (menuitem_t), - &OPTIONS_HUDDef, - 0, - OPTIONS_HUDOnline, - 48, 80, - SKINCOLOR_SUNSLAM, 0, - 2, 5, - M_DrawGenericOptions, - M_OptionsTick, - NULL, - NULL, - NULL, -}; - -// Gameplay options -- see gopt_e -menuitem_t OPTIONS_Gameplay[] = -{ - - {IT_STRING | IT_CVAR, "Game Speed", "Change Game Speed for the next map.", - NULL, {.cvar = &cv_kartspeed}, 0, 0}, - - {IT_STRING | IT_CVAR, "Base Lap Count", "Change how many laps must be completed per race.", - NULL, {.cvar = &cv_numlaps}, 0, 0}, - - {IT_STRING | IT_CVAR, "Frantic Items", "Make item odds crazier with more powerful items!", - NULL, {.cvar = &cv_kartfrantic}, 0, 0}, - - {IT_STRING | IT_CVAR, "Encore Mode", "Forces Encore Mode on for the next map.", - NULL, {.cvar = &cv_kartencore}, 0, 0}, - - {IT_STRING | IT_CVAR, "Exit Countdown", "How long players have to finish after 1st place finishes.", - NULL, {.cvar = &cv_countdowntime}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Time Limit", "Change the time limit for Battle rounds.", - NULL, {.cvar = &cv_timelimit}, 0, 0}, - - {IT_STRING | IT_CVAR, "Starting Bumpers", "Change how many bumpers player start with in Battle.", - NULL, {.cvar = &cv_kartbumpers}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Minimum Input Delay", "Practice for online play! Higher = more delay.", - NULL, {.cvar = &cv_mindelay}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_SUBMENU, "Random Item Toggles...", "Change which items to enable for your games.", - NULL, {.submenu = &OPTIONS_GameplayItemsDef}, 0, 0}, - -}; - -menu_t OPTIONS_GameplayDef = { - sizeof (OPTIONS_Gameplay) / sizeof (menuitem_t), - &OPTIONS_MainDef, - 0, - OPTIONS_Gameplay, - 48, 80, - SKINCOLOR_SCARLET, 0, - 2, 5, - M_DrawGenericOptions, - M_OptionsTick, - NULL, - NULL, - NULL, -}; - -menuitem_t OPTIONS_GameplayItems[] = -{ - // Mostly handled by the drawing function. - {IT_KEYHANDLER | IT_NOTHING, NULL, "Super Rings", NULL, {.routine = M_HandleItemToggles}, KITEM_SUPERRING, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Self-Propelled Bombs", NULL, {.routine = M_HandleItemToggles}, KITEM_SPB, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Eggman Marks", NULL, {.routine = M_HandleItemToggles}, KITEM_EGGMAN, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Toggle All", NULL, {.routine = M_HandleItemToggles}, 0, 0}, - - {IT_KEYHANDLER | IT_NOTHING, NULL, "Sneakers", NULL, {.routine = M_HandleItemToggles}, KITEM_SNEAKER, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Sneakers x2", NULL, {.routine = M_HandleItemToggles}, KRITEM_DUALSNEAKER, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Sneakers x3", NULL, {.routine = M_HandleItemToggles}, KRITEM_TRIPLESNEAKER, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Rocket Sneakers", NULL, {.routine = M_HandleItemToggles}, KITEM_ROCKETSNEAKER, 0}, - - {IT_KEYHANDLER | IT_NOTHING, NULL, "Bananas", NULL, {.routine = M_HandleItemToggles}, KITEM_BANANA, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Bananas x3", NULL, {.routine = M_HandleItemToggles}, KRITEM_TRIPLEBANANA, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Proximity Mines", NULL, {.routine = M_HandleItemToggles}, KITEM_MINE, 0}, - - {IT_KEYHANDLER | IT_NOTHING, NULL, "Orbinauts", NULL, {.routine = M_HandleItemToggles}, KITEM_ORBINAUT, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Orbinauts x3", NULL, {.routine = M_HandleItemToggles}, KRITEM_TRIPLEORBINAUT, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Orbinauts x4", NULL, {.routine = M_HandleItemToggles}, KRITEM_QUADORBINAUT, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Land Mines", NULL, {.routine = M_HandleItemToggles}, KITEM_LANDMINE, 0}, - - {IT_KEYHANDLER | IT_NOTHING, NULL, "Jawz", NULL, {.routine = M_HandleItemToggles}, KITEM_JAWZ, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Jawz x2", NULL, {.routine = M_HandleItemToggles}, KRITEM_DUALJAWZ, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Ballhogs", NULL, {.routine = M_HandleItemToggles}, KITEM_BALLHOG, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Drop Targets", NULL, {.routine = M_HandleItemToggles}, KITEM_DROPTARGET, sfx_s258}, - - {IT_KEYHANDLER | IT_NOTHING, NULL, "Lightning Shields", NULL, {.routine = M_HandleItemToggles}, KITEM_LIGHTNINGSHIELD, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Bubble Shields", NULL, {.routine = M_HandleItemToggles}, KITEM_BUBBLESHIELD, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Flame Shields", NULL, {.routine = M_HandleItemToggles}, KITEM_FLAMESHIELD, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Hyudoros", NULL, {.routine = M_HandleItemToggles}, KITEM_HYUDORO, 0}, - - {IT_KEYHANDLER | IT_NOTHING, NULL, "Invinciblity", NULL, {.routine = M_HandleItemToggles}, KITEM_INVINCIBILITY, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Grow", NULL, {.routine = M_HandleItemToggles}, KITEM_GROW, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Shrink", NULL, {.routine = M_HandleItemToggles}, KITEM_SHRINK, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, NULL, NULL, {.routine = M_HandleItemToggles}, 255, 0}, - - {IT_KEYHANDLER | IT_NOTHING, NULL, "Pogo Springs", NULL, {.routine = M_HandleItemToggles}, KITEM_POGOSPRING, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Kitchen Sinks", NULL, {.routine = M_HandleItemToggles}, KITEM_KITCHENSINK, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, NULL, NULL, {.routine = M_HandleItemToggles}, 255, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, NULL, NULL, {.routine = M_HandleItemToggles}, 255, 0} -}; - -menu_t OPTIONS_GameplayItemsDef = { - sizeof (OPTIONS_GameplayItems) / sizeof (menuitem_t), - &OPTIONS_GameplayDef, - 0, - OPTIONS_GameplayItems, - 14, 40, - SKINCOLOR_SCARLET, 0, - 2, 5, - M_DrawItemToggles, - M_OptionsTick, - NULL, - NULL, - NULL, -}; - -menuitem_t OPTIONS_Server[] = -{ - - {IT_STRING | IT_CVAR | IT_CV_STRING, "Server Name", "Change the name of your server.", - NULL, {.cvar = &cv_servername}, 0, 0}, - - {IT_STRING | IT_CVAR, "Intermission", "Set how long to stay on the result screen.", - NULL, {.cvar = &cv_inttime}, 0, 0}, - - {IT_STRING | IT_CVAR, "Map Progression", "Set how the next map is chosen.", - NULL, {.cvar = &cv_advancemap}, 0, 0}, - - {IT_STRING | IT_CVAR, "Vote Timer", "Set how long players have to vote.", - NULL, {.cvar = &cv_votetime}, 0, 0}, - - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Maximum Players", "How many players can play at once.", - NULL, {.cvar = &cv_maxplayers}, 0, 0}, - - {IT_STRING | IT_CVAR, "Maximum Connections", "How many players & spectators can connect to the server.", - NULL, {.cvar = &cv_maxconnections}, 0, 0}, - - {IT_STRING | IT_CVAR, "Allow Joining", "Sets whether players can connect to your server.", - NULL, {.cvar = &cv_allownewplayer}, 0, 0}, - - {IT_STRING | IT_CVAR, "Allow Downloads", "Allows joiners to download missing files from you.", - NULL, {.cvar = &cv_downloading}, 0, 0}, - - {IT_STRING | IT_CVAR, "Pause Permissions", "Sets who can pause the game.", - NULL, {.cvar = &cv_pause}, 0, 0}, - - {IT_STRING | IT_CVAR, "Mute Chat", "Prevents non-admins from sending chat messages.", - NULL, {.cvar = &cv_mute}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_SUBMENU, "Advanced...", "Advanced options. Be careful when messing with these!", - NULL, {.submenu = &OPTIONS_ServerAdvancedDef}, 0, 0}, - -}; - -menu_t OPTIONS_ServerDef = { - sizeof (OPTIONS_Server) / sizeof (menuitem_t), - &OPTIONS_MainDef, - 0, - OPTIONS_Server, - 48, 70, // This menu here is slightly higher because there's a lot of options... - SKINCOLOR_VIOLET, 0, - 2, 5, - M_DrawGenericOptions, - M_OptionsTick, - NULL, - NULL, - NULL, -}; - -menuitem_t OPTIONS_ServerAdvanced[] = -{ - - {IT_STRING | IT_CVAR | IT_CV_STRING, "Server Browser Address", "Default is \'https://ms.kartkrew.org/ms/api\'", - NULL, {.cvar = &cv_masterserver}, 0, 0}, - - {IT_STRING | IT_CVAR, "Resynch. Attempts", "How many times to attempt sending data to desynchronized players.", - NULL, {.cvar = &cv_resynchattempts}, 0, 0}, - - {IT_STRING | IT_CVAR, "Ping Limit (ms)", "Players above the ping limit will get kicked from the server.", - NULL, {.cvar = &cv_maxping}, 0, 0}, - - {IT_STRING | IT_CVAR, "Ping Timeout (s)", "Players must be above the ping limit for this long before being kicked.", - NULL, {.cvar = &cv_pingtimeout}, 0, 0}, - - {IT_STRING | IT_CVAR, "Connection Timeout (tics)", "Players not giving any netowrk activity for this long are kicked.", - NULL, {.cvar = &cv_nettimeout}, 0, 0}, - - {IT_STRING | IT_CVAR, "Join Timeout (tics)", "Players taking too long to join are kicked.", - NULL, {.cvar = &cv_jointimeout}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Max File Transfer", "Maximum size of the files that can be downloaded from joining clients. (KB)", - NULL, {.cvar = &cv_maxsend}, 0, 0}, - - {IT_STRING | IT_CVAR, "File Transfer Speed", "File transfer packet rate. Larger values send more data.", - NULL, {.cvar = &cv_downloadspeed}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Log Joiner IPs", "Shows the IP of connecting players.", - NULL, {.cvar = &cv_showjoinaddress}, 0, 0}, - - {IT_STRING | IT_CVAR, "Log Resynch", "Shows which players need resynchronization.", - NULL, {.cvar = &cv_blamecfail}, 0, 0}, - - {IT_STRING | IT_CVAR, "Log Transfers", "Shows when clients are downloading files from you.", - NULL, {.cvar = &cv_noticedownload}, 0, 0}, -}; - -menu_t OPTIONS_ServerAdvancedDef = { - sizeof (OPTIONS_ServerAdvanced) / sizeof (menuitem_t), - &OPTIONS_ServerDef, - 0, - OPTIONS_ServerAdvanced, - 48, 70, // This menu here is slightly higher because there's a lot of options... - SKINCOLOR_VIOLET, 0, - 2, 5, - M_DrawGenericOptions, - M_OptionsTick, - NULL, - NULL, - NULL, -}; - -// data options menu -- see dopt_e -menuitem_t OPTIONS_Data[] = -{ - - {IT_STRING | IT_SUBMENU, "Screenshot Options...", "Set options relative to screenshot and GIF capture.", - NULL, {.submenu = &OPTIONS_DataScreenshotDef}, 0, 0}, - - {IT_STRING | IT_SUBMENU, "Addon Options...", "Set options relative to the addons menu.", - NULL, {.submenu = &OPTIONS_DataAddonDef}, 0, 0}, - - {IT_STRING | IT_SUBMENU, "Replay Options...", "Set options relative to replays.", - NULL, {.submenu = &OPTIONS_DataReplayDef}, 0, 0}, - -#ifdef HAVE_DISCORDRPC - {IT_STRING | IT_SUBMENU, "Discord Options...", "Set options relative to Discord Rich Presence.", - NULL, {.submenu = &OPTIONS_DataDiscordDef}, 0, 0}, -#endif - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_SUBMENU, "\x85""Erase Data...", "Erase specific data. Be careful, what's deleted is gone forever!", - NULL, {.submenu = &OPTIONS_DataEraseDef}, 0, 0}, - -}; - -menu_t OPTIONS_DataDef = { - sizeof (OPTIONS_Data) / sizeof (menuitem_t), - &OPTIONS_MainDef, - 0, - OPTIONS_Data, - 48, 80, - SKINCOLOR_BLUEBERRY, 0, - 2, 5, - M_DrawGenericOptions, - M_OptionsTick, - NULL, - NULL, - NULL, -}; - -menuitem_t OPTIONS_DataAddon[] = -{ - - {IT_HEADER, "MENU", NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Location", "Where to start searching addons from in the menu.", - NULL, {.cvar = &cv_addons_option}, 0, 0}, - - {IT_STRING | IT_CVAR | IT_CV_STRING, "Custom Folder", "Specify which folder to start searching from if the location is set to custom.", - NULL, {.cvar = &cv_addons_folder}, 24, 0}, - - {IT_STRING | IT_CVAR, "Identify Addons via", "Set whether to consider the extension or contents of a file.", - NULL, {.cvar = &cv_addons_md5}, 0, 0}, - - {IT_STRING | IT_CVAR, "Show Unsupported Files", "Sets whether non-addon files should be shown.", - NULL, {.cvar = &cv_addons_showall}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_HEADER, "SEARCH", NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Matching", "Set where to check for the text pattern when looking up addons via name.", - NULL, {.cvar = &cv_addons_search_type}, 0, 0}, - - {IT_STRING | IT_CVAR, "Case Sensitivity", "Set whether to consider the case when searching for addons..", - NULL, {.cvar = &cv_addons_search_case}, 0, 0}, - -}; - -menu_t OPTIONS_DataAddonDef = { - sizeof (OPTIONS_DataAddon) / sizeof (menuitem_t), - &OPTIONS_DataDef, - 0, - OPTIONS_DataAddon, - 48, 80, - SKINCOLOR_BLUEBERRY, 0, - 2, 5, - M_DrawGenericOptions, - M_OptionsTick, - NULL, - NULL, - NULL, -}; - -menuitem_t OPTIONS_DataScreenshot[] = -{ - - {IT_HEADER, "SCREENSHOTS (F8)", NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Storage Location", "Sets where to store screenshots.", - NULL, {.cvar = &cv_screenshot_option}, 0, 0}, - - {IT_STRING | IT_CVAR | IT_CV_STRING, "Custom Folder", "Specify which folder to save screenshots in.", - NULL, {.cvar = &cv_screenshot_folder}, 24, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_HEADER, "GIF RECORDING (F9)", NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Storage Location", "Sets where to store GIFs", - NULL, {.cvar = &cv_movie_option}, 0, 0}, - - {IT_STRING | IT_CVAR | IT_CV_STRING, "Custom Folder", "Specify which folder to save GIFs in.", - NULL, {.cvar = &cv_movie_folder}, 24, 0}, - -}; - -menu_t OPTIONS_DataScreenshotDef = { - sizeof (OPTIONS_DataScreenshot) / sizeof (menuitem_t), - &OPTIONS_DataDef, - 0, - OPTIONS_DataScreenshot, - 48, 80, - SKINCOLOR_BLUEBERRY, 0, - 2, 5, - M_DrawGenericOptions, - M_OptionsTick, - NULL, - NULL, - NULL, -}; - -menuitem_t OPTIONS_DataReplay[] = -{ - {IT_STRING | IT_CVAR, "Record Replays", "Select when to save replays.", - NULL, {.cvar = &cv_recordmultiplayerdemos}, 0, 0}, - - {IT_STRING | IT_CVAR, "Synch. Check Interval", "How often to check for synchronization while playing back a replay.", - NULL, {.cvar = &cv_netdemosyncquality}, 0, 0}, -}; - -menu_t OPTIONS_DataReplayDef = { - sizeof (OPTIONS_DataReplay) / sizeof (menuitem_t), - &OPTIONS_DataDef, - 0, - OPTIONS_DataReplay, - 48, 80, - SKINCOLOR_BLUEBERRY, 0, - 2, 5, - M_DrawGenericOptions, - M_OptionsTick, - NULL, - NULL, - NULL, -}; - -#ifdef HAVE_DISCORDRPC -menuitem_t OPTIONS_DataDiscord[] = -{ - {IT_STRING | IT_CVAR, "Rich Presence", "Allow Discord to display game info on your status.", - NULL, {.cvar = &cv_discordrp}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_HEADER, "RICH PRESENCE SETTINGS", NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Streamer Mode", "Prevents the logging of some account information such as your tag in the console.", - NULL, {.cvar = &cv_discordstreamer}, 0, 0}, - - {IT_STRING | IT_CVAR, "Allow Ask to Join", "Allow other people to request joining your game from Discord.", - NULL, {.cvar = &cv_discordasks}, 0, 0}, - - {IT_STRING | IT_CVAR, "Allow Invites", "Set who is allowed to generate Discord invites to your game.", - NULL, {.cvar = &cv_discordinvites}, 0, 0}, - -}; - -menu_t OPTIONS_DataDiscordDef = { - sizeof (OPTIONS_DataDiscord) / sizeof (menuitem_t), - &OPTIONS_DataDef, - 0, - OPTIONS_DataDiscord, - 48, 80, - SKINCOLOR_BLUEBERRY, 0, - 2, 5, - M_DrawGenericOptions, - M_OptionsTick, - NULL, - NULL, - NULL, -}; -#endif - - -menuitem_t OPTIONS_DataErase[] = -{ - - {IT_STRING | IT_CALL, "Erase Time Attack Data", "Be careful! What's deleted is gone forever!", - NULL, {.routine = M_EraseData}, 0, 0}, - - {IT_STRING | IT_CALL, "Erase Unlockable Data", "Be careful! What's deleted is gone forever!", - NULL, {.routine = M_EraseData}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CALL, "Erase Profile Data...", "Select a Profile to erase.", - NULL, {.routine = M_CheckProfileData}, 0, 0}, - - {IT_SPACE | IT_NOTHING, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CALL, "\x85\x45rase all Data", "Be careful! What's deleted is gone forever!", - NULL, {.routine = M_EraseData}, 0, 0}, - -}; - -menu_t OPTIONS_DataEraseDef = { - sizeof (OPTIONS_DataErase) / sizeof (menuitem_t), - &OPTIONS_DataDef, - 0, - OPTIONS_DataErase, - 48, 80, - SKINCOLOR_BLUEBERRY, 0, - 2, 5, - M_DrawGenericOptions, - M_OptionsTick, - NULL, - NULL, - NULL, -}; - -menuitem_t OPTIONS_DataProfileErase[] = -{ - {IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, {.routine = M_HandleProfileErase}, 0, 0}, -}; - -menu_t OPTIONS_DataProfileEraseDef = { - sizeof (OPTIONS_DataProfileErase) / sizeof (menuitem_t), - &OPTIONS_DataEraseDef, - 0, - OPTIONS_DataProfileErase, - 48, 80, - SKINCOLOR_BLUEBERRY, 0, - 2, 5, - M_DrawProfileErase, - M_OptionsTick, - NULL, - NULL, - NULL -}; - -// extras menu -menuitem_t EXTRAS_Main[] = -{ - - {IT_STRING | IT_CALL, "Addons", "Add files to customize your experience.", - NULL, {.routine = M_Addons}, 0, 0}, - - {IT_STRING | IT_CALL, "Challenges", "View the requirements for some of the secret content you can unlock!", - NULL, {.routine = M_Challenges}, 0, 0}, - - {IT_STRING | IT_CALL, "Replay Hut", "Play the replays you've saved throughout your many races & battles!", - NULL, {.routine = M_ReplayHut}, 0, 0}, - - {IT_STRING | IT_CALL, "Statistics", "Look back on some of your greatest achievements such as your playtime and wins!", - NULL, {.routine = M_Statistics}, 0, 0}, -}; - -// the extras menu essentially reuses the options menu stuff -menu_t EXTRAS_MainDef = { - sizeof (EXTRAS_Main) / sizeof (menuitem_t), - &MainDef, - 0, - EXTRAS_Main, - 0, 0, - 0, 0, - 2, 5, - M_DrawExtras, - M_ExtrasTick, - NULL, - NULL, - M_ExtrasInputs -}; - -// extras menu: replay hut -menuitem_t EXTRAS_ReplayHut[] = -{ - {IT_KEYHANDLER|IT_NOTHING, "", "", // Dummy menuitem for the replay list - NULL, {.routine = M_HandleReplayHutList}, 0, 0}, - - {IT_NOTHING, "", "", // Dummy for handling wrapping to the top of the menu.. - NULL, {NULL}, 0, 0}, -}; - -menu_t EXTRAS_ReplayHutDef = -{ - sizeof (EXTRAS_ReplayHut)/sizeof (menuitem_t), - &EXTRAS_MainDef, - 0, - EXTRAS_ReplayHut, - 30, 80, - 0, 0, - 0, 0, - M_DrawReplayHut, - NULL, - NULL, - M_QuitReplayHut, - NULL -}; - -menuitem_t EXTRAS_ReplayStart[] = -{ - {IT_CALL |IT_STRING, "Load Addons and Watch", NULL, - NULL, {.routine = M_HutStartReplay}, 0, 0}, - - {IT_CALL |IT_STRING, "Load Without Addons", NULL, - NULL, {.routine = M_HutStartReplay}, 10, 0}, - - {IT_CALL |IT_STRING, "Watch Replay", NULL, - NULL, {.routine = M_HutStartReplay}, 10, 0}, - - {IT_SUBMENU |IT_STRING, "Go Back", NULL, - NULL, {.submenu = &EXTRAS_ReplayHutDef}, 30, 0}, -}; - - -menu_t EXTRAS_ReplayStartDef = -{ - sizeof (EXTRAS_ReplayStart)/sizeof (menuitem_t), - &EXTRAS_ReplayHutDef, - 0, - EXTRAS_ReplayStart, - 27, 80, - 0, 0, - 0, 0, - M_DrawReplayStartMenu, - NULL, - NULL, - NULL, - NULL -}; - -// ------------------- -// In-game/pause menus -// ------------------- - -// ESC pause menu -// Since there's no descriptions to each item, we'll use the descriptions as the names of the patches we want to draw for each option :) - -menuitem_t PAUSE_Main[] = -{ - - {IT_STRING | IT_CALL, "ADDONS", "M_ICOADD", - NULL, {.routine = M_Addons}, 0, 0}, - - {IT_STRING | IT_KEYHANDLER, "GAMETYPE", "M_ICOGAM", - NULL, {.routine = M_HandlePauseMenuGametype}, 0, 0}, - - {IT_STRING | IT_CALL, "CHANGE MAP", "M_ICOMAP", - NULL, {.routine = M_LevelSelectInit}, 0, -1}, - - {IT_STRING | IT_CALL, "RESTART MAP", "M_ICORE", - NULL, {.routine = M_RestartMap}, 0, 0}, - - {IT_STRING | IT_CALL, "TRY AGAIN", "M_ICORE", - NULL, {.routine = M_TryAgain}, 0, 0}, - -#ifdef HAVE_DISCORDRPC - {IT_STRING | IT_CALL, "DISCORD REQUESTS", "M_ICODIS", - NULL, {NULL}, 0, 0}, -#endif - - {IT_STRING | IT_CALL, "RESUME GAME", "M_ICOUNP", - NULL, {.routine = M_QuitPauseMenu}, 0, 0}, - - {IT_STRING | IT_CALL, "SPECTATE", "M_ICOSPC", - NULL, {.routine = M_ConfirmSpectate}, 0, 0}, - - {IT_STRING | IT_CALL, "ENTER GAME", "M_ICOENT", - NULL, {.routine = M_ConfirmEnterGame}, 0, 0}, - - {IT_STRING | IT_CALL, "CANCEL JOIN", "M_ICOSPC", - NULL, {.routine = M_ConfirmSpectate}, 0, 0}, - - {IT_STRING | IT_SUBMENU, "JOIN OR SPECTATE", "M_ICOENT", - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CALL, "PLAYER SETUP", "M_ICOCHR", - NULL, {.routine = M_CharacterSelect}, 0, 0}, - - {IT_STRING | IT_CALL, "OPTIONS", "M_ICOOPT", - NULL, {.routine = M_InitOptions}, 0, 0}, - - {IT_STRING | IT_CALL, "EXIT GAME", "M_ICOEXT", - NULL, {.routine = M_EndGame}, 0, 0}, -}; - -menu_t PAUSE_MainDef = { - sizeof (PAUSE_Main) / sizeof (menuitem_t), - NULL, - 0, - PAUSE_Main, - 0, 0, - 0, 0, - 1, 10, // For transition with some menus! - M_DrawPause, - M_PauseTick, - NULL, - NULL, - M_PauseInputs -}; - -// Replay popup menu -menuitem_t PAUSE_PlaybackMenu[] = -{ - {IT_CALL | IT_STRING, "Hide Menu (Esc)", NULL, "M_PHIDE", {.routine = M_SelectableClearMenus}, 0, 0}, - - {IT_CALL | IT_STRING, "Rewind ([)", NULL, "M_PREW", {.routine = M_PlaybackRewind}, 20, 0}, - {IT_CALL | IT_STRING, "Pause (\\)", NULL, "M_PPAUSE", {.routine = M_PlaybackPause}, 36, 0}, - {IT_CALL | IT_STRING, "Fast-Forward (])", NULL, "M_PFFWD", {.routine = M_PlaybackFastForward}, 52, 0}, - {IT_CALL | IT_STRING, "Backup Frame ([)", NULL, "M_PSTEPB", {.routine = M_PlaybackRewind}, 20, 0}, - {IT_CALL | IT_STRING, "Resume", NULL, "M_PRESUM", {.routine = M_PlaybackPause}, 36, 0}, - {IT_CALL | IT_STRING, "Advance Frame (])", NULL, "M_PFADV", {.routine = M_PlaybackAdvance}, 52, 0}, - - {IT_ARROWS | IT_STRING, "View Count (- and =)", NULL, "M_PVIEWS", {.routine = M_PlaybackSetViews}, 72, 0}, - {IT_ARROWS | IT_STRING, "Viewpoint (1)", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 88, 0}, - {IT_ARROWS | IT_STRING, "Viewpoint 2 (2)", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 104, 0}, - {IT_ARROWS | IT_STRING, "Viewpoint 3 (3)", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 120, 0}, - {IT_ARROWS | IT_STRING, "Viewpoint 4 (4)", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 136, 0}, - - {IT_CALL | IT_STRING, "Toggle Free Camera (')", NULL, "M_PVIEWS", {.routine = M_PlaybackToggleFreecam}, 156, 0}, - {IT_CALL | IT_STRING, "Stop Playback", NULL, "M_PEXIT", {.routine = M_PlaybackQuit}, 172, 0}, -}; - -menu_t PAUSE_PlaybackMenuDef = { - sizeof (PAUSE_PlaybackMenu) / sizeof (menuitem_t), - NULL, - 0, - PAUSE_PlaybackMenu, - BASEVIDWIDTH/2 - 88, 2, - 0, 0, - 0, 0, - M_DrawPlaybackMenu, - NULL, - NULL, - NULL, - NULL -}; - - -// Other misc menus: - -// Manual -menuitem_t MISC_Manual[] = { - {IT_NOTHING | IT_KEYHANDLER, "MANUAL00", NULL, NULL, {.routine = M_HandleImageDef}, 0, 0}, - {IT_NOTHING | IT_KEYHANDLER, "MANUAL01", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, - {IT_NOTHING | IT_KEYHANDLER, "MANUAL02", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, - {IT_NOTHING | IT_KEYHANDLER, "MANUAL03", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, - {IT_NOTHING | IT_KEYHANDLER, "MANUAL04", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, - {IT_NOTHING | IT_KEYHANDLER, "MANUAL05", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, - {IT_NOTHING | IT_KEYHANDLER, "MANUAL06", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, - {IT_NOTHING | IT_KEYHANDLER, "MANUAL07", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, - {IT_NOTHING | IT_KEYHANDLER, "MANUAL08", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, - {IT_NOTHING | IT_KEYHANDLER, "MANUAL09", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, - {IT_NOTHING | IT_KEYHANDLER, "MANUAL10", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, - {IT_NOTHING | IT_KEYHANDLER, "MANUAL11", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, - {IT_NOTHING | IT_KEYHANDLER, "MANUAL12", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, - {IT_NOTHING | IT_KEYHANDLER, "MANUAL99", NULL, NULL, {.routine = M_HandleImageDef}, 0, 0}, -}; - -menu_t MISC_ManualDef = IMAGEDEF(MISC_Manual); - -// Addons menu! -menuitem_t MISC_AddonsMenu[] = -{ - {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, NULL, - NULL, {.cvar = &cv_dummyaddonsearch}, 0, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, NULL, - NULL, {.routine = M_HandleAddons}, 0, 0}, // dummy menuitem for the control func -}; - -menu_t MISC_AddonsDef = { - sizeof (MISC_AddonsMenu)/sizeof (menuitem_t), - NULL, - 0, - MISC_AddonsMenu, - 50, 28, - 0, 0, - 0, 0, - M_DrawAddons, - M_AddonsRefresh, - NULL, - NULL, - NULL -}; - -// Challenges. -menuitem_t MISC_ChallengesStatsDummyMenu[] = -{ - {IT_STRING | IT_CALL, "Back", NULL, NULL, {.routine = M_GoBack}, 0, 0}, -}; - -menu_t MISC_ChallengesDef = { - sizeof (MISC_ChallengesStatsDummyMenu)/sizeof (menuitem_t), - &MainDef, - 0, - MISC_ChallengesStatsDummyMenu, - BASEVIDWIDTH/2, 32, - 0, 0, - 98, 0, - M_DrawChallenges, - M_ChallengesTick, - NULL, - NULL, - M_ChallengesInputs, -}; - -menu_t MISC_StatisticsDef = { - sizeof (MISC_ChallengesStatsDummyMenu)/sizeof (menuitem_t), - &MainDef, - 0, - MISC_ChallengesStatsDummyMenu, - 280, 185, - 0, 0, - 98, 0, - M_DrawStatistics, - NULL, - NULL, - NULL, - M_StatisticsInputs, -}; diff --git a/src/menus/CMakeLists.txt b/src/menus/CMakeLists.txt new file mode 100644 index 000000000..43bc71147 --- /dev/null +++ b/src/menus/CMakeLists.txt @@ -0,0 +1,41 @@ +target_sources(SRB2SDL2 PRIVATE + extras-1.c + extras-addons.c + extras-challenges.c + extras-replay-hut.c + main-1.c + main-profile-select.c + options-1.c + options-data-1.c + options-data-addons.c + options-data-discord.c + options-data-erase-1.c + options-data-erase-profile.c + options-data-replays.c + options-data-screenshots.c + options-gameplay-1.c + options-gameplay-item-toggles.c + options-hud-1.c + options-hud-online.c + options-profiles-1.c + options-profiles-edit-1.c + options-profiles-edit-controls.c + options-server-1.c + options-server-advanced.c + options-sound.c + options-video-1.c + options-video-gl.c + options-video-modes.c + play-1.c + play-char-select.c + play-local-1.c + play-local-race-1.c + play-local-race-difficulty.c + play-local-race-time-attack.c + play-online-1.c + play-online-host.c + play-online-join-ip.c + play-online-server-browser.c +) + +add_subdirectory(transient) diff --git a/src/menus/extras-1.c b/src/menus/extras-1.c new file mode 100644 index 000000000..e6af1edf3 --- /dev/null +++ b/src/menus/extras-1.c @@ -0,0 +1,37 @@ +/// \file menus/extras-1.c +/// \brief Extras Menu + +#include "../k_menu.h" + +menuitem_t EXTRAS_Main[] = +{ + + {IT_STRING | IT_CALL, "Addons", "Add files to customize your experience.", + NULL, {.routine = M_Addons}, 0, 0}, + + {IT_STRING | IT_CALL, "Challenges", "View the requirements for some of the secret content you can unlock!", + NULL, {.routine = M_Challenges}, 0, 0}, + + {IT_STRING | IT_CALL, "Replay Hut", "Play the replays you've saved throughout your many races & battles!", + NULL, {.routine = M_ReplayHut}, 0, 0}, + + {IT_STRING | IT_CALL, "Statistics", "Look back on some of your greatest achievements such as your playtime and wins!", + NULL, {.routine = M_Statistics}, 0, 0}, +}; + +// the extras menu essentially reuses the options menu stuff +menu_t EXTRAS_MainDef = { + sizeof (EXTRAS_Main) / sizeof (menuitem_t), + &MainDef, + 0, + EXTRAS_Main, + 0, 0, + 0, 0, + 2, 5, + M_DrawExtras, + M_ExtrasTick, + NULL, + NULL, + M_ExtrasInputs +}; + diff --git a/src/menus/extras-addons.c b/src/menus/extras-addons.c new file mode 100644 index 000000000..b010861d3 --- /dev/null +++ b/src/menus/extras-addons.c @@ -0,0 +1,27 @@ +/// \file menus/extras-addons.c +/// \brief Addons menu! + +#include "../k_menu.h" + +menuitem_t MISC_AddonsMenu[] = +{ + {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, NULL, + NULL, {.cvar = &cv_dummyaddonsearch}, 0, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, NULL, + NULL, {.routine = M_HandleAddons}, 0, 0}, // dummy menuitem for the control func +}; + +menu_t MISC_AddonsDef = { + sizeof (MISC_AddonsMenu)/sizeof (menuitem_t), + NULL, + 0, + MISC_AddonsMenu, + 50, 28, + 0, 0, + 0, 0, + M_DrawAddons, + M_AddonsRefresh, + NULL, + NULL, + NULL +}; diff --git a/src/menus/extras-challenges.c b/src/menus/extras-challenges.c new file mode 100644 index 000000000..15c955d0e --- /dev/null +++ b/src/menus/extras-challenges.c @@ -0,0 +1,39 @@ +/// \file menus/extras-challenges.c +/// \brief Challenges. + +#include "../k_menu.h" + +menuitem_t MISC_ChallengesStatsDummyMenu[] = +{ + {IT_STRING | IT_CALL, "Back", NULL, NULL, {.routine = M_GoBack}, 0, 0}, +}; + +menu_t MISC_ChallengesDef = { + sizeof (MISC_ChallengesStatsDummyMenu)/sizeof (menuitem_t), + &MainDef, + 0, + MISC_ChallengesStatsDummyMenu, + BASEVIDWIDTH/2, 32, + 0, 0, + 98, 0, + M_DrawChallenges, + M_ChallengesTick, + NULL, + NULL, + M_ChallengesInputs, +}; + +menu_t MISC_StatisticsDef = { + sizeof (MISC_ChallengesStatsDummyMenu)/sizeof (menuitem_t), + &MainDef, + 0, + MISC_ChallengesStatsDummyMenu, + 280, 185, + 0, 0, + 98, 0, + M_DrawStatistics, + NULL, + NULL, + NULL, + M_StatisticsInputs, +}; diff --git a/src/menus/extras-replay-hut.c b/src/menus/extras-replay-hut.c new file mode 100644 index 000000000..3ba3f7e20 --- /dev/null +++ b/src/menus/extras-replay-hut.c @@ -0,0 +1,62 @@ +/// \file menus/extras-replay-hut.c +/// \brief Extras Menu: Replay Hut + +#include "../k_menu.h" + +// extras menu: replay hut +menuitem_t EXTRAS_ReplayHut[] = +{ + {IT_KEYHANDLER|IT_NOTHING, "", "", // Dummy menuitem for the replay list + NULL, {.routine = M_HandleReplayHutList}, 0, 0}, + + {IT_NOTHING, "", "", // Dummy for handling wrapping to the top of the menu.. + NULL, {NULL}, 0, 0}, +}; + +menu_t EXTRAS_ReplayHutDef = +{ + sizeof (EXTRAS_ReplayHut)/sizeof (menuitem_t), + &EXTRAS_MainDef, + 0, + EXTRAS_ReplayHut, + 30, 80, + 0, 0, + 0, 0, + M_DrawReplayHut, + NULL, + NULL, + M_QuitReplayHut, + NULL +}; + +menuitem_t EXTRAS_ReplayStart[] = +{ + {IT_CALL |IT_STRING, "Load Addons and Watch", NULL, + NULL, {.routine = M_HutStartReplay}, 0, 0}, + + {IT_CALL |IT_STRING, "Load Without Addons", NULL, + NULL, {.routine = M_HutStartReplay}, 10, 0}, + + {IT_CALL |IT_STRING, "Watch Replay", NULL, + NULL, {.routine = M_HutStartReplay}, 10, 0}, + + {IT_SUBMENU |IT_STRING, "Go Back", NULL, + NULL, {.submenu = &EXTRAS_ReplayHutDef}, 30, 0}, +}; + + +menu_t EXTRAS_ReplayStartDef = +{ + sizeof (EXTRAS_ReplayStart)/sizeof (menuitem_t), + &EXTRAS_ReplayHutDef, + 0, + EXTRAS_ReplayStart, + 27, 80, + 0, 0, + 0, 0, + M_DrawReplayStartMenu, + NULL, + NULL, + NULL, + NULL +}; diff --git a/src/menus/main-1.c b/src/menus/main-1.c new file mode 100644 index 000000000..ea337e3f3 --- /dev/null +++ b/src/menus/main-1.c @@ -0,0 +1,34 @@ +/// \file menus/main-1.c +/// \brief Main Menu + +// ========================================================================== +// ORGANIZATION START. +// ========================================================================== +// Note: Never should we be jumping from one category of menu options to another +// without first going to the Main Menu. +// Note: Ignore the above if you're working with the Pause menu. +// Note: (Prefix)_MainMenu should be the target of all Main Menu options that +// point to submenus. + +#include "../k_menu.h" + +menuitem_t MainMenu[] = +{ + {IT_STRING | IT_CALL, "Play", + "Cut to the chase and start the race!", NULL, + {.routine = M_CharacterSelect}, 0, 0}, + + {IT_STRING | IT_CALL, "Extras", + "Check out some bonus features.", "MENUI001", + {.routine = M_InitExtras}, 0, 0}, + + {IT_STRING, "Options", + "Configure your controls, settings, and preferences.", NULL, + {.routine = M_InitOptions}, 0, 0}, + + {IT_STRING | IT_CALL, "Quit", + "Exit \"Dr. Robotnik's Ring Racers\".", NULL, + {.routine = M_QuitSRB2}, 0, 0}, +}; + +menu_t MainDef = KARTGAMEMODEMENU(MainMenu, NULL); diff --git a/src/menus/main-profile-select.c b/src/menus/main-profile-select.c new file mode 100644 index 000000000..1f1154db6 --- /dev/null +++ b/src/menus/main-profile-select.c @@ -0,0 +1,24 @@ +/// \file menus/main-profile-select.c +/// \brief Duplicate for main profile select. + +#include "../k_menu.h" + +menuitem_t MAIN_Profiles[] = { + {IT_KEYHANDLER | IT_NOTHING, NULL, "Select a profile to use or create a new Profile.", + NULL, {.routine = M_HandleProfileSelect}, 0, 0}, // dummy menuitem for the control func +}; + +menu_t MAIN_ProfilesDef = { + sizeof (MAIN_Profiles) / sizeof (menuitem_t), + NULL, + 0, + MAIN_Profiles, + 32, 80, + SKINCOLOR_ULTRAMARINE, 0, + 2, 5, + M_DrawProfileSelect, + M_OptionsTick, + NULL, + NULL, + NULL, +}; diff --git a/src/menus/options-1.c b/src/menus/options-1.c new file mode 100644 index 000000000..6c6d12374 --- /dev/null +++ b/src/menus/options-1.c @@ -0,0 +1,49 @@ +/// \file menus/options-1.c +/// \brief Options Menu + +#include "../k_menu.h" + +// options menu -- see mopt_e +menuitem_t OPTIONS_Main[] = +{ + + {IT_STRING | IT_CALL, "Profile Setup", "Remap keys & buttons to your likings.", + NULL, {.routine = M_ProfileSelectInit}, 0, 0}, + + {IT_STRING | IT_SUBMENU, "Video Options", "Change video settings such as the resolution.", + NULL, {.submenu = &OPTIONS_VideoDef}, 0, 0}, + + {IT_STRING | IT_SUBMENU, "Sound Options", "Adjust various sound settings such as the volume.", + NULL, {.submenu = &OPTIONS_SoundDef}, 0, 0}, + + {IT_STRING | IT_SUBMENU, "HUD Options", "Options related to the Heads-Up Display.", + NULL, {.submenu = &OPTIONS_HUDDef}, 0, 0}, + + {IT_STRING | IT_SUBMENU, "Gameplay Options", "Change various game related options", + NULL, {.submenu = &OPTIONS_GameplayDef}, 0, 0}, + + {IT_STRING | IT_SUBMENU, "Server Options", "Change various specific options for your game server.", + NULL, {.submenu = &OPTIONS_ServerDef}, 0, 0}, + + {IT_STRING | IT_SUBMENU, "Data Options", "Miscellaneous data options such as the screenshot format.", + NULL, {.submenu = &OPTIONS_DataDef}, 0, 0}, + + {IT_STRING | IT_CALL, "Tricks & Secrets", "Those who bother reading a game manual always get the edge over those who don't!", + NULL, {.routine = M_Manual}, 0, 0}, +}; + +// For options menu, the 'extra1' field will determine the background colour to use for... the background! (What a concept!) +menu_t OPTIONS_MainDef = { + sizeof (OPTIONS_Main) / sizeof (menuitem_t), + &MainDef, + 0, + OPTIONS_Main, + 0, 0, + SKINCOLOR_SLATE, 0, + 2, 5, + M_DrawOptions, + M_OptionsTick, + NULL, + NULL, + M_OptionsInputs +}; diff --git a/src/menus/options-data-1.c b/src/menus/options-data-1.c new file mode 100644 index 000000000..a4bd7b685 --- /dev/null +++ b/src/menus/options-data-1.c @@ -0,0 +1,45 @@ +/// \file menus/options-data-1.c +/// \brief Data Options -- see dopt_e + +#include "../k_menu.h" + +// data options menu -- see dopt_e +menuitem_t OPTIONS_Data[] = +{ + + {IT_STRING | IT_SUBMENU, "Screenshot Options...", "Set options relative to screenshot and GIF capture.", + NULL, {.submenu = &OPTIONS_DataScreenshotDef}, 0, 0}, + + {IT_STRING | IT_SUBMENU, "Addon Options...", "Set options relative to the addons menu.", + NULL, {.submenu = &OPTIONS_DataAddonDef}, 0, 0}, + + {IT_STRING | IT_SUBMENU, "Replay Options...", "Set options relative to replays.", + NULL, {.submenu = &OPTIONS_DataReplayDef}, 0, 0}, + +#ifdef HAVE_DISCORDRPC + {IT_STRING | IT_SUBMENU, "Discord Options...", "Set options relative to Discord Rich Presence.", + NULL, {.submenu = &OPTIONS_DataDiscordDef}, 0, 0}, +#endif + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_SUBMENU, "\x85""Erase Data...", "Erase specific data. Be careful, what's deleted is gone forever!", + NULL, {.submenu = &OPTIONS_DataEraseDef}, 0, 0}, + +}; + +menu_t OPTIONS_DataDef = { + sizeof (OPTIONS_Data) / sizeof (menuitem_t), + &OPTIONS_MainDef, + 0, + OPTIONS_Data, + 48, 80, + SKINCOLOR_BLUEBERRY, 0, + 2, 5, + M_DrawGenericOptions, + M_OptionsTick, + NULL, + NULL, + NULL, +}; diff --git a/src/menus/options-data-addons.c b/src/menus/options-data-addons.c new file mode 100644 index 000000000..8b6cce96a --- /dev/null +++ b/src/menus/options-data-addons.c @@ -0,0 +1,53 @@ +/// \file menus/options-data-addons.c +/// \brief Addon Options + +#include "../k_menu.h" +#include "../filesrch.h" // addons cvars + +menuitem_t OPTIONS_DataAddon[] = +{ + + {IT_HEADER, "MENU", NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Location", "Where to start searching addons from in the menu.", + NULL, {.cvar = &cv_addons_option}, 0, 0}, + + {IT_STRING | IT_CVAR | IT_CV_STRING, "Custom Folder", "Specify which folder to start searching from if the location is set to custom.", + NULL, {.cvar = &cv_addons_folder}, 24, 0}, + + {IT_STRING | IT_CVAR, "Identify Addons via", "Set whether to consider the extension or contents of a file.", + NULL, {.cvar = &cv_addons_md5}, 0, 0}, + + {IT_STRING | IT_CVAR, "Show Unsupported Files", "Sets whether non-addon files should be shown.", + NULL, {.cvar = &cv_addons_showall}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_HEADER, "SEARCH", NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Matching", "Set where to check for the text pattern when looking up addons via name.", + NULL, {.cvar = &cv_addons_search_type}, 0, 0}, + + {IT_STRING | IT_CVAR, "Case Sensitivity", "Set whether to consider the case when searching for addons..", + NULL, {.cvar = &cv_addons_search_case}, 0, 0}, + +}; + +menu_t OPTIONS_DataAddonDef = { + sizeof (OPTIONS_DataAddon) / sizeof (menuitem_t), + &OPTIONS_DataDef, + 0, + OPTIONS_DataAddon, + 48, 80, + SKINCOLOR_BLUEBERRY, 0, + 2, 5, + M_DrawGenericOptions, + M_OptionsTick, + NULL, + NULL, + NULL, +}; + diff --git a/src/menus/options-data-discord.c b/src/menus/options-data-discord.c new file mode 100644 index 000000000..6ee635d4b --- /dev/null +++ b/src/menus/options-data-discord.c @@ -0,0 +1,42 @@ +/// \file menus/options-data-discord.c +/// \brief Discord Rich Presence Options + +#include "../k_menu.h" +#include "../discord.h" // discord rpc cvars + +menuitem_t OPTIONS_DataDiscord[] = +{ + {IT_STRING | IT_CVAR, "Rich Presence", "Allow Discord to display game info on your status.", + NULL, {.cvar = &cv_discordrp}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_HEADER, "RICH PRESENCE SETTINGS", NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Streamer Mode", "Prevents the logging of some account information such as your tag in the console.", + NULL, {.cvar = &cv_discordstreamer}, 0, 0}, + + {IT_STRING | IT_CVAR, "Allow Ask to Join", "Allow other people to request joining your game from Discord.", + NULL, {.cvar = &cv_discordasks}, 0, 0}, + + {IT_STRING | IT_CVAR, "Allow Invites", "Set who is allowed to generate Discord invites to your game.", + NULL, {.cvar = &cv_discordinvites}, 0, 0}, + +}; + +menu_t OPTIONS_DataDiscordDef = { + sizeof (OPTIONS_DataDiscord) / sizeof (menuitem_t), + &OPTIONS_DataDef, + 0, + OPTIONS_DataDiscord, + 48, 80, + SKINCOLOR_BLUEBERRY, 0, + 2, 5, + M_DrawGenericOptions, + M_OptionsTick, + NULL, + NULL, + NULL, +}; diff --git a/src/menus/options-data-erase-1.c b/src/menus/options-data-erase-1.c new file mode 100644 index 000000000..8be6deff0 --- /dev/null +++ b/src/menus/options-data-erase-1.c @@ -0,0 +1,42 @@ +/// \file menus/options-data-erase-1.c +/// \brief Erase Data Menu + +#include "../k_menu.h" + +menuitem_t OPTIONS_DataErase[] = +{ + + {IT_STRING | IT_CALL, "Erase Time Attack Data", "Be careful! What's deleted is gone forever!", + NULL, {.routine = M_EraseData}, 0, 0}, + + {IT_STRING | IT_CALL, "Erase Unlockable Data", "Be careful! What's deleted is gone forever!", + NULL, {.routine = M_EraseData}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CALL, "Erase Profile Data...", "Select a Profile to erase.", + NULL, {.routine = M_CheckProfileData}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CALL, "\x85\x45rase all Data", "Be careful! What's deleted is gone forever!", + NULL, {.routine = M_EraseData}, 0, 0}, + +}; + +menu_t OPTIONS_DataEraseDef = { + sizeof (OPTIONS_DataErase) / sizeof (menuitem_t), + &OPTIONS_DataDef, + 0, + OPTIONS_DataErase, + 48, 80, + SKINCOLOR_BLUEBERRY, 0, + 2, 5, + M_DrawGenericOptions, + M_OptionsTick, + NULL, + NULL, + NULL, +}; diff --git a/src/menus/options-data-erase-profile.c b/src/menus/options-data-erase-profile.c new file mode 100644 index 000000000..87e4e95cc --- /dev/null +++ b/src/menus/options-data-erase-profile.c @@ -0,0 +1,24 @@ +/// \file menus/options-data-erase-profile.c +/// \brief Erase Profile Menu + +#include "../k_menu.h" + +menuitem_t OPTIONS_DataProfileErase[] = +{ + {IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, {.routine = M_HandleProfileErase}, 0, 0}, +}; + +menu_t OPTIONS_DataProfileEraseDef = { + sizeof (OPTIONS_DataProfileErase) / sizeof (menuitem_t), + &OPTIONS_DataEraseDef, + 0, + OPTIONS_DataProfileErase, + 48, 80, + SKINCOLOR_BLUEBERRY, 0, + 2, 5, + M_DrawProfileErase, + M_OptionsTick, + NULL, + NULL, + NULL +}; diff --git a/src/menus/options-data-replays.c b/src/menus/options-data-replays.c new file mode 100644 index 000000000..507f1c8ea --- /dev/null +++ b/src/menus/options-data-replays.c @@ -0,0 +1,28 @@ +/// \file menus/options-data-replays.c +/// \brief Replay Options + +#include "../k_menu.h" + +menuitem_t OPTIONS_DataReplay[] = +{ + {IT_STRING | IT_CVAR, "Record Replays", "Select when to save replays.", + NULL, {.cvar = &cv_recordmultiplayerdemos}, 0, 0}, + + {IT_STRING | IT_CVAR, "Synch. Check Interval", "How often to check for synchronization while playing back a replay.", + NULL, {.cvar = &cv_netdemosyncquality}, 0, 0}, +}; + +menu_t OPTIONS_DataReplayDef = { + sizeof (OPTIONS_DataReplay) / sizeof (menuitem_t), + &OPTIONS_DataDef, + 0, + OPTIONS_DataReplay, + 48, 80, + SKINCOLOR_BLUEBERRY, 0, + 2, 5, + M_DrawGenericOptions, + M_OptionsTick, + NULL, + NULL, + NULL, +}; diff --git a/src/menus/options-data-screenshots.c b/src/menus/options-data-screenshots.c new file mode 100644 index 000000000..a24dea49c --- /dev/null +++ b/src/menus/options-data-screenshots.c @@ -0,0 +1,46 @@ +/// \file menus/options-data-screenshots.c +/// \brief Screeshot Options + +#include "../k_menu.h" +#include "../m_misc.h" // screenshot cvars + +menuitem_t OPTIONS_DataScreenshot[] = +{ + + {IT_HEADER, "SCREENSHOTS (F8)", NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Storage Location", "Sets where to store screenshots.", + NULL, {.cvar = &cv_screenshot_option}, 0, 0}, + + {IT_STRING | IT_CVAR | IT_CV_STRING, "Custom Folder", "Specify which folder to save screenshots in.", + NULL, {.cvar = &cv_screenshot_folder}, 24, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_HEADER, "GIF RECORDING (F9)", NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Storage Location", "Sets where to store GIFs", + NULL, {.cvar = &cv_movie_option}, 0, 0}, + + {IT_STRING | IT_CVAR | IT_CV_STRING, "Custom Folder", "Specify which folder to save GIFs in.", + NULL, {.cvar = &cv_movie_folder}, 24, 0}, + +}; + +menu_t OPTIONS_DataScreenshotDef = { + sizeof (OPTIONS_DataScreenshot) / sizeof (menuitem_t), + &OPTIONS_DataDef, + 0, + OPTIONS_DataScreenshot, + 48, 80, + SKINCOLOR_BLUEBERRY, 0, + 2, 5, + M_DrawGenericOptions, + M_OptionsTick, + NULL, + NULL, + NULL, +}; diff --git a/src/menus/options-gameplay-1.c b/src/menus/options-gameplay-1.c new file mode 100644 index 000000000..75606e4bd --- /dev/null +++ b/src/menus/options-gameplay-1.c @@ -0,0 +1,60 @@ +/// \file menus/options-gameplay-1.c +/// \brief Gameplay Options -- see gopt_e + +#include "../k_menu.h" + +menuitem_t OPTIONS_Gameplay[] = +{ + + {IT_STRING | IT_CVAR, "Game Speed", "Change Game Speed for the next map.", + NULL, {.cvar = &cv_kartspeed}, 0, 0}, + + {IT_STRING | IT_CVAR, "Base Lap Count", "Change how many laps must be completed per race.", + NULL, {.cvar = &cv_numlaps}, 0, 0}, + + {IT_STRING | IT_CVAR, "Frantic Items", "Make item odds crazier with more powerful items!", + NULL, {.cvar = &cv_kartfrantic}, 0, 0}, + + {IT_STRING | IT_CVAR, "Encore Mode", "Forces Encore Mode on for the next map.", + NULL, {.cvar = &cv_kartencore}, 0, 0}, + + {IT_STRING | IT_CVAR, "Exit Countdown", "How long players have to finish after 1st place finishes.", + NULL, {.cvar = &cv_countdowntime}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Time Limit", "Change the time limit for Battle rounds.", + NULL, {.cvar = &cv_timelimit}, 0, 0}, + + {IT_STRING | IT_CVAR, "Starting Bumpers", "Change how many bumpers player start with in Battle.", + NULL, {.cvar = &cv_kartbumpers}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Minimum Input Delay", "Practice for online play! Higher = more delay.", + NULL, {.cvar = &cv_mindelay}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_SUBMENU, "Random Item Toggles...", "Change which items to enable for your games.", + NULL, {.submenu = &OPTIONS_GameplayItemsDef}, 0, 0}, + +}; + +menu_t OPTIONS_GameplayDef = { + sizeof (OPTIONS_Gameplay) / sizeof (menuitem_t), + &OPTIONS_MainDef, + 0, + OPTIONS_Gameplay, + 48, 80, + SKINCOLOR_SCARLET, 0, + 2, 5, + M_DrawGenericOptions, + M_OptionsTick, + NULL, + NULL, + NULL, +}; diff --git a/src/menus/options-gameplay-item-toggles.c b/src/menus/options-gameplay-item-toggles.c new file mode 100644 index 000000000..3479d5998 --- /dev/null +++ b/src/menus/options-gameplay-item-toggles.c @@ -0,0 +1,62 @@ +/// \file menus/options-gameplay-item-toggles.c +/// \brief Random Item Toggles + +#include "../k_menu.h" + +menuitem_t OPTIONS_GameplayItems[] = +{ + // Mostly handled by the drawing function. + {IT_KEYHANDLER | IT_NOTHING, NULL, "Super Rings", NULL, {.routine = M_HandleItemToggles}, KITEM_SUPERRING, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Self-Propelled Bombs", NULL, {.routine = M_HandleItemToggles}, KITEM_SPB, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Eggman Marks", NULL, {.routine = M_HandleItemToggles}, KITEM_EGGMAN, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Toggle All", NULL, {.routine = M_HandleItemToggles}, 0, 0}, + + {IT_KEYHANDLER | IT_NOTHING, NULL, "Sneakers", NULL, {.routine = M_HandleItemToggles}, KITEM_SNEAKER, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Sneakers x2", NULL, {.routine = M_HandleItemToggles}, KRITEM_DUALSNEAKER, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Sneakers x3", NULL, {.routine = M_HandleItemToggles}, KRITEM_TRIPLESNEAKER, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Rocket Sneakers", NULL, {.routine = M_HandleItemToggles}, KITEM_ROCKETSNEAKER, 0}, + + {IT_KEYHANDLER | IT_NOTHING, NULL, "Bananas", NULL, {.routine = M_HandleItemToggles}, KITEM_BANANA, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Bananas x3", NULL, {.routine = M_HandleItemToggles}, KRITEM_TRIPLEBANANA, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Proximity Mines", NULL, {.routine = M_HandleItemToggles}, KITEM_MINE, 0}, + + {IT_KEYHANDLER | IT_NOTHING, NULL, "Orbinauts", NULL, {.routine = M_HandleItemToggles}, KITEM_ORBINAUT, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Orbinauts x3", NULL, {.routine = M_HandleItemToggles}, KRITEM_TRIPLEORBINAUT, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Orbinauts x4", NULL, {.routine = M_HandleItemToggles}, KRITEM_QUADORBINAUT, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Land Mines", NULL, {.routine = M_HandleItemToggles}, KITEM_LANDMINE, 0}, + + {IT_KEYHANDLER | IT_NOTHING, NULL, "Jawz", NULL, {.routine = M_HandleItemToggles}, KITEM_JAWZ, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Jawz x2", NULL, {.routine = M_HandleItemToggles}, KRITEM_DUALJAWZ, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Ballhogs", NULL, {.routine = M_HandleItemToggles}, KITEM_BALLHOG, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Drop Targets", NULL, {.routine = M_HandleItemToggles}, KITEM_DROPTARGET, sfx_s258}, + + {IT_KEYHANDLER | IT_NOTHING, NULL, "Lightning Shields", NULL, {.routine = M_HandleItemToggles}, KITEM_LIGHTNINGSHIELD, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Bubble Shields", NULL, {.routine = M_HandleItemToggles}, KITEM_BUBBLESHIELD, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Flame Shields", NULL, {.routine = M_HandleItemToggles}, KITEM_FLAMESHIELD, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Hyudoros", NULL, {.routine = M_HandleItemToggles}, KITEM_HYUDORO, 0}, + + {IT_KEYHANDLER | IT_NOTHING, NULL, "Invinciblity", NULL, {.routine = M_HandleItemToggles}, KITEM_INVINCIBILITY, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Grow", NULL, {.routine = M_HandleItemToggles}, KITEM_GROW, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Shrink", NULL, {.routine = M_HandleItemToggles}, KITEM_SHRINK, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, NULL, NULL, {.routine = M_HandleItemToggles}, 255, 0}, + + {IT_KEYHANDLER | IT_NOTHING, NULL, "Pogo Springs", NULL, {.routine = M_HandleItemToggles}, KITEM_POGOSPRING, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Kitchen Sinks", NULL, {.routine = M_HandleItemToggles}, KITEM_KITCHENSINK, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, NULL, NULL, {.routine = M_HandleItemToggles}, 255, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, NULL, NULL, {.routine = M_HandleItemToggles}, 255, 0} +}; + +menu_t OPTIONS_GameplayItemsDef = { + sizeof (OPTIONS_GameplayItems) / sizeof (menuitem_t), + &OPTIONS_GameplayDef, + 0, + OPTIONS_GameplayItems, + 14, 40, + SKINCOLOR_SCARLET, 0, + 2, 5, + M_DrawItemToggles, + M_OptionsTick, + NULL, + NULL, + NULL, +}; diff --git a/src/menus/options-hud-1.c b/src/menus/options-hud-1.c new file mode 100644 index 000000000..2948cd2fe --- /dev/null +++ b/src/menus/options-hud-1.c @@ -0,0 +1,57 @@ +/// \file menus/options-hud-1.c +/// \brief HUD Options + +#include "../k_menu.h" +#include "../r_main.h" // cv_showhud +#include "../v_video.h" // cv_constextsize +#include "../console.h" // console cvars + +menuitem_t OPTIONS_HUD[] = +{ + + {IT_STRING | IT_CVAR, "Show HUD (F3)", "Toggles HUD display. Great for taking screenshots!", + NULL, {.cvar = &cv_showhud}, 0, 0}, + + {IT_STRING | IT_CVAR | IT_CV_SLIDER, "HUD Opacity", "Non opaque values may have performance impacts in software mode.", + NULL, {.cvar = &cv_translucenthud}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Speedometer", "Choose to what speed unit to display or toggle off the speedometer.", + NULL, {.cvar = &cv_kartspeedometer}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Console Text Size", "Size of the text within the console.", + NULL, {.cvar = &cv_constextsize}, 0, 0}, + + // we spell words properly here. + {IT_STRING | IT_CVAR, "Console Tint", "Change the background colour of the console.", + NULL, {.cvar = &cons_backcolor}, 0, 0}, + + {IT_STRING | IT_CVAR, "Show \"FOCUS LOST\"", "Displays \"FOCUS LOST\" when the game window isn't the active window.", + NULL, {.cvar = &cv_showfocuslost}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_SUBMENU, "Online HUD Options...", "HUD options related to the online chat box and other features.", + NULL, {.submenu = &OPTIONS_HUDOnlineDef}, 0, 0}, +}; + +menu_t OPTIONS_HUDDef = { + sizeof (OPTIONS_HUD) / sizeof (menuitem_t), + &OPTIONS_MainDef, + 0, + OPTIONS_HUD, + 48, 80, + SKINCOLOR_SUNSLAM, 0, + 2, 5, + M_DrawGenericOptions, + M_OptionsTick, + NULL, + NULL, + NULL, +}; diff --git a/src/menus/options-hud-online.c b/src/menus/options-hud-online.c new file mode 100644 index 000000000..3159cc302 --- /dev/null +++ b/src/menus/options-hud-online.c @@ -0,0 +1,54 @@ +/// \file menus/options-hud-inline.c +/// \brief Online HUD Options + +#include "../k_menu.h" + +menuitem_t OPTIONS_HUDOnline[] = +{ + + {IT_STRING | IT_CVAR, "Chat Mode", "Choose whether to display chat in its own window or the console.", + NULL, {.cvar = &cv_consolechat}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Chat Box Tint", "Changes the background colour of the chat box.", + NULL, {.cvar = &cv_chatbacktint}, 0, 0}, + + {IT_STRING | IT_CVAR | IT_CV_SLIDER, "Chat Box Width", "Change the width of the Chat Box", + NULL, {.cvar = &cv_chatwidth}, 0, 0}, + + {IT_STRING | IT_CVAR | IT_CV_SLIDER, "Chat Box Height", "Change the height of the Chat Box", + NULL, {.cvar = &cv_chatheight}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Message Fadeout Time", "How long chat messages stay displayed with the chat closed.", + NULL, {.cvar = &cv_chattime}, 0, 0}, + + {IT_STRING | IT_CVAR, "Spam Protection", "Prevents too many message from a single player from being displayed.", + NULL, {.cvar = &cv_chatspamprotection}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Local Ping Display", "In netgames, displays your ping at the lower right corner of the screen.", + NULL, {.cvar = &cv_showping}, 0, 0}, + +}; + +menu_t OPTIONS_HUDOnlineDef = { + sizeof (OPTIONS_HUDOnline) / sizeof (menuitem_t), + &OPTIONS_HUDDef, + 0, + OPTIONS_HUDOnline, + 48, 80, + SKINCOLOR_SUNSLAM, 0, + 2, 5, + M_DrawGenericOptions, + M_OptionsTick, + NULL, + NULL, + NULL, +}; diff --git a/src/menus/options-profiles-1.c b/src/menus/options-profiles-1.c new file mode 100644 index 000000000..a61eb1ef5 --- /dev/null +++ b/src/menus/options-profiles-1.c @@ -0,0 +1,25 @@ +/// \file menus/options-profiles-1.c +/// \brief Profiles Menu + +#include "../k_menu.h" + +// profile select +menuitem_t OPTIONS_Profiles[] = { + {IT_KEYHANDLER | IT_NOTHING, NULL, "Select a Profile.", + NULL, {.routine = M_HandleProfileSelect}, 0, 0}, // dummy menuitem for the control func +}; + +menu_t OPTIONS_ProfilesDef = { + sizeof (OPTIONS_Profiles) / sizeof (menuitem_t), + &OPTIONS_MainDef, + 0, + OPTIONS_Profiles, + 32, 80, + SKINCOLOR_ULTRAMARINE, 0, + 2, 5, + M_DrawProfileSelect, + M_OptionsTick, + NULL, + NULL, + NULL, +}; diff --git a/src/menus/options-profiles-edit-1.c b/src/menus/options-profiles-edit-1.c new file mode 100644 index 000000000..2e9f91c17 --- /dev/null +++ b/src/menus/options-profiles-edit-1.c @@ -0,0 +1,37 @@ +/// \file menus/options-profiles-edit-1.c +/// \brief Profile Editor + +#include "../k_menu.h" + +menuitem_t OPTIONS_EditProfile[] = { + {IT_STRING | IT_CVAR | IT_CV_STRING, "Profile Name", "6-character long name to identify this Profile.", + NULL, {.cvar = &cv_dummyprofilename}, 0, 0}, + + {IT_STRING | IT_CVAR | IT_CV_STRING, "Player Name", "Name displayed online when using this Profile.", + NULL, {.cvar = &cv_dummyprofileplayername}, 0, 0}, + + {IT_STRING | IT_CALL, "Character", "Default character and color for this Profile.", + NULL, {.routine = M_CharacterSelect}, 0, 0}, + + {IT_STRING | IT_CALL, "Controls", "Select the button mappings for this Profile.", + NULL, {.routine = M_ProfileDeviceSelect}, 0, 0}, + + {IT_STRING | IT_CALL, "Confirm", "Confirm changes.", + NULL, {.routine = M_ConfirmProfile}, 0, 0}, + +}; + +menu_t OPTIONS_EditProfileDef = { + sizeof (OPTIONS_EditProfile) / sizeof (menuitem_t), + &OPTIONS_ProfilesDef, + 0, + OPTIONS_EditProfile, + 32, 80, + SKINCOLOR_ULTRAMARINE, 0, + 2, 5, + M_DrawEditProfile, + M_HandleProfileEdit, + NULL, + NULL, + M_ProfileEditInputs, +}; diff --git a/src/menus/options-profiles-edit-controls.c b/src/menus/options-profiles-edit-controls.c new file mode 100644 index 000000000..774bcdfa4 --- /dev/null +++ b/src/menus/options-profiles-edit-controls.c @@ -0,0 +1,110 @@ +/// \file menus/options-profiles-edit-controls.c +/// \brief Profile Controls Editor + +#include "../k_menu.h" + +menuitem_t OPTIONS_ProfileControls[] = { + + {IT_HEADER, "MAIN CONTROLS", "That's the stuff on the controller!!", + NULL, {NULL}, 0, 0}, + + {IT_CONTROL, "A", "Accelerate / Confirm", + "PR_BTA", {.routine = M_ProfileSetControl}, gc_a, 0}, + + {IT_CONTROL, "B", "Look backwards / Back", + "PR_BTB", {.routine = M_ProfileSetControl}, gc_b, 0}, + + {IT_CONTROL, "C", "Spindash / Extra", + "PR_BTC", {.routine = M_ProfileSetControl}, gc_c, 0}, + + {IT_CONTROL, "X", "Brake / Back", + "PR_BTX", {.routine = M_ProfileSetControl}, gc_x, 0}, + + // @TODO What does this do??? + {IT_CONTROL, "Y", "N/A ?", + "PR_BTY", {.routine = M_ProfileSetControl}, gc_y, 0}, + + {IT_CONTROL, "Z", "N/A ?", + "PR_BTZ", {.routine = M_ProfileSetControl}, gc_z, 0}, + + {IT_CONTROL, "L", "Use item", + "PR_BTL", {.routine = M_ProfileSetControl}, gc_l, 0}, + + {IT_CONTROL, "R", "Drift", + "PR_BTR", {.routine = M_ProfileSetControl}, gc_r, 0}, + + {IT_CONTROL, "Turn Left", "Turn left", + "PR_PADL", {.routine = M_ProfileSetControl}, gc_left, 0}, + + {IT_CONTROL, "Turn Right", "Turn right", + "PR_PADR", {.routine = M_ProfileSetControl}, gc_right, 0}, + + {IT_CONTROL, "Aim Forward", "Aim forwards", + "PR_PADU", {.routine = M_ProfileSetControl}, gc_up, 0}, + + {IT_CONTROL, "Aim Backwards", "Aim backwards", + "PR_PADD", {.routine = M_ProfileSetControl}, gc_down, 0}, + + {IT_CONTROL, "Start", "Open pause menu", + "PR_BTS", {.routine = M_ProfileSetControl}, gc_start, 0}, + + {IT_HEADER, "OPTIONAL CONTROLS", "Take a screenshot, chat...", + NULL, {NULL}, 0, 0}, + + {IT_CONTROL, "SCREENSHOT", "Also usable with F8 on Keyboard.", + NULL, {.routine = M_ProfileSetControl}, gc_screenshot, 0}, + + {IT_CONTROL, "GIF CAPTURE", "Also usable with F9 on Keyboard.", + NULL, {.routine = M_ProfileSetControl}, gc_recordgif, 0}, + + {IT_CONTROL, "OPEN CHAT", "Opens chatbox in online games.", + NULL, {.routine = M_ProfileSetControl}, gc_talk, 0}, + + {IT_CONTROL, "OPEN TEAM CHAT", "Do we even have team gamemodes?", + NULL, {.routine = M_ProfileSetControl}, gc_teamtalk, 0}, + + {IT_CONTROL, "SHOW RANKINGS", "Show mid-game rankings.", + NULL, {.routine = M_ProfileSetControl}, gc_rankings, 0}, + + {IT_CONTROL, "OPEN CONSOLE", "Opens the developer options console.", + NULL, {.routine = M_ProfileSetControl}, gc_console, 0}, + + {IT_CONTROL, "LUA/A", "May be used by add-ons.", + NULL, {.routine = M_ProfileSetControl}, gc_luaa, 0}, + + {IT_CONTROL, "LUA/B", "May be used by add-ons.", + NULL, {.routine = M_ProfileSetControl}, gc_luab, 0}, + + {IT_CONTROL, "LUA/C", "May be used by add-ons.", + NULL, {.routine = M_ProfileSetControl}, gc_luac, 0}, + + {IT_HEADER, "TOGGLES", "For per-player commands", + NULL, {NULL}, 0, 0}, + + {IT_CONTROL | IT_CVAR, "KICKSTART ACCEL", "Hold A to auto-accel. Tap it to cancel.", + NULL, {.cvar = &cv_dummyprofilekickstart}, 0, 0}, + + {IT_HEADER, "EXTRA", "", + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CALL, "TRY MAPPINGS", "Test your controls.", + NULL, {.routine = M_ProfileTryController}, 0, 0}, + + {IT_STRING | IT_CALL, "CONFIRM", "Go back to profile setup.", + NULL, {.routine = M_ProfileControlsConfirm}, 0, 0}, +}; + +menu_t OPTIONS_ProfileControlsDef = { + sizeof (OPTIONS_ProfileControls) / sizeof (menuitem_t), + &OPTIONS_EditProfileDef, + 0, + OPTIONS_ProfileControls, + 32, 80, + SKINCOLOR_ULTRAMARINE, 0, + 3, 5, + M_DrawProfileControls, + M_HandleProfileControls, + NULL, + NULL, + M_ProfileControlsInputs, +}; diff --git a/src/menus/options-server-1.c b/src/menus/options-server-1.c new file mode 100644 index 000000000..401a6964b --- /dev/null +++ b/src/menus/options-server-1.c @@ -0,0 +1,64 @@ +/// \file menus/options-server-1.c +/// \brief Server Options + +#include "../k_menu.h" + +menuitem_t OPTIONS_Server[] = +{ + + {IT_STRING | IT_CVAR | IT_CV_STRING, "Server Name", "Change the name of your server.", + NULL, {.cvar = &cv_servername}, 0, 0}, + + {IT_STRING | IT_CVAR, "Intermission", "Set how long to stay on the result screen.", + NULL, {.cvar = &cv_inttime}, 0, 0}, + + {IT_STRING | IT_CVAR, "Map Progression", "Set how the next map is chosen.", + NULL, {.cvar = &cv_advancemap}, 0, 0}, + + {IT_STRING | IT_CVAR, "Vote Timer", "Set how long players have to vote.", + NULL, {.cvar = &cv_votetime}, 0, 0}, + + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Maximum Players", "How many players can play at once.", + NULL, {.cvar = &cv_maxplayers}, 0, 0}, + + {IT_STRING | IT_CVAR, "Maximum Connections", "How many players & spectators can connect to the server.", + NULL, {.cvar = &cv_maxconnections}, 0, 0}, + + {IT_STRING | IT_CVAR, "Allow Joining", "Sets whether players can connect to your server.", + NULL, {.cvar = &cv_allownewplayer}, 0, 0}, + + {IT_STRING | IT_CVAR, "Allow Downloads", "Allows joiners to download missing files from you.", + NULL, {.cvar = &cv_downloading}, 0, 0}, + + {IT_STRING | IT_CVAR, "Pause Permissions", "Sets who can pause the game.", + NULL, {.cvar = &cv_pause}, 0, 0}, + + {IT_STRING | IT_CVAR, "Mute Chat", "Prevents non-admins from sending chat messages.", + NULL, {.cvar = &cv_mute}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_SUBMENU, "Advanced...", "Advanced options. Be careful when messing with these!", + NULL, {.submenu = &OPTIONS_ServerAdvancedDef}, 0, 0}, + +}; + +menu_t OPTIONS_ServerDef = { + sizeof (OPTIONS_Server) / sizeof (menuitem_t), + &OPTIONS_MainDef, + 0, + OPTIONS_Server, + 48, 70, // This menu here is slightly higher because there's a lot of options... + SKINCOLOR_VIOLET, 0, + 2, 5, + M_DrawGenericOptions, + M_OptionsTick, + NULL, + NULL, + NULL, +}; diff --git a/src/menus/options-server-advanced.c b/src/menus/options-server-advanced.c new file mode 100644 index 000000000..f8434dd62 --- /dev/null +++ b/src/menus/options-server-advanced.c @@ -0,0 +1,62 @@ +/// \file menus/options-server-advanced.c +/// \brief Advanced Server Options + +#include "../k_menu.h" + +menuitem_t OPTIONS_ServerAdvanced[] = +{ + + {IT_STRING | IT_CVAR | IT_CV_STRING, "Server Browser Address", "Default is \'https://ms.kartkrew.org/ms/api\'", + NULL, {.cvar = &cv_masterserver}, 0, 0}, + + {IT_STRING | IT_CVAR, "Resynch. Attempts", "How many times to attempt sending data to desynchronized players.", + NULL, {.cvar = &cv_resynchattempts}, 0, 0}, + + {IT_STRING | IT_CVAR, "Ping Limit (ms)", "Players above the ping limit will get kicked from the server.", + NULL, {.cvar = &cv_maxping}, 0, 0}, + + {IT_STRING | IT_CVAR, "Ping Timeout (s)", "Players must be above the ping limit for this long before being kicked.", + NULL, {.cvar = &cv_pingtimeout}, 0, 0}, + + {IT_STRING | IT_CVAR, "Connection Timeout (tics)", "Players not giving any netowrk activity for this long are kicked.", + NULL, {.cvar = &cv_nettimeout}, 0, 0}, + + {IT_STRING | IT_CVAR, "Join Timeout (tics)", "Players taking too long to join are kicked.", + NULL, {.cvar = &cv_jointimeout}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Max File Transfer", "Maximum size of the files that can be downloaded from joining clients. (KB)", + NULL, {.cvar = &cv_maxsend}, 0, 0}, + + {IT_STRING | IT_CVAR, "File Transfer Speed", "File transfer packet rate. Larger values send more data.", + NULL, {.cvar = &cv_downloadspeed}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Log Joiner IPs", "Shows the IP of connecting players.", + NULL, {.cvar = &cv_showjoinaddress}, 0, 0}, + + {IT_STRING | IT_CVAR, "Log Resynch", "Shows which players need resynchronization.", + NULL, {.cvar = &cv_blamecfail}, 0, 0}, + + {IT_STRING | IT_CVAR, "Log Transfers", "Shows when clients are downloading files from you.", + NULL, {.cvar = &cv_noticedownload}, 0, 0}, +}; + +menu_t OPTIONS_ServerAdvancedDef = { + sizeof (OPTIONS_ServerAdvanced) / sizeof (menuitem_t), + &OPTIONS_ServerDef, + 0, + OPTIONS_ServerAdvanced, + 48, 70, // This menu here is slightly higher because there's a lot of options... + SKINCOLOR_VIOLET, 0, + 2, 5, + M_DrawGenericOptions, + M_OptionsTick, + NULL, + NULL, + NULL, +}; diff --git a/src/menus/options-sound.c b/src/menus/options-sound.c new file mode 100644 index 000000000..636dd0f0a --- /dev/null +++ b/src/menus/options-sound.c @@ -0,0 +1,66 @@ +/// \file menus/options-sound.c +/// \brief Sound Options + +#include "../k_menu.h" +#include "../s_sound.h" // sounds consvars +#include "../g_game.h" // cv_chatnotifications + +menuitem_t OPTIONS_Sound[] = +{ + + {IT_STRING | IT_CVAR, "SFX", "Enable or disable sound effect playback.", + NULL, {.cvar = &cv_gamesounds}, 0, 0}, + + {IT_STRING | IT_CVAR | IT_CV_SLIDER, "SFX Volume", "Adjust the volume of sound effects.", + NULL, {.cvar = &cv_soundvolume}, 0, 0}, + + {IT_STRING | IT_CVAR, "Music", "Enable or disable music playback.", + NULL, {.cvar = &cv_gamedigimusic}, 0, 0}, + + {IT_STRING | IT_CVAR | IT_CV_SLIDER, "Music Volume", "Adjust the volume of music playback.", + NULL, {.cvar = &cv_digmusicvolume}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Reverse L/R Channels", "Reverse left & right channels for Stereo playback.", + NULL, {.cvar = &stereoreverse}, 0, 0}, + + {IT_STRING | IT_CVAR, "Surround", "Enables or disable Surround sound playback.", + NULL, {.cvar = &surround}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Chat Notifications", "Set when to play notification sounds when chat messages are received.", + NULL, {.cvar = &cv_chatnotifications}, 0, 0}, + + {IT_STRING | IT_CVAR, "Character Voices", "Set how often to play character voices in game.", + NULL, {.cvar = &cv_kartvoices}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Play Music While Unfocused", "Keeps playing music even if the game is not the active window.", + NULL, {.cvar = &cv_playmusicifunfocused}, 0, 0}, + + {IT_STRING | IT_CVAR, "Play SFX While Unfocused", "Keeps playing sound effects even if the game is not the active window.", + NULL, {.cvar = &cv_playsoundifunfocused}, 0, 0}, + + // @TODO: Sound test (there's currently no space on this menu, might be better to throw it in extras?) +}; + +menu_t OPTIONS_SoundDef = { + sizeof (OPTIONS_Sound) / sizeof (menuitem_t), + &OPTIONS_MainDef, + 0, + OPTIONS_Sound, + 48, 80, + SKINCOLOR_THUNDER, 0, + 2, 5, + M_DrawGenericOptions, + M_OptionsTick, + NULL, + NULL, + NULL, +}; diff --git a/src/menus/options-video-1.c b/src/menus/options-video-1.c new file mode 100644 index 000000000..3341ae2ad --- /dev/null +++ b/src/menus/options-video-1.c @@ -0,0 +1,68 @@ +/// \file menus/options-video-1.c +/// \brief Video Options + +#include "../k_menu.h" +#include "../r_main.h" // cv_skybox +#include "../v_video.h" // cv_globalgamma +#include "../r_fps.h" // fps cvars + +// options menu +menuitem_t OPTIONS_Video[] = +{ + + {IT_STRING | IT_CALL, "Set Resolution...", "Change the screen resolution for the game.", + NULL, {.routine = M_VideoModeMenu}, 0, 0}, + +// A check to see if you're not running on a fucking antique potato powered stone i guess??????? + +#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) + {IT_STRING | IT_CVAR, "Fullscreen", "Set whether you want to use fullscreen or windowed mode.", + NULL, {.cvar = &cv_fullscreen}, 0, 0}, +#endif + + {IT_NOTHING|IT_SPACE, NULL, "Kanade best waifu! I promise!", + NULL, {NULL}, 0, 0}, + + // Everytime I see a screenshot at max gamma I die inside + {IT_STRING | IT_CVAR | IT_CV_SLIDER, "Gamma", "Adjusts the overall brightness of the game.", + NULL, {.cvar = &cv_globalgamma}, 0, 0}, + + {IT_STRING | IT_CVAR, "FPS Cap", "Handles the refresh rate of the game (does not affect gamelogic).", + NULL, {.cvar = &cv_fpscap}, 0, 0}, + + {IT_STRING | IT_CVAR, "Enable Skyboxes", "Turning this off will improve performance at the detriment of visuals for many maps.", + NULL, {.cvar = &cv_skybox}, 0, 0}, + + {IT_STRING | IT_CVAR, "Draw Distance", "How far objects can be drawn. Lower values may improve performance at the cost of visibility.", + NULL, {.cvar = &cv_drawdist}, 0, 0}, + + {IT_STRING | IT_CVAR, "Weather Draw Distance", "Affects how far weather visuals can be drawn. Lower values improve performance.", + NULL, {.cvar = &cv_drawdist_precip}, 0, 0}, + + {IT_STRING | IT_CVAR, "Show FPS", "Displays the game framerate at the lower right corner of the screen.", + NULL, {.cvar = &cv_ticrate}, 0, 0}, + + {IT_NOTHING|IT_SPACE, NULL, "Kanade best waifu! I promise!", + NULL, {NULL}, 0, 0}, + +#ifdef HWRENDER + {IT_STRING | IT_SUBMENU, "Hardware Options...", "For usage and configuration of the OpenGL renderer.", + NULL, {.submenu = &OPTIONS_VideoOGLDef}, 0, 0}, +#endif + +}; + +menu_t OPTIONS_VideoDef = { + sizeof (OPTIONS_Video) / sizeof (menuitem_t), + &OPTIONS_MainDef, + 0, + OPTIONS_Video, + 32, 80, + SKINCOLOR_PLAGUE, 0, + 2, 5, + M_DrawGenericOptions, + M_OptionsTick, + NULL, + NULL, + NULL, +}; diff --git a/src/menus/options-video-gl.c b/src/menus/options-video-gl.c new file mode 100644 index 000000000..92a30f733 --- /dev/null +++ b/src/menus/options-video-gl.c @@ -0,0 +1,60 @@ +/// \file menus/options-video-gl.c +/// \brief OpenGL Options + +#include "../k_menu.h" +#include "../hardware/hw_main.h" // gl consvars + +menuitem_t OPTIONS_VideoOGL[] = +{ + + {IT_STRING | IT_CVAR, "Renderer", "Change renderers between Software and OpenGL", + NULL, {.cvar = &cv_renderer}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_HEADER, "OPTIONS BELOW ARE OPENGL ONLY!", "Watch people get confused anyway!!", + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "3D Models", "Use 3D models instead of sprites when applicable.", + NULL, {.cvar = &cv_glmodels}, 0, 0}, + + {IT_STRING | IT_CVAR, "Shaders", "Use GLSL Shaders. Turning them off increases performance at the expanse of visual quality.", + NULL, {.cvar = &cv_glshaders}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Texture Quality", "Texture depth. Higher values are recommended.", + NULL, {.cvar = &cv_scr_depth}, 0, 0}, + + {IT_STRING | IT_CVAR, "Texture Filter", "Texture Filter. Nearest is recommended.", + NULL, {.cvar = &cv_glfiltermode}, 0, 0}, + + {IT_STRING | IT_CVAR, "Anisotropic", "Lower values will improve performance at a minor quality loss.", + NULL, {.cvar = &cv_glanisotropicmode}, 0, 0}, + + {IT_SPACE | IT_NOTHING, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Sprite Billboarding", "Adjusts sprites when viewed from above or below to not make them appear flat.", + NULL, {.cvar = &cv_glspritebillboarding}, 0, 0}, + + {IT_STRING | IT_CVAR, "Software Perspective", "Emulates Software shearing when looking up or down. Not recommended.", + NULL, {.cvar = &cv_glshearing}, 0, 0}, +}; + +menu_t OPTIONS_VideoOGLDef = { + sizeof (OPTIONS_VideoOGL) / sizeof (menuitem_t), + &OPTIONS_VideoDef, + 0, + OPTIONS_VideoOGL, + 32, 80, + SKINCOLOR_PLAGUE, 0, + 2, 5, + M_DrawGenericOptions, + M_OptionsTick, + NULL, + NULL, + NULL, +}; diff --git a/src/menus/options-video-modes.c b/src/menus/options-video-modes.c new file mode 100644 index 000000000..160820abf --- /dev/null +++ b/src/menus/options-video-modes.c @@ -0,0 +1,26 @@ +/// \file menus/options-video-modes.c +/// \brief Video modes (resolutions) + +#include "../k_menu.h" + +menuitem_t OPTIONS_VideoModes[] = { + + {IT_KEYHANDLER | IT_NOTHING, NULL, "Select a resolution.", + NULL, {.routine = M_HandleVideoModes}, 0, 0}, // dummy menuitem for the control func + +}; + +menu_t OPTIONS_VideoModesDef = { + sizeof (OPTIONS_VideoModes) / sizeof (menuitem_t), + &OPTIONS_VideoDef, + 0, + OPTIONS_VideoModes, + 48, 80, + SKINCOLOR_PLAGUE, 0, + 2, 5, + M_DrawVideoModes, + M_OptionsTick, + NULL, + NULL, + NULL, +}; diff --git a/src/menus/play-1.c b/src/menus/play-1.c new file mode 100644 index 000000000..d4c8ee099 --- /dev/null +++ b/src/menus/play-1.c @@ -0,0 +1,17 @@ +/// \file menus/play-1.c +/// \brief Play Menu + +#include "../k_menu.h" + +menuitem_t PLAY_MainMenu[] = +{ + {IT_STRING | IT_CALL, "Local Play", "Play only on this computer.", + NULL, {.routine = M_SetupGametypeMenu}, 0, 0}, + + {IT_STRING | IT_CALL, "Online", "Connect to other computers.", + NULL, {.routine = M_MPOptSelectInit}, /*M_MPRoomSelectInit,*/ 0, 0}, + + {IT_STRING | IT_CALL, "Back", NULL, NULL, {.routine = M_GoBack}, 0, 0}, +}; + +menu_t PLAY_MainDef = KARTGAMEMODEMENU(PLAY_MainMenu, &PLAY_CharSelectDef); diff --git a/src/menus/play-char-select.c b/src/menus/play-char-select.c new file mode 100644 index 000000000..cf3306cca --- /dev/null +++ b/src/menus/play-char-select.c @@ -0,0 +1,24 @@ +/// \file menus/play-char-select.c +/// \brief Character Select + +#include "../k_menu.h" + +menuitem_t PLAY_CharSelect[] = +{ + {IT_NOTHING, NULL, NULL, NULL, {NULL}, 0, 0}, +}; + +menu_t PLAY_CharSelectDef = { + sizeof (PLAY_CharSelect) / sizeof (menuitem_t), + &MainDef, + 0, + PLAY_CharSelect, + 0, 0, + 0, 0, + 0, 0, + M_DrawCharacterSelect, + M_CharacterSelectTick, + M_CharacterSelectInit, + M_CharacterSelectQuit, + M_CharacterSelectHandler +}; diff --git a/src/menus/play-local-1.c b/src/menus/play-local-1.c new file mode 100644 index 000000000..6267f91b6 --- /dev/null +++ b/src/menus/play-local-1.c @@ -0,0 +1,23 @@ +/// \file menus/play-local-1.c +/// \brief Local Play, gamemode selection menu + +#include "../k_menu.h" + +menuitem_t PLAY_GamemodesMenu[] = +{ + {IT_STRING | IT_CALL, "Race", "A contest to see who's the fastest of them all!", + NULL, {.routine = M_SetupRaceMenu}, 0, 0}, + + {IT_STRING | IT_CALL, "Battle", "It's last kart standing in this free-for-all!", + "MENIMG00", {.routine = M_LevelSelectInit}, 0, GT_BATTLE}, + + {IT_STRING | IT_CALL, "Capsules", "Bust up all of the capsules in record time!", + NULL, {.routine = M_LevelSelectInit}, 1, GT_BATTLE}, + + {IT_STRING | IT_CALL, "Special", "Strike your target and secure the prize!", + NULL, {.routine = M_LevelSelectInit}, 1, GT_SPECIAL}, + + {IT_STRING | IT_CALL, "Back", NULL, NULL, {.routine = M_GoBack}, 0, 0}, +}; + +menu_t PLAY_GamemodesDef = KARTGAMEMODEMENU(PLAY_GamemodesMenu, &PLAY_MainDef); diff --git a/src/menus/play-local-race-1.c b/src/menus/play-local-race-1.c new file mode 100644 index 000000000..84faa4a8f --- /dev/null +++ b/src/menus/play-local-race-1.c @@ -0,0 +1,20 @@ +/// \file menus/play-local-race-1.c +/// \brief Race Mode Menu + +#include "../k_menu.h" + +menuitem_t PLAY_RaceGamemodesMenu[] = +{ + {IT_STRING | IT_CALL, "Grand Prix", "Compete for the best rank over five races!", + NULL, {.routine = M_SetupDifficultySelect}, 0, 0}, + + {IT_STRING | IT_CALL, "Match Race", "Play by your own rules in a specialized, single race!", + "MENIMG01", {.routine = M_SetupDifficultySelect}, 1, 0}, + + {IT_STRING | IT_CALL, "Time Attack", "Record your best time on any track!", + NULL, {.routine = M_LevelSelectInit}, 1, GT_RACE}, + + {IT_STRING | IT_CALL, "Back", NULL, NULL, {.routine = M_GoBack}, 0, 0}, +}; + +menu_t PLAY_RaceGamemodesDef = KARTGAMEMODEMENU(PLAY_RaceGamemodesMenu, &PLAY_GamemodesDef); diff --git a/src/menus/play-local-race-difficulty.c b/src/menus/play-local-race-difficulty.c new file mode 100644 index 000000000..a55ede90b --- /dev/null +++ b/src/menus/play-local-race-difficulty.c @@ -0,0 +1,47 @@ +/// \file menus/play-local-race-difficulty.c +/// \brief difficulty selection -- see drace_e + +#include "../k_menu.h" + +menuitem_t PLAY_RaceDifficulty[] = +{ + // For GP + {IT_STRING | IT_CVAR, "Difficulty", "Select the game difficulty", + NULL, {.cvar = &cv_dummygpdifficulty}, 0, 0}, + + // Match Race + {IT_STRING | IT_CVAR, "Difficulty", "Select the game speed", + NULL, {.cvar = &cv_dummykartspeed}, 0, 0}, + + // DISABLE THAT OPTION OUTSIDE OF MATCH RACE + {IT_STRING2 | IT_CVAR, "CPU", "Set the difficulty of CPU players.", + NULL, {.cvar = &cv_dummymatchbots}, 0, 0}, + {IT_STRING2 | IT_CVAR, "Racers", "Sets the number of racers, including players and CPU.", + NULL, {.cvar = &cv_maxplayers}, 0, 0}, + + {IT_STRING2 | IT_CVAR, "Encore", "Enable or disable Encore mode", + NULL, {.cvar = &cv_dummygpencore}, 0, 0}, + + // For GP + {IT_STRING | IT_CALL, "Cup Select", "Go on and select a cup!", NULL, {.routine = M_LevelSelectInit}, 2, GT_RACE}, + + // Match Race + {IT_STRING | IT_CALL, "Map Select", "Go on and select a race track!", NULL, {.routine = M_LevelSelectInit}, 0, GT_RACE}, + + {IT_STRING | IT_CALL, "Back", NULL, NULL, {.routine = M_GoBack}, 0, 0}, +}; + +menu_t PLAY_RaceDifficultyDef = { + sizeof(PLAY_RaceDifficulty) / sizeof(menuitem_t), + &PLAY_RaceGamemodesDef, + 0, + PLAY_RaceDifficulty, + 0, 0, + 0, 0, + 1, 5, + M_DrawRaceDifficulty, + NULL, + NULL, + NULL, + NULL +}; diff --git a/src/menus/play-local-race-time-attack.c b/src/menus/play-local-race-time-attack.c new file mode 100644 index 000000000..488a1b42d --- /dev/null +++ b/src/menus/play-local-race-time-attack.c @@ -0,0 +1,116 @@ +/// \file menus/play-local-race-time-attack.c +/// \brief Race Time Attack Menu + +#include "../k_menu.h" + +// see ta_e +menuitem_t PLAY_TimeAttack[] = +{ + {IT_STRING | IT_SUBMENU, "Replay...", NULL, NULL, {.submenu = &PLAY_TAReplayDef}, 0, 0}, + {IT_STRING | IT_SUBMENU, "Guest...", NULL, NULL, {.submenu = &PLAY_TAReplayGuestDef}, 0, 0}, + {IT_STRING | IT_SUBMENU, "Ghosts...", NULL, NULL, {.submenu = &PLAY_TAGhostsDef}, 0, 0}, + {IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0}, + {IT_STRING | IT_CALL, "Start", NULL, NULL, {.routine = M_StartTimeAttack}, 0, 0}, +}; + +menu_t PLAY_TimeAttackDef = { + sizeof(PLAY_TimeAttack) / sizeof(menuitem_t), + &PLAY_LevelSelectDef, + 0, + PLAY_TimeAttack, + 0, 0, + 0, 0, + 2, 5, + M_DrawTimeAttack, + NULL, + NULL, + NULL, + NULL +}; + + +menuitem_t PLAY_TAReplay[] = +{ + {IT_STRING | IT_CALL, "Replay Best Time", NULL, NULL, {.routine = M_ReplayTimeAttack}, 0, 0}, + {IT_STRING | IT_CALL, "Replay Best Lap", NULL, NULL, {.routine = M_ReplayTimeAttack}, 0, 0}, + {IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0}, + {IT_STRING | IT_CALL, "Replay Last", NULL, NULL, {.routine = M_ReplayTimeAttack}, 0, 0}, + {IT_STRING | IT_CALL, "Replay Guest", NULL, NULL, {.routine = M_ReplayTimeAttack}, 0, 0}, + {IT_STRING | IT_CALL, "Replay Staff", NULL, NULL, {.routine = M_HandleStaffReplay}, 0, 0}, + {IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_SUBMENU, "Back", NULL, NULL, {.submenu = &PLAY_TimeAttackDef}, 0, 0}, +}; + +menu_t PLAY_TAReplayDef = { + sizeof(PLAY_TAReplay) / sizeof(menuitem_t), + &PLAY_TimeAttackDef, + 0, + PLAY_TAReplay, + 0, 0, + 0, 0, + 2, 5, + M_DrawTimeAttack, + NULL, + NULL, + NULL, + NULL +}; + +menuitem_t PLAY_TAReplayGuest[] = +{ + {IT_HEADERTEXT|IT_HEADER, "Save as guest...", NULL, NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CALL, "Best Time", NULL, NULL, {.routine = M_SetGuestReplay}, 0, 0}, + {IT_STRING | IT_CALL, "Best Lap", NULL, NULL, {.routine = M_SetGuestReplay}, 0, 0}, + {IT_STRING | IT_CALL, "Last Run", NULL, NULL, {.routine = M_SetGuestReplay}, 0, 0}, + + {IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0}, + {IT_STRING | IT_CALL, "Delete Guest", NULL, NULL, {.routine = M_SetGuestReplay}, 0, 0}, + + {IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0}, + {IT_STRING | IT_SUBMENU, "Back", NULL, NULL, {.submenu = &PLAY_TimeAttackDef}, 0, 0}, + +}; + +menu_t PLAY_TAReplayGuestDef = { + sizeof(PLAY_TAReplayGuest) / sizeof(menuitem_t), + &PLAY_TimeAttackDef, + 0, + PLAY_TAReplayGuest, + 0, 0, + 0, 0, + 2, 5, + M_DrawTimeAttack, + NULL, + NULL, + NULL, + NULL +}; + +menuitem_t PLAY_TAGhosts[] = +{ + {IT_STRING | IT_CVAR, "Best Time", NULL, NULL, {.cvar = &cv_ghost_besttime}, 0, 0}, + {IT_STRING | IT_CVAR, "Best Lap", NULL, NULL, {.cvar = &cv_ghost_bestlap}, 0, 0}, + {IT_STRING | IT_CVAR, "Last", NULL, NULL, {.cvar = &cv_ghost_last}, 0, 0}, + {IT_DISABLED, "Guest", NULL, NULL, {.cvar = &cv_ghost_guest}, 0, 0}, + {IT_DISABLED, "Staff", NULL, NULL, {.cvar = &cv_ghost_staff}, 0, 0}, + + {IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0}, + {IT_STRING | IT_SUBMENU, "Back", NULL, NULL, {.submenu = &PLAY_TimeAttackDef}, 0, 0}, +}; + +menu_t PLAY_TAGhostsDef = { + sizeof(PLAY_TAGhosts) / sizeof(menuitem_t), + &PLAY_TimeAttackDef, + 0, + PLAY_TAGhosts, + 0, 0, + 0, 0, + 2, 5, + M_DrawTimeAttack, + NULL, + NULL, + NULL, + NULL +}; diff --git a/src/menus/play-online-1.c b/src/menus/play-online-1.c new file mode 100644 index 000000000..18c8c0568 --- /dev/null +++ b/src/menus/play-online-1.c @@ -0,0 +1,32 @@ +/// \file menus/play-online-1.c +/// \brief MULTIPLAYER OPTION SELECT + +#include "../k_menu.h" + +menuitem_t PLAY_MP_OptSelect[] = +{ + //{IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, M_MPOptSelect, 0, 0}, + {IT_STRING | IT_CALL, "Host Game", "Start your own online game!", + NULL, {.routine = M_MPHostInit}, 0, 0}, + + {IT_STRING | IT_CALL, "Server Browser", "Search for game servers to play in.", + NULL, {.routine = M_MPRoomSelectInit}, 0, 0}, + + {IT_STRING | IT_CALL, "Join by IP", "Join an online game by its IP address.", + NULL, {.routine = M_MPJoinIPInit}, 0, 0}, +}; + +menu_t PLAY_MP_OptSelectDef = { + sizeof (PLAY_MP_OptSelect) / sizeof (menuitem_t), + &PLAY_MainDef, + 0, + PLAY_MP_OptSelect, + 0, 0, + 0, 0, + -1, 1, + M_DrawMPOptSelect, + M_MPOptSelectTick, + NULL, + NULL, + NULL +}; diff --git a/src/menus/play-online-host.c b/src/menus/play-online-host.c new file mode 100644 index 000000000..0a0faea74 --- /dev/null +++ b/src/menus/play-online-host.c @@ -0,0 +1,41 @@ +/// \file menus/play-online-host.c +/// \brief MULTIPLAYER HOST SCREEN -- see mhost_e + +#include "../k_menu.h" + +// MULTIPLAYER HOST SCREEN -- see mhost_e +menuitem_t PLAY_MP_Host[] = +{ + //{IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, M_MPOptSelect, 0, 0}, + + {IT_STRING | IT_CVAR | IT_CV_STRING, "Server Name", "Display name for your game online. Other players will see this.", + NULL, {.cvar = &cv_servername}, 0, 0}, + + {IT_STRING | IT_CVAR, "Public Server", "Display or not your game in the Server Browser for other players.", + NULL, {.cvar = &cv_advertise}, 0, 0}, + + {IT_STRING | IT_CVAR, "Max. Players", "Set how many players can play at once. Others will spectate.", + NULL, {.cvar = &cv_maxplayers}, 0, 0}, + + {IT_STRING | IT_KEYHANDLER, "Gamemode", "Choose the type of play on your server.", + NULL, {.routine = M_HandleHostMenuGametype}, 0, 0}, + + {IT_STRING | IT_CALL, "GO", "Select a map with the currently selected gamemode", + NULL, {.routine = M_MPSetupNetgameMapSelect}, 0, 0}, + +}; + +menu_t PLAY_MP_HostDef = { + sizeof (PLAY_MP_Host) / sizeof (menuitem_t), + &PLAY_MP_OptSelectDef, + 0, + PLAY_MP_Host, + 0, 0, + 0, 0, + -1, 1, // 1 frame transition.... This is really just because I don't want the black fade when we press esc, hehe + M_DrawMPHost, + M_MPOptSelectTick, // This handles the unfolding options + NULL, + M_MPResetOpts, + NULL +}; diff --git a/src/menus/play-online-join-ip.c b/src/menus/play-online-join-ip.c new file mode 100644 index 000000000..398756eb9 --- /dev/null +++ b/src/menus/play-online-join-ip.c @@ -0,0 +1,43 @@ +/// \file menus/play-online-join-ip.c +/// \brief MULTIPLAYER JOIN BY IP + +#include "../k_menu.h" + +menuitem_t PLAY_MP_JoinIP[] = +{ + //{IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, M_MPOptSelect, 0, 0}, + + {IT_STRING | IT_CVAR | IT_CV_STRING, "IP: ", "Type the IPv4 address of the server.", + NULL, {.cvar = &cv_dummyip}, 0, 0}, + + {IT_STRING, "CONNECT ", "Attempt to connect to the server you entered the IP for.", + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_SPACE, "LAST IPs JOINED:", "Kanade best waifu :)", + NULL, {NULL}, 0, 0}, + + {IT_STRING, "servip1", "The last 3 IPs you've succesfully joined are displayed here.", + NULL, {NULL}, 0, 0}, + + {IT_STRING, "servip2", "The last 3 IPs you've succesfully joined are displayed here.", + NULL, {NULL}, 0, 0}, + + {IT_STRING, "servip3", "The last 3 IPs you've succesfully joined are displayed here.", + NULL, {NULL}, 0, 0}, + +}; + +menu_t PLAY_MP_JoinIPDef = { + sizeof (PLAY_MP_JoinIP) / sizeof (menuitem_t), + &PLAY_MP_OptSelectDef, + 0, + PLAY_MP_JoinIP, + 0, 0, + 0, 0, + -1, 1, // 1 frame transition.... This is really just because I don't want the black fade when we press esc, hehe + M_DrawMPJoinIP, + M_MPOptSelectTick, // This handles the unfolding options + NULL, + M_MPResetOpts, + M_JoinIPInputs +}; diff --git a/src/menus/play-online-server-browser.c b/src/menus/play-online-server-browser.c new file mode 100644 index 000000000..6549340a7 --- /dev/null +++ b/src/menus/play-online-server-browser.c @@ -0,0 +1,53 @@ +/// \file menus/play-online-server-browser.c +/// \brief Online server, CORE / MODDED + +#include "../k_menu.h" + +// MULTIPLAYER ROOM SELECT (CORE / MODDED) +menuitem_t PLAY_MP_RoomSelect[] = +{ + {IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, {.routine = M_MPRoomSelect}, 0, 0}, +}; + +menu_t PLAY_MP_RoomSelectDef = { + sizeof (PLAY_MP_RoomSelect) / sizeof (menuitem_t), + &PLAY_MP_OptSelectDef, + 0, + PLAY_MP_RoomSelect, + 0, 0, + 0, 0, + 0, 0, + M_DrawMPRoomSelect, + M_MPRoomSelectTick, + NULL, + NULL, + NULL +}; + +// SERVER BROWSER +menuitem_t PLAY_MP_ServerBrowser[] = +{ + + {IT_STRING | IT_CVAR, "SORT BY", NULL, // tooltip MUST be null. + NULL, {.cvar = &cv_serversort}, 0, 0}, + + {IT_STRING, "REFRESH", NULL, + NULL, {NULL}, 0, 0}, + + {IT_NOTHING, NULL, NULL, NULL, {NULL}, 0, 0}, +}; + +menu_t PLAY_MP_ServerBrowserDef = { + sizeof (PLAY_MP_ServerBrowser) / sizeof (menuitem_t), + &PLAY_MP_RoomSelectDef, + 0, + PLAY_MP_ServerBrowser, + 32, 36, + 0, 0, + 0, 0, + M_DrawMPServerBrowser, + M_MPServerBrowserTick, + NULL, + NULL, + M_ServerBrowserInputs +}; diff --git a/src/menus/transient/CMakeLists.txt b/src/menus/transient/CMakeLists.txt new file mode 100644 index 000000000..305c82829 --- /dev/null +++ b/src/menus/transient/CMakeLists.txt @@ -0,0 +1,6 @@ +target_sources(SRB2SDL2 PRIVATE + level-select.c + manual.c + pause-game.c + pause-replay.c +) diff --git a/src/menus/transient/level-select.c b/src/menus/transient/level-select.c new file mode 100644 index 000000000..ab124b8e5 --- /dev/null +++ b/src/menus/transient/level-select.c @@ -0,0 +1,44 @@ +/// \file menus/transient/level-select.c +/// \brief Level Select + +#include "../../k_menu.h" + +menuitem_t PLAY_CupSelect[] = +{ + {IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, {.routine = M_CupSelectHandler}, 0, 0}, +}; + +menu_t PLAY_CupSelectDef = { + sizeof(PLAY_CupSelect) / sizeof(menuitem_t), + &PLAY_RaceGamemodesDef, + 0, + PLAY_CupSelect, + 0, 0, + 0, 0, + 2, 5, + M_DrawCupSelect, + M_CupSelectTick, + NULL, + NULL, + NULL +}; + +menuitem_t PLAY_LevelSelect[] = +{ + {IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, {.routine = M_LevelSelectHandler}, 0, 0}, +}; + +menu_t PLAY_LevelSelectDef = { + sizeof(PLAY_LevelSelect) / sizeof(menuitem_t), + &PLAY_CupSelectDef, + 0, + PLAY_LevelSelect, + 0, 0, + 0, 0, + 2, 5, + M_DrawLevelSelect, + M_LevelSelectTick, + NULL, + NULL, + NULL +}; diff --git a/src/menus/transient/manual.c b/src/menus/transient/manual.c new file mode 100644 index 000000000..2ba3c32a9 --- /dev/null +++ b/src/menus/transient/manual.c @@ -0,0 +1,23 @@ +/// \file menus/transient/manual.c +/// \brief Manual + +#include "../../k_menu.h" + +menuitem_t MISC_Manual[] = { + {IT_NOTHING | IT_KEYHANDLER, "MANUAL00", NULL, NULL, {.routine = M_HandleImageDef}, 0, 0}, + {IT_NOTHING | IT_KEYHANDLER, "MANUAL01", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, + {IT_NOTHING | IT_KEYHANDLER, "MANUAL02", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, + {IT_NOTHING | IT_KEYHANDLER, "MANUAL03", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, + {IT_NOTHING | IT_KEYHANDLER, "MANUAL04", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, + {IT_NOTHING | IT_KEYHANDLER, "MANUAL05", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, + {IT_NOTHING | IT_KEYHANDLER, "MANUAL06", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, + {IT_NOTHING | IT_KEYHANDLER, "MANUAL07", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, + {IT_NOTHING | IT_KEYHANDLER, "MANUAL08", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, + {IT_NOTHING | IT_KEYHANDLER, "MANUAL09", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, + {IT_NOTHING | IT_KEYHANDLER, "MANUAL10", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, + {IT_NOTHING | IT_KEYHANDLER, "MANUAL11", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, + {IT_NOTHING | IT_KEYHANDLER, "MANUAL12", NULL, NULL, {.routine = M_HandleImageDef}, 1, 0}, + {IT_NOTHING | IT_KEYHANDLER, "MANUAL99", NULL, NULL, {.routine = M_HandleImageDef}, 0, 0}, +}; + +menu_t MISC_ManualDef = IMAGEDEF(MISC_Manual); diff --git a/src/menus/transient/pause-game.c b/src/menus/transient/pause-game.c new file mode 100644 index 000000000..5a29da812 --- /dev/null +++ b/src/menus/transient/pause-game.c @@ -0,0 +1,70 @@ +/// \file menus/transient/pause-game.c +/// \brief In-game/pause menus + +#include "../../k_menu.h" + +// ESC pause menu +// Since there's no descriptions to each item, we'll use the descriptions as the names of the patches we want to draw for each option :) + +menuitem_t PAUSE_Main[] = +{ + + {IT_STRING | IT_CALL, "ADDONS", "M_ICOADD", + NULL, {.routine = M_Addons}, 0, 0}, + + {IT_STRING | IT_KEYHANDLER, "GAMETYPE", "M_ICOGAM", + NULL, {.routine = M_HandlePauseMenuGametype}, 0, 0}, + + {IT_STRING | IT_CALL, "CHANGE MAP", "M_ICOMAP", + NULL, {.routine = M_LevelSelectInit}, 0, -1}, + + {IT_STRING | IT_CALL, "RESTART MAP", "M_ICORE", + NULL, {.routine = M_RestartMap}, 0, 0}, + + {IT_STRING | IT_CALL, "TRY AGAIN", "M_ICORE", + NULL, {.routine = M_TryAgain}, 0, 0}, + +#ifdef HAVE_DISCORDRPC + {IT_STRING | IT_CALL, "DISCORD REQUESTS", "M_ICODIS", + NULL, {NULL}, 0, 0}, +#endif + + {IT_STRING | IT_CALL, "RESUME GAME", "M_ICOUNP", + NULL, {.routine = M_QuitPauseMenu}, 0, 0}, + + {IT_STRING | IT_CALL, "SPECTATE", "M_ICOSPC", + NULL, {.routine = M_ConfirmSpectate}, 0, 0}, + + {IT_STRING | IT_CALL, "ENTER GAME", "M_ICOENT", + NULL, {.routine = M_ConfirmEnterGame}, 0, 0}, + + {IT_STRING | IT_CALL, "CANCEL JOIN", "M_ICOSPC", + NULL, {.routine = M_ConfirmSpectate}, 0, 0}, + + {IT_STRING | IT_SUBMENU, "JOIN OR SPECTATE", "M_ICOENT", + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CALL, "PLAYER SETUP", "M_ICOCHR", + NULL, {.routine = M_CharacterSelect}, 0, 0}, + + {IT_STRING | IT_CALL, "OPTIONS", "M_ICOOPT", + NULL, {.routine = M_InitOptions}, 0, 0}, + + {IT_STRING | IT_CALL, "EXIT GAME", "M_ICOEXT", + NULL, {.routine = M_EndGame}, 0, 0}, +}; + +menu_t PAUSE_MainDef = { + sizeof (PAUSE_Main) / sizeof (menuitem_t), + NULL, + 0, + PAUSE_Main, + 0, 0, + 0, 0, + 1, 10, // For transition with some menus! + M_DrawPause, + M_PauseTick, + NULL, + NULL, + M_PauseInputs +}; diff --git a/src/menus/transient/pause-replay.c b/src/menus/transient/pause-replay.c new file mode 100644 index 000000000..06b0dd594 --- /dev/null +++ b/src/menus/transient/pause-replay.c @@ -0,0 +1,40 @@ +/// \file menus/transient/pause-replay.c +/// \brief Replay popup menu + +#include "../../k_menu.h" + +menuitem_t PAUSE_PlaybackMenu[] = +{ + {IT_CALL | IT_STRING, "Hide Menu (Esc)", NULL, "M_PHIDE", {.routine = M_SelectableClearMenus}, 0, 0}, + + {IT_CALL | IT_STRING, "Rewind ([)", NULL, "M_PREW", {.routine = M_PlaybackRewind}, 20, 0}, + {IT_CALL | IT_STRING, "Pause (\\)", NULL, "M_PPAUSE", {.routine = M_PlaybackPause}, 36, 0}, + {IT_CALL | IT_STRING, "Fast-Forward (])", NULL, "M_PFFWD", {.routine = M_PlaybackFastForward}, 52, 0}, + {IT_CALL | IT_STRING, "Backup Frame ([)", NULL, "M_PSTEPB", {.routine = M_PlaybackRewind}, 20, 0}, + {IT_CALL | IT_STRING, "Resume", NULL, "M_PRESUM", {.routine = M_PlaybackPause}, 36, 0}, + {IT_CALL | IT_STRING, "Advance Frame (])", NULL, "M_PFADV", {.routine = M_PlaybackAdvance}, 52, 0}, + + {IT_ARROWS | IT_STRING, "View Count (- and =)", NULL, "M_PVIEWS", {.routine = M_PlaybackSetViews}, 72, 0}, + {IT_ARROWS | IT_STRING, "Viewpoint (1)", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 88, 0}, + {IT_ARROWS | IT_STRING, "Viewpoint 2 (2)", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 104, 0}, + {IT_ARROWS | IT_STRING, "Viewpoint 3 (3)", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 120, 0}, + {IT_ARROWS | IT_STRING, "Viewpoint 4 (4)", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 136, 0}, + + {IT_CALL | IT_STRING, "Toggle Free Camera (')", NULL, "M_PVIEWS", {.routine = M_PlaybackToggleFreecam}, 156, 0}, + {IT_CALL | IT_STRING, "Stop Playback", NULL, "M_PEXIT", {.routine = M_PlaybackQuit}, 172, 0}, +}; + +menu_t PAUSE_PlaybackMenuDef = { + sizeof (PAUSE_PlaybackMenu) / sizeof (menuitem_t), + NULL, + 0, + PAUSE_PlaybackMenu, + BASEVIDWIDTH/2 - 88, 2, + 0, 0, + 0, 0, + M_DrawPlaybackMenu, + NULL, + NULL, + NULL, + NULL +}; From 9be7563353d4281736e2df549a572002aa75d11e Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 7 Jan 2023 07:51:54 -0800 Subject: [PATCH 04/32] sdl/i_video.cpp: fix -Wsign-compare --- src/sdl/i_video.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl/i_video.cpp b/src/sdl/i_video.cpp index b015af04c..715c9ebf9 100644 --- a/src/sdl/i_video.cpp +++ b/src/sdl/i_video.cpp @@ -572,7 +572,7 @@ static INT32 SDLJoyAxis(const Sint16 axis, UINT8 pid) static void Impl_HandleWindowEvent(SDL_WindowEvent evt) { -#define FOCUSUNION (mousefocus | (kbfocus << 1)) +#define FOCUSUNION static_cast(mousefocus | (kbfocus << 1)) static SDL_bool firsttimeonmouse = SDL_TRUE; static SDL_bool mousefocus = SDL_TRUE; static SDL_bool kbfocus = SDL_TRUE; From 9980631e2f92ce5e88d17d4d0c6a62fb35576106 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 8 Jan 2023 13:58:14 +0000 Subject: [PATCH 05/32] Fix bots' `realtime` not ticking upwards when all human players have exited This corrects the issue where bots have the same time on exit as the last human player, and therefore tie with them, with disastrous consequences for GP. --- src/p_user.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index d626e1e19..c00991850 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2664,7 +2664,7 @@ static void P_DeathThink(player_t *player) } // Keep time rolling - if (!(exitcountdown && !racecountdown) && !(player->exiting || mapreset) && !(player->pflags & PF_NOCONTEST) && !stoppedclock) + if (!(player->exiting || mapreset) && !(player->pflags & PF_NOCONTEST) && !stoppedclock) { if (leveltime >= starttime) { @@ -4023,7 +4023,7 @@ void P_PlayerThink(player_t *player) } // Synchronizes the "real" amount of time spent in the level. - if (!(exitcountdown && !racecountdown) && !(player->exiting || mapreset) && !(player->pflags & PF_NOCONTEST) && !stoppedclock) + if (!(player->exiting || mapreset) && !(player->pflags & PF_NOCONTEST) && !stoppedclock) { if (leveltime >= starttime) { From 3d9137a9cf964928e9d7de0916fa4bb237fe6091 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 8 Jan 2023 14:02:02 +0000 Subject: [PATCH 06/32] Pre-emptively fixes a possible issue where a player who is exiting would have their realtime adjusted on respawn, affecting final results. --- src/p_mobj.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 24d881471..b5bb16c45 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11735,7 +11735,11 @@ void P_SpawnPlayer(INT32 playernum) mobj->health = 1; p->playerstate = PST_LIVE; - p->realtime = leveltime; + if (!p->exiting || !p->realtime) + { + p->realtime = leveltime; + } + p->followitem = skins[p->skin].followitem; //awayview stuff From 2aa43f04b2d7ca68bab8432c8355a7bdb193a7b6 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 8 Jan 2023 16:45:14 +0000 Subject: [PATCH 07/32] Additional memory safety for follower handling --- src/k_follower.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/k_follower.c b/src/k_follower.c index 0a8869077..41623d57e 100644 --- a/src/k_follower.c +++ b/src/k_follower.c @@ -315,7 +315,8 @@ void K_HandleFollower(player_t *player) // don't do anything if we can't have a follower to begin with. // (It gets removed under those conditions) - if (player->spectator || player->followerskin < 0) + if (player->spectator || player->followerskin < 0 + || player->mo == NULL || P_MobjWasRemoved(player->mo)) { if (player->follower) { @@ -377,12 +378,15 @@ void K_HandleFollower(player_t *player) // Set follower colour color = K_GetEffectiveFollowerColor(player->followercolor, player->skincolor); - if (player->follower == NULL) // follower doesn't exist / isn't valid + if (player->follower == NULL || P_MobjWasRemoved(player->follower)) // follower doesn't exist / isn't valid { //CONS_Printf("Spawning follower...\n"); // so let's spawn one! P_SetTarget(&player->follower, P_SpawnMobj(sx, sy, sz, MT_FOLLOWER)); + if (player->follower == NULL) + return; + K_UpdateFollowerState(player->follower, fl.idlestate, FOLLOWERSTATE_IDLE); P_SetTarget(&player->follower->target, player->mo); // we need that to know when we need to disappear @@ -402,14 +406,6 @@ void K_HandleFollower(player_t *player) } else // follower exists, woo! { - // Safety net (2) - - if (P_MobjWasRemoved(player->follower)) - { - P_SetTarget(&player->follower, NULL); // Remove this and respawn one, don't crash the game if Lua decides to P_RemoveMobj this thing. - return; - } - // first of all, handle states following the same model as above: if (player->follower->tics == 1) { From ba3a3f4203b6ba23dbbf596a0c7e875c88428356 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 8 Jan 2023 16:51:58 +0000 Subject: [PATCH 08/32] Follower hitlag - If a player enters hitlag, put their follower in hitlag too - If a follower exists and is in hitlag, don't update it in K_HandleFollower --- src/k_follower.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/k_follower.c b/src/k_follower.c index 41623d57e..f0a1d7748 100644 --- a/src/k_follower.c +++ b/src/k_follower.c @@ -406,6 +406,12 @@ void K_HandleFollower(player_t *player) } else // follower exists, woo! { + if (player->follower->hitlag != 0) + { + // Don't update frames in hitlag + return; + } + // first of all, handle states following the same model as above: if (player->follower->tics == 1) { @@ -621,4 +627,11 @@ void K_HandleFollower(player_t *player) K_UpdateFollowerState(player->follower, fl.idlestate, FOLLOWERSTATE_IDLE); } } + + if (player->mo->hitlag) + { + player->follower->hitlag = player->mo->hitlag; + player->follower->eflags |= (player->mo->eflags & MFE_DAMAGEHITLAG); + return; + } } From 1b859f50733a58cdcd90903150a83876f0a9f749 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Mon, 9 Jan 2023 13:05:35 -0600 Subject: [PATCH 09/32] cxx: Add srb2::Overload for using std::visit --- src/audio/wav.cpp | 18 ++++++------------ src/cxxutil.hpp | 11 +++++++++++ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/audio/wav.cpp b/src/audio/wav.cpp index 31f3a0468..751c87b41 100644 --- a/src/audio/wav.cpp +++ b/src/audio/wav.cpp @@ -13,6 +13,8 @@ #include #include +#include "../cxxutil.hpp" + using namespace srb2; using srb2::audio::Wav; @@ -130,14 +132,6 @@ std::vector read_int16_samples_from_stream(io::SpanStream& stream, std: return samples; } -template -struct OverloadVisitor : Ts... { - using Ts::operator()...; -}; - -template -OverloadVisitor(Ts...) -> OverloadVisitor; - } // namespace Wav::Wav() = default; @@ -171,7 +165,7 @@ Wav::Wav(tcb::span data) { throw std::runtime_error("WAVE tag length exceeds stream length"); } - auto tag_visitor = OverloadVisitor { + auto tag_visitor = srb2::Overload { [&](const FmtTag& fmt) { if (read_fmt) { throw std::runtime_error("WAVE has multiple 'fmt' tags"); @@ -248,7 +242,7 @@ std::size_t read_samples(std::size_t channels, } // namespace std::size_t Wav::get_samples(std::size_t offset, tcb::span> buffer) const noexcept { - auto samples_visitor = OverloadVisitor { + auto samples_visitor = srb2::Overload { [&](const std::vector& samples) { return read_samples(channels(), offset, samples, buffer); }, [&](const std::vector& samples) { return read_samples(channels(), offset, samples, buffer); @@ -258,7 +252,7 @@ std::size_t Wav::get_samples(std::size_t offset, tcb::span> buf } std::size_t Wav::interleaved_length() const noexcept { - auto samples_visitor = OverloadVisitor {[](const std::vector& samples) { return samples.size(); }, - [](const std::vector& samples) { return samples.size(); }}; + auto samples_visitor = srb2::Overload {[](const std::vector& samples) { return samples.size(); }, + [](const std::vector& samples) { return samples.size(); }}; return std::visit(samples_visitor, interleaved_samples_); } diff --git a/src/cxxutil.hpp b/src/cxxutil.hpp index 74349a0ff..82131768a 100644 --- a/src/cxxutil.hpp +++ b/src/cxxutil.hpp @@ -147,6 +147,17 @@ public: template NotNull(T) -> NotNull; +/// @brief Utility struct for combining several Callables (e.g. lambdas) into a single Callable with the call operator +/// overloaded. Use it to build a visitor for calling std::visit on variants. +/// @tparam ...Ts callable types +template +struct Overload : Ts... { + using Ts::operator()...; +}; + +template +Overload(Ts...) -> Overload; + } // namespace srb2 #endif // __SRB2_CXXUTIL_HPP__ From 9f649d77012fd0bbb31d44fbec11afed7c2b95ac Mon Sep 17 00:00:00 2001 From: Eidolon Date: Mon, 9 Jan 2023 14:58:59 -0600 Subject: [PATCH 10/32] audio: conditionally shutdown SFX/Music players Fixes a potential segfault during startup where the sound hasn't been initialized yet, but an I_Error occurs while loading data. --- src/sdl/new_sound.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sdl/new_sound.cpp b/src/sdl/new_sound.cpp index 3052ee587..0415778f1 100644 --- a/src/sdl/new_sound.cpp +++ b/src/sdl/new_sound.cpp @@ -186,7 +186,8 @@ void I_ShutdownSound(void) { SdlAudioLockHandle _; for (auto& channel : sound_effect_channels) { - *channel = audio::SoundEffectPlayer(); + if (channel) + *channel = audio::SoundEffectPlayer(); } } @@ -329,7 +330,8 @@ void I_InitMusic(void) { void I_ShutdownMusic(void) { SdlAudioLockHandle _; - *music_player = audio::MusicPlayer(); + if (music_player) + *music_player = audio::MusicPlayer(); } /// ------------------------ From f43de07fd1da93d6f6cbc708e59dac6bb0eb1009 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Mon, 9 Jan 2023 13:12:09 -0600 Subject: [PATCH 11/32] cxx: clang-format adjustments --- .clang-format | 5 +- src/audio/chunk_load.cpp | 80 ++++++---- src/audio/chunk_load.hpp | 3 +- src/audio/expand_mono.cpp | 6 +- src/audio/expand_mono.hpp | 6 +- src/audio/filter.cpp | 6 +- src/audio/filter.hpp | 6 +- src/audio/gain.cpp | 9 +- src/audio/gain.hpp | 6 +- src/audio/gme.cpp | 42 ++++-- src/audio/gme.hpp | 12 +- src/audio/gme_player.cpp | 31 ++-- src/audio/gme_player.hpp | 6 +- src/audio/mixer.cpp | 21 ++- src/audio/mixer.hpp | 6 +- src/audio/music_player.cpp | 208 +++++++++++++++++--------- src/audio/music_player.hpp | 9 +- src/audio/ogg.cpp | 90 ++++++++---- src/audio/ogg.hpp | 15 +- src/audio/ogg_player.cpp | 68 ++++++--- src/audio/ogg_player.hpp | 6 +- src/audio/resample.cpp | 21 ++- src/audio/resample.hpp | 9 +- src/audio/sample.hpp | 42 ++++-- src/audio/sound_chunk.hpp | 6 +- src/audio/sound_effect_player.cpp | 24 ++- src/audio/sound_effect_player.hpp | 6 +- src/audio/source.hpp | 6 +- src/audio/wav.cpp | 124 ++++++++++------ src/audio/wav.hpp | 9 +- src/audio/wav_player.cpp | 18 ++- src/audio/wav_player.hpp | 6 +- src/audio/xmp.cpp | 57 ++++--- src/audio/xmp.hpp | 14 +- src/audio/xmp_player.cpp | 18 ++- src/audio/xmp_player.hpp | 6 +- src/cxxutil.hpp | 16 +- src/sdl/new_sound.cpp | 237 ++++++++++++++++++++---------- 38 files changed, 849 insertions(+), 411 deletions(-) diff --git a/.clang-format b/.clang-format index ff27be35d..15b53c893 100644 --- a/.clang-format +++ b/.clang-format @@ -6,6 +6,8 @@ UseTab: Always TabWidth: 4 ColumnLimit: 120 AccessModifierOffset: -4 +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortEnumsOnASingleLine: false @@ -13,10 +15,11 @@ AllowShortFunctionsOnASingleLine: InlineOnly AllowShortIfStatementsOnASingleLine: false AllowShortLambdasOnASingleLine: All AllowShortLoopsOnASingleLine: false +AlignAfterOpenBracket: BlockIndent AlwaysBreakTemplateDeclarations: Yes BinPackArguments: false BinPackParameters: false -BreakBeforeBraces: Attach # K&R/OTBS, braces on same line, Java style +BreakBeforeBraces: Allman # Always break before braces, to match existing SRB2 code BreakConstructorInitializers: BeforeComma CompactNamespaces: true ConstructorInitializerAllOnOneLineOrOnePerLine: true diff --git a/src/audio/chunk_load.cpp b/src/audio/chunk_load.cpp index 79900ec17..c076c1bdb 100644 --- a/src/audio/chunk_load.cpp +++ b/src/audio/chunk_load.cpp @@ -30,20 +30,26 @@ using std::size_t; using namespace srb2::audio; using namespace srb2; -namespace { +namespace +{ // Utility for leveraging Resampler... -class SoundChunkSource : public Source<1> { +class SoundChunkSource : public Source<1> +{ public: explicit SoundChunkSource(std::unique_ptr&& chunk) - : chunk_(std::forward>(chunk)) {} + : chunk_(std::forward>(chunk)) + { + } - virtual size_t generate(tcb::span> buffer) override final { + virtual size_t generate(tcb::span> buffer) override final + { if (!chunk_) return 0; size_t written = 0; - for (; pos_ < chunk_->samples.size() && written < buffer.size(); pos_++) { + for (; pos_ < chunk_->samples.size() && written < buffer.size(); pos_++) + { buffer[written] = chunk_->samples[pos_]; written++; } @@ -56,13 +62,15 @@ private: }; template -std::vector> generate_to_vec(I& source, std::size_t estimate = 0) { +std::vector> generate_to_vec(I& source, std::size_t estimate = 0) +{ std::vector> generated; size_t total = 0; size_t read = 0; generated.reserve(estimate); - do { + do + { generated.resize(total + 4096); read = source.generate(tcb::span {generated.data() + total, 4096}); total += read; @@ -71,7 +79,8 @@ std::vector> generate_to_vec(I& source, std::size_t estimate = 0) { return generated; } -optional try_load_dmx(tcb::span data) { +optional try_load_dmx(tcb::span data) +{ io::SpanStream stream {data}; if (io::remaining(stream) < 8) @@ -90,14 +99,16 @@ optional try_load_dmx(tcb::span data) { stream.seek(io::SeekFrom::kCurrent, 16); std::vector> samples; - for (size_t i = 0; i < length; i++) { + for (size_t i = 0; i < length; i++) + { uint8_t doom_sample = io::read_uint8(stream); float float_sample = audio::sample_to_float(doom_sample); samples.push_back(Sample<1> {float_sample}); } size_t samples_len = samples.size(); - if (rate == 44100) { + if (rate == 44100) + { return SoundChunk {samples}; } @@ -110,7 +121,8 @@ optional try_load_dmx(tcb::span data) { size_t total = 0; size_t read = 0; resampled.reserve(samples_len * (static_cast(kSampleRate) / rate)); - do { + do + { resampled.resize(total + 4096); read = resampler.generate(tcb::span {resampled.data() + total, 4096}); total += read; @@ -120,34 +132,44 @@ optional try_load_dmx(tcb::span data) { return SoundChunk {std::move(resampled)}; } -optional try_load_wav(tcb::span data) { +optional try_load_wav(tcb::span data) +{ io::SpanStream stream {data}; audio::Wav wav; std::size_t sample_rate; - try { + try + { wav = audio::load_wav(stream); - } catch (const std::exception& ex) { + } + catch (const std::exception& ex) + { return nullopt; } sample_rate = wav.sample_rate(); - audio::Resampler<1> resampler(std::make_unique(std::move(wav)), - sample_rate / static_cast(kSampleRate)); + audio::Resampler<1> resampler( + std::make_unique(std::move(wav)), + sample_rate / static_cast(kSampleRate) + ); SoundChunk chunk {generate_to_vec(resampler)}; return chunk; } -optional try_load_ogg(tcb::span data) { +optional try_load_ogg(tcb::span data) +{ std::shared_ptr> player; - try { + try + { io::SpanStream data_stream {data}; audio::Ogg ogg = audio::load_ogg(data_stream); player = std::make_shared>(std::move(ogg)); - } catch (...) { + } + catch (...) + { return nullopt; } player->looping(false); @@ -161,19 +183,26 @@ optional try_load_ogg(tcb::span data) { return chunk; } -optional try_load_gme(tcb::span data) { +optional try_load_gme(tcb::span data) +{ std::shared_ptr> player; - try { - if (data[0] == std::byte {0x1F} && data[1] == std::byte {0x8B}) { + try + { + if (data[0] == std::byte {0x1F} && data[1] == std::byte {0x8B}) + { io::SpanStream stream {data}; audio::Gme gme = audio::load_gme(stream); player = std::make_shared>(std::move(gme)); - } else { + } + else + { io::ZlibInputStream stream {io::SpanStream(data)}; audio::Gme gme = audio::load_gme(stream); player = std::make_shared>(std::move(gme)); } - } catch (...) { + } + catch (...) + { return nullopt; } std::vector> samples {generate_to_vec(*player)}; @@ -183,7 +212,8 @@ optional try_load_gme(tcb::span data) { } // namespace -optional srb2::audio::try_load_chunk(tcb::span data) { +optional srb2::audio::try_load_chunk(tcb::span data) +{ optional ret; ret = try_load_dmx(data); diff --git a/src/audio/chunk_load.hpp b/src/audio/chunk_load.hpp index c97d559d2..675a327cf 100644 --- a/src/audio/chunk_load.hpp +++ b/src/audio/chunk_load.hpp @@ -17,7 +17,8 @@ #include "sound_chunk.hpp" -namespace srb2::audio { +namespace srb2::audio +{ /// @brief Try to load a chunk from the given byte span. std::optional try_load_chunk(tcb::span data); diff --git a/src/audio/expand_mono.cpp b/src/audio/expand_mono.cpp index ce7cf0dc3..ee4e20147 100644 --- a/src/audio/expand_mono.cpp +++ b/src/audio/expand_mono.cpp @@ -17,8 +17,10 @@ using namespace srb2::audio; ExpandMono::~ExpandMono() = default; -size_t ExpandMono::filter(tcb::span> input_buffer, tcb::span> buffer) { - for (size_t i = 0; i < std::min(input_buffer.size(), buffer.size()); i++) { +size_t ExpandMono::filter(tcb::span> input_buffer, tcb::span> buffer) +{ + for (size_t i = 0; i < std::min(input_buffer.size(), buffer.size()); i++) + { buffer[i].amplitudes[0] = input_buffer[i].amplitudes[0]; buffer[i].amplitudes[1] = input_buffer[i].amplitudes[0]; } diff --git a/src/audio/expand_mono.hpp b/src/audio/expand_mono.hpp index f3686704e..d06a95a7c 100644 --- a/src/audio/expand_mono.hpp +++ b/src/audio/expand_mono.hpp @@ -14,9 +14,11 @@ #include "filter.hpp" -namespace srb2::audio { +namespace srb2::audio +{ -class ExpandMono : public Filter<1, 2> { +class ExpandMono : public Filter<1, 2> +{ public: virtual ~ExpandMono(); virtual std::size_t filter(tcb::span> input_buffer, tcb::span> buffer) override final; diff --git a/src/audio/filter.cpp b/src/audio/filter.cpp index 8bb09bdfb..b68e0a7b9 100644 --- a/src/audio/filter.cpp +++ b/src/audio/filter.cpp @@ -17,7 +17,8 @@ using srb2::audio::Sample; using srb2::audio::Source; template -size_t Filter::generate(tcb::span> buffer) { +size_t Filter::generate(tcb::span> buffer) +{ input_buffer_.clear(); input_buffer_.resize(buffer.size()); @@ -27,7 +28,8 @@ size_t Filter::generate(tcb::span> buffer) { } template -void Filter::bind(const shared_ptr>& input) { +void Filter::bind(const shared_ptr>& input) +{ input_ = input; } diff --git a/src/audio/filter.hpp b/src/audio/filter.hpp index 59dce6e1e..56b2eef18 100644 --- a/src/audio/filter.hpp +++ b/src/audio/filter.hpp @@ -18,10 +18,12 @@ #include "source.hpp" -namespace srb2::audio { +namespace srb2::audio +{ template -class Filter : public Source { +class Filter : public Source +{ public: virtual std::size_t generate(tcb::span> buffer) override; diff --git a/src/audio/gain.cpp b/src/audio/gain.cpp index 59839bb69..8db17d4e8 100644 --- a/src/audio/gain.cpp +++ b/src/audio/gain.cpp @@ -20,9 +20,11 @@ using srb2::audio::Sample; constexpr const float kGainInterpolationAlpha = 0.8f; template -size_t Gain::filter(tcb::span> input_buffer, tcb::span> buffer) { +size_t Gain::filter(tcb::span> input_buffer, tcb::span> buffer) +{ size_t written = std::min(buffer.size(), input_buffer.size()); - for (size_t i = 0; i < written; i++) { + for (size_t i = 0; i < written; i++) + { buffer[i] = input_buffer[i]; buffer[i] *= gain_; gain_ += (new_gain_ - gain_) * kGainInterpolationAlpha; @@ -32,7 +34,8 @@ size_t Gain::filter(tcb::span> input_buffer, tcb::span> b } template -void Gain::gain(float new_gain) { +void Gain::gain(float new_gain) +{ new_gain_ = std::clamp(new_gain, 0.0f, 1.0f); } diff --git a/src/audio/gain.hpp b/src/audio/gain.hpp index ef4dd0d53..42055466e 100644 --- a/src/audio/gain.hpp +++ b/src/audio/gain.hpp @@ -14,10 +14,12 @@ #include "filter.hpp" -namespace srb2::audio { +namespace srb2::audio +{ template -class Gain : public Filter { +class Gain : public Filter +{ public: virtual std::size_t filter(tcb::span> input_buffer, tcb::span> buffer) override final; void gain(float new_gain); diff --git a/src/audio/gme.cpp b/src/audio/gme.cpp index 38279dd98..8b6ea928b 100644 --- a/src/audio/gme.cpp +++ b/src/audio/gme.cpp @@ -17,37 +17,45 @@ using namespace srb2; using namespace srb2::audio; -Gme::Gme() : memory_data_(), instance_(nullptr) { +Gme::Gme() : memory_data_(), instance_(nullptr) +{ } -Gme::Gme(Gme&& rhs) noexcept : memory_data_(), instance_(nullptr) { +Gme::Gme(Gme&& rhs) noexcept : memory_data_(), instance_(nullptr) +{ std::swap(memory_data_, rhs.memory_data_); std::swap(instance_, rhs.instance_); } -Gme::Gme(std::vector&& data) : memory_data_(std::move(data)), instance_(nullptr) { +Gme::Gme(std::vector&& data) : memory_data_(std::move(data)), instance_(nullptr) +{ _init_with_data(); } -Gme::Gme(tcb::span data) : memory_data_(data.begin(), data.end()), instance_(nullptr) { +Gme::Gme(tcb::span data) : memory_data_(data.begin(), data.end()), instance_(nullptr) +{ _init_with_data(); } -Gme& Gme::operator=(Gme&& rhs) noexcept { +Gme& Gme::operator=(Gme&& rhs) noexcept +{ std::swap(memory_data_, rhs.memory_data_); std::swap(instance_, rhs.instance_); return *this; } -Gme::~Gme() { - if (instance_) { +Gme::~Gme() +{ + if (instance_) + { gme_delete(instance_); instance_ = nullptr; } } -std::size_t Gme::get_samples(tcb::span buffer) { +std::size_t Gme::get_samples(tcb::span buffer) +{ SRB2_ASSERT(instance_ != nullptr); gme_err_t err = gme_play(instance_, buffer.size(), buffer.data()); @@ -57,13 +65,15 @@ std::size_t Gme::get_samples(tcb::span buffer) { return buffer.size(); } -void Gme::seek(int sample) { +void Gme::seek(int sample) +{ SRB2_ASSERT(instance_ != nullptr); gme_seek_samples(instance_, sample); } -std::optional Gme::duration_seconds() const { +std::optional Gme::duration_seconds() const +{ SRB2_ASSERT(instance_ != nullptr); gme_info_t* info = nullptr; @@ -79,7 +89,8 @@ std::optional Gme::duration_seconds() const { return static_cast(info->length) / 1000.f; } -std::optional Gme::loop_point_seconds() const { +std::optional Gme::loop_point_seconds() const +{ SRB2_ASSERT(instance_ != nullptr); gme_info_t* info = nullptr; @@ -95,7 +106,8 @@ std::optional Gme::loop_point_seconds() const { return loop_point_ms / 44100.f; } -float Gme::position_seconds() const { +float Gme::position_seconds() const +{ SRB2_ASSERT(instance_ != nullptr); gme_info_t* info = nullptr; @@ -117,8 +129,10 @@ float Gme::position_seconds() const { return position / 1000.f; } -void Gme::_init_with_data() { - if (instance_) { +void Gme::_init_with_data() +{ + if (instance_) + { return; } diff --git a/src/audio/gme.hpp b/src/audio/gme.hpp index 34f2c2769..453f5cdda 100644 --- a/src/audio/gme.hpp +++ b/src/audio/gme.hpp @@ -24,9 +24,11 @@ #include "../io/streams.hpp" -namespace srb2::audio { +namespace srb2::audio +{ -class GmeException : public std::exception { +class GmeException : public std::exception +{ std::string msg_; public: @@ -35,7 +37,8 @@ public: virtual const char* what() const noexcept override { return msg_.c_str(); } }; -class Gme { +class Gme +{ std::vector memory_data_; Music_Emu* instance_; @@ -64,7 +67,8 @@ private: }; template , int> = 0> -inline Gme load_gme(I& stream) { +inline Gme load_gme(I& stream) +{ std::vector data = srb2::io::read_to_vec(stream); return Gme {std::move(data)}; } diff --git a/src/audio/gme_player.cpp b/src/audio/gme_player.cpp index 229c99676..a3f0f08f8 100644 --- a/src/audio/gme_player.cpp +++ b/src/audio/gme_player.cpp @@ -13,7 +13,8 @@ using namespace srb2; using namespace srb2::audio; template -GmePlayer::GmePlayer(Gme&& gme) : gme_(std::forward(gme)), buf_() { +GmePlayer::GmePlayer(Gme&& gme) : gme_(std::forward(gme)), buf_() +{ } template @@ -26,17 +27,22 @@ template GmePlayer::~GmePlayer() = default; template -std::size_t GmePlayer::generate(tcb::span> buffer) { +std::size_t GmePlayer::generate(tcb::span> buffer) +{ buf_.clear(); buf_.resize(buffer.size() * 2); std::size_t read = gme_.get_samples(tcb::make_span(buf_)); buf_.resize(read); std::size_t new_samples = std::min((read / 2), buffer.size()); - for (std::size_t i = 0; i < new_samples; i++) { - if constexpr (C == 1) { + for (std::size_t i = 0; i < new_samples; i++) + { + if constexpr (C == 1) + { buffer[i].amplitudes[0] = (buf_[i * 2] / 32768.f + buf_[i * 2 + 1] / 32768.f) / 2.f; - } else if constexpr (C == 2) { + } + else if constexpr (C == 2) + { buffer[i].amplitudes[0] = buf_[i * 2] / 32768.f; buffer[i].amplitudes[1] = buf_[i * 2 + 1] / 32768.f; } @@ -45,27 +51,32 @@ std::size_t GmePlayer::generate(tcb::span> buffer) { } template -void GmePlayer::seek(float position_seconds) { +void GmePlayer::seek(float position_seconds) +{ gme_.seek(static_cast(position_seconds * 44100.f)); } template -void GmePlayer::reset() { +void GmePlayer::reset() +{ gme_.seek(0); } template -std::optional GmePlayer::duration_seconds() const { +std::optional GmePlayer::duration_seconds() const +{ return gme_.duration_seconds(); } template -std::optional GmePlayer::loop_point_seconds() const { +std::optional GmePlayer::loop_point_seconds() const +{ return gme_.loop_point_seconds(); } template -float GmePlayer::position_seconds() const { +float GmePlayer::position_seconds() const +{ return gme_.position_seconds(); } diff --git a/src/audio/gme_player.hpp b/src/audio/gme_player.hpp index a2f555c08..1d23cde6e 100644 --- a/src/audio/gme_player.hpp +++ b/src/audio/gme_player.hpp @@ -15,10 +15,12 @@ #include "gme.hpp" #include "source.hpp" -namespace srb2::audio { +namespace srb2::audio +{ template -class GmePlayer : public Source { +class GmePlayer : public Source +{ Gme gme_; std::vector buf_; diff --git a/src/audio/mixer.cpp b/src/audio/mixer.cpp index d4b718ffa..133cda16f 100644 --- a/src/audio/mixer.cpp +++ b/src/audio/mixer.cpp @@ -18,16 +18,20 @@ using srb2::audio::Mixer; using srb2::audio::Sample; using srb2::audio::Source; -namespace { +namespace +{ template -void default_init_sample_buffer(Sample* buffer, size_t size) { +void default_init_sample_buffer(Sample* buffer, size_t size) +{ std::for_each(buffer, buffer + size, [](auto& i) { i = Sample {}; }); } template -void mix_sample_buffers(Sample* dst, size_t size, Sample* src, size_t src_size) { - for (size_t i = 0; i < size && i < src_size; i++) { +void mix_sample_buffers(Sample* dst, size_t size, Sample* src, size_t src_size) +{ + for (size_t i = 0; i < size && i < src_size; i++) + { dst[i] += src[i]; } } @@ -35,12 +39,14 @@ void mix_sample_buffers(Sample* dst, size_t size, Sample* src, size_t src_ } // namespace template -size_t Mixer::generate(tcb::span> buffer) { +size_t Mixer::generate(tcb::span> buffer) +{ buffer_.resize(buffer.size()); default_init_sample_buffer(buffer.data(), buffer.size()); - for (auto& source : sources_) { + for (auto& source : sources_) + { size_t read = source->generate(buffer_); mix_sample_buffers(buffer.data(), buffer.size(), buffer_.data(), read); @@ -51,7 +57,8 @@ size_t Mixer::generate(tcb::span> buffer) { } template -void Mixer::add_source(const shared_ptr>& source) { +void Mixer::add_source(const shared_ptr>& source) +{ sources_.push_back(source); } diff --git a/src/audio/mixer.hpp b/src/audio/mixer.hpp index 75c8ba2f9..06e143cc8 100644 --- a/src/audio/mixer.hpp +++ b/src/audio/mixer.hpp @@ -17,10 +17,12 @@ #include "source.hpp" -namespace srb2::audio { +namespace srb2::audio +{ template -class Mixer : public Source { +class Mixer : public Source +{ public: virtual std::size_t generate(tcb::span> buffer) override final; diff --git a/src/audio/music_player.cpp b/src/audio/music_player.cpp index bb85a01de..5433f2100 100644 --- a/src/audio/music_player.cpp +++ b/src/audio/music_player.cpp @@ -43,12 +43,14 @@ using srb2::audio::Sample; using srb2::audio::Source; using namespace srb2; -class MusicPlayer::Impl { +class MusicPlayer::Impl +{ public: Impl() = default; Impl(tcb::span data) : Impl() { _load(data); } - size_t generate(tcb::span> buffer) { + size_t generate(tcb::span> buffer) + { if (!resampler_) return 0; @@ -57,12 +59,14 @@ public: size_t total_written = 0; - while (total_written < buffer.size()) { + while (total_written < buffer.size()) + { const size_t generated = resampler_->generate(buffer.subspan(total_written)); // To avoid a branch preventing optimizations, we're always going to apply // the fade gain, even if it would clamp anyway. - for (std::size_t i = 0; i < generated; i++) { + for (std::size_t i = 0; i < generated; i++) + { const float alpha = 1.0 - (gain_samples_target_ - std::min(gain_samples_ + i, gain_samples_target_)) / static_cast(gain_samples_target_); const float fade_gain = (gain_target_ - gain_) * std::clamp(alpha, 0.f, 1.f) + gain_; @@ -71,7 +75,8 @@ public: gain_samples_ = std::min(gain_samples_ + generated, gain_samples_target_); - if (gain_samples_ >= gain_samples_target_) { + if (gain_samples_ >= gain_samples_target_) + { fading_ = false; gain_samples_ = gain_samples_target_; gain_ = gain_target_; @@ -79,7 +84,8 @@ public: total_written += generated; - if (generated == 0) { + if (generated == 0) + { playing_ = false; break; } @@ -88,53 +94,68 @@ public: return total_written; } - void _load(tcb::span data) { + void _load(tcb::span data) + { ogg_inst_ = nullptr; gme_inst_ = nullptr; xmp_inst_ = nullptr; resampler_ = std::nullopt; - try { + try + { io::SpanStream stream {data}; audio::Ogg ogg = audio::load_ogg(stream); ogg_inst_ = std::make_shared>(std::move(ogg)); ogg_inst_->looping(looping_); resampler_ = Resampler<2>(ogg_inst_, ogg_inst_->sample_rate() / 44100.f); - } catch (const std::exception& ex) { + } + catch (const std::exception& ex) + { // it's probably not ogg ogg_inst_ = nullptr; resampler_ = std::nullopt; } - if (!resampler_) { - try { - if (data[0] == std::byte {0x1F} && data[1] == std::byte {0x8B}) { + if (!resampler_) + { + try + { + if (data[0] == std::byte {0x1F} && data[1] == std::byte {0x8B}) + { io::ZlibInputStream stream {io::SpanStream(data)}; audio::Gme gme = audio::load_gme(stream); gme_inst_ = std::make_shared>(std::move(gme)); - } else { + } + else + { io::SpanStream stream {data}; audio::Gme gme = audio::load_gme(stream); gme_inst_ = std::make_shared>(std::move(gme)); } resampler_ = Resampler<2>(gme_inst_, 1.f); - } catch (const std::exception& ex) { + } + catch (const std::exception& ex) + { // it's probably not gme gme_inst_ = nullptr; resampler_ = std::nullopt; } } - if (!resampler_) { - try { + if (!resampler_) + { + try + { io::SpanStream stream {data}; audio::Xmp<2> xmp = audio::load_xmp<2>(stream); xmp_inst_ = std::make_shared>(std::move(xmp)); xmp_inst_->looping(looping_); resampler_ = Resampler<2>(xmp_inst_, 1.f); - } catch (const std::exception& ex) { + } + catch (const std::exception& ex) + { // it's probably not xmp xmp_inst_ = nullptr; resampler_ = std::nullopt; @@ -146,74 +167,103 @@ public: internal_gain(1.f); } - void play(bool looping) { - if (ogg_inst_) { + void play(bool looping) + { + if (ogg_inst_) + { ogg_inst_->looping(looping); ogg_inst_->playing(true); playing_ = true; ogg_inst_->reset(); - } else if (gme_inst_) { + } + else if (gme_inst_) + { playing_ = true; gme_inst_->reset(); - } else if (xmp_inst_) { + } + else if (xmp_inst_) + { xmp_inst_->looping(looping); playing_ = true; xmp_inst_->reset(); } } - void unpause() { - if (ogg_inst_) { + void unpause() + { + if (ogg_inst_) + { ogg_inst_->playing(true); playing_ = true; - } else if (gme_inst_) { + } + else if (gme_inst_) + { playing_ = true; - } else if (xmp_inst_) { + } + else if (xmp_inst_) + { playing_ = true; } } - void pause() { - if (ogg_inst_) { + void pause() + { + if (ogg_inst_) + { ogg_inst_->playing(false); playing_ = false; - } else if (gme_inst_) { + } + else if (gme_inst_) + { playing_ = false; - } else if (xmp_inst_) { + } + else if (xmp_inst_) + { playing_ = false; } } - void stop() { - if (ogg_inst_) { + void stop() + { + if (ogg_inst_) + { ogg_inst_->reset(); ogg_inst_->playing(false); playing_ = false; - } else if (gme_inst_) { + } + else if (gme_inst_) + { gme_inst_->reset(); playing_ = false; - } else if (xmp_inst_) { + } + else if (xmp_inst_) + { xmp_inst_->reset(); playing_ = false; } } - void seek(float position_seconds) { - if (ogg_inst_) { + void seek(float position_seconds) + { + if (ogg_inst_) + { ogg_inst_->seek(position_seconds); return; } - if (gme_inst_) { + if (gme_inst_) + { gme_inst_->seek(position_seconds); return; } - if (xmp_inst_) { + if (xmp_inst_) + { xmp_inst_->seek(position_seconds); return; } } - bool playing() const { + bool playing() const + { if (ogg_inst_) return ogg_inst_->playing(); else if (gme_inst_) @@ -224,7 +274,8 @@ public: return false; } - std::optional music_type() const { + std::optional music_type() const + { if (ogg_inst_) return audio::MusicType::kOgg; else if (gme_inst_) @@ -235,7 +286,8 @@ public: return std::nullopt; } - std::optional duration_seconds() const { + std::optional duration_seconds() const + { if (ogg_inst_) return ogg_inst_->duration_seconds(); if (gme_inst_) @@ -246,7 +298,8 @@ public: return std::nullopt; } - std::optional loop_point_seconds() const { + std::optional loop_point_seconds() const + { if (ogg_inst_) return ogg_inst_->loop_point_seconds(); if (gme_inst_) @@ -255,7 +308,8 @@ public: return std::nullopt; } - std::optional position_seconds() const { + std::optional position_seconds() const + { if (ogg_inst_) return ogg_inst_->position_seconds(); if (gme_inst_) @@ -266,13 +320,14 @@ public: void fade_to(float gain, float seconds) { fade_from_to(gain_target_, gain, seconds); } - void fade_from_to(float from, float to, float seconds) { + void fade_from_to(float from, float to, float seconds) + { fading_ = true; gain_ = from; gain_target_ = to; // Gain samples target must always be at least 1 to avoid a div-by-zero. - gain_samples_target_ = std::max( - static_cast(seconds * 44100.f), UINT64_C(1)); // UINT64_C generates a uint64_t literal + gain_samples_target_ = + std::max(static_cast(seconds * 44100.f), UINT64_C(1)); // UINT64_C generates a uint64_t literal gain_samples_ = 0; } @@ -280,12 +335,14 @@ public: void stop_fade() { internal_gain(gain_target_); } - void loop_point_seconds(float loop_point) { + void loop_point_seconds(float loop_point) + { if (ogg_inst_) ogg_inst_->loop_point_seconds(loop_point); } - void internal_gain(float gain) { + void internal_gain(float gain) + { fading_ = false; gain_ = gain; gain_target_ = gain; @@ -310,112 +367,131 @@ private: }; // The special member functions MUST be declared in this unit, where Impl is complete. -MusicPlayer::MusicPlayer() : impl_(make_unique()) { +MusicPlayer::MusicPlayer() : impl_(make_unique()) +{ } -MusicPlayer::MusicPlayer(tcb::span data) : impl_(make_unique(data)) { +MusicPlayer::MusicPlayer(tcb::span data) : impl_(make_unique(data)) +{ } MusicPlayer::MusicPlayer(MusicPlayer&& rhs) noexcept = default; MusicPlayer& MusicPlayer::operator=(MusicPlayer&& rhs) noexcept = default; MusicPlayer::~MusicPlayer() = default; -void MusicPlayer::play(bool looping) { +void MusicPlayer::play(bool looping) +{ SRB2_ASSERT(impl_ != nullptr); return impl_->play(looping); } -void MusicPlayer::unpause() { +void MusicPlayer::unpause() +{ SRB2_ASSERT(impl_ != nullptr); return impl_->unpause(); } -void MusicPlayer::pause() { +void MusicPlayer::pause() +{ SRB2_ASSERT(impl_ != nullptr); return impl_->pause(); } -void MusicPlayer::stop() { +void MusicPlayer::stop() +{ SRB2_ASSERT(impl_ != nullptr); return impl_->stop(); } -void MusicPlayer::seek(float position_seconds) { +void MusicPlayer::seek(float position_seconds) +{ SRB2_ASSERT(impl_ != nullptr); return impl_->seek(position_seconds); } -bool MusicPlayer::playing() const { +bool MusicPlayer::playing() const +{ SRB2_ASSERT(impl_ != nullptr); return impl_->playing(); } -size_t MusicPlayer::generate(tcb::span> buffer) { +size_t MusicPlayer::generate(tcb::span> buffer) +{ SRB2_ASSERT(impl_ != nullptr); return impl_->generate(buffer); } -std::optional MusicPlayer::music_type() const { +std::optional MusicPlayer::music_type() const +{ SRB2_ASSERT(impl_ != nullptr); return impl_->music_type(); } -std::optional MusicPlayer::duration_seconds() const { +std::optional MusicPlayer::duration_seconds() const +{ SRB2_ASSERT(impl_ != nullptr); return impl_->duration_seconds(); } -std::optional MusicPlayer::loop_point_seconds() const { +std::optional MusicPlayer::loop_point_seconds() const +{ SRB2_ASSERT(impl_ != nullptr); return impl_->loop_point_seconds(); } -std::optional MusicPlayer::position_seconds() const { +std::optional MusicPlayer::position_seconds() const +{ SRB2_ASSERT(impl_ != nullptr); return impl_->position_seconds(); } -void MusicPlayer::fade_to(float gain, float seconds) { +void MusicPlayer::fade_to(float gain, float seconds) +{ SRB2_ASSERT(impl_ != nullptr); impl_->fade_to(gain, seconds); } -void MusicPlayer::fade_from_to(float from, float to, float seconds) { +void MusicPlayer::fade_from_to(float from, float to, float seconds) +{ SRB2_ASSERT(impl_ != nullptr); impl_->fade_from_to(from, to, seconds); } -void MusicPlayer::internal_gain(float gain) { +void MusicPlayer::internal_gain(float gain) +{ SRB2_ASSERT(impl_ != nullptr); impl_->internal_gain(gain); } -bool MusicPlayer::fading() const { +bool MusicPlayer::fading() const +{ SRB2_ASSERT(impl_ != nullptr); return impl_->fading(); } -void MusicPlayer::stop_fade() { +void MusicPlayer::stop_fade() +{ SRB2_ASSERT(impl_ != nullptr); impl_->stop_fade(); } -void MusicPlayer::loop_point_seconds(float loop_point) { +void MusicPlayer::loop_point_seconds(float loop_point) +{ SRB2_ASSERT(impl_ != nullptr); impl_->loop_point_seconds(loop_point); diff --git a/src/audio/music_player.hpp b/src/audio/music_player.hpp index 668724fa0..69f32dd6b 100644 --- a/src/audio/music_player.hpp +++ b/src/audio/music_player.hpp @@ -19,15 +19,18 @@ struct stb_vorbis; -namespace srb2::audio { +namespace srb2::audio +{ -enum class MusicType { +enum class MusicType +{ kOgg, kGme, kMod }; -class MusicPlayer : public Source<2> { +class MusicPlayer : public Source<2> +{ public: MusicPlayer(); MusicPlayer(tcb::span data); diff --git a/src/audio/ogg.cpp b/src/audio/ogg.cpp index 388fd37fe..b86e9c85c 100644 --- a/src/audio/ogg.cpp +++ b/src/audio/ogg.cpp @@ -16,11 +16,14 @@ using namespace srb2; using namespace srb2::audio; -StbVorbisException::StbVorbisException(int code) noexcept : code_(code) { +StbVorbisException::StbVorbisException(int code) noexcept : code_(code) +{ } -const char* StbVorbisException::what() const noexcept { - switch (code_) { +const char* StbVorbisException::what() const noexcept +{ + switch (code_) + { case VORBIS__no_error: return "No error"; case VORBIS_need_more_data: @@ -68,54 +71,73 @@ const char* StbVorbisException::what() const noexcept { } } -Ogg::Ogg() noexcept : memory_data_(), instance_(nullptr) { +Ogg::Ogg() noexcept : memory_data_(), instance_(nullptr) +{ } -Ogg::Ogg(std::vector data) : memory_data_(std::move(data)), instance_(nullptr) { +Ogg::Ogg(std::vector data) : memory_data_(std::move(data)), instance_(nullptr) +{ _init_with_data(); } -Ogg::Ogg(tcb::span data) : memory_data_(data.begin(), data.end()), instance_(nullptr) { +Ogg::Ogg(tcb::span data) : memory_data_(data.begin(), data.end()), instance_(nullptr) +{ _init_with_data(); } -Ogg::Ogg(Ogg&& rhs) noexcept : memory_data_(), instance_(nullptr) { +Ogg::Ogg(Ogg&& rhs) noexcept : memory_data_(), instance_(nullptr) +{ std::swap(memory_data_, rhs.memory_data_); std::swap(instance_, rhs.instance_); } -Ogg& Ogg::operator=(Ogg&& rhs) noexcept { +Ogg& Ogg::operator=(Ogg&& rhs) noexcept +{ std::swap(memory_data_, rhs.memory_data_); std::swap(instance_, rhs.instance_); return *this; } -Ogg::~Ogg() { - if (instance_) { +Ogg::~Ogg() +{ + if (instance_) + { stb_vorbis_close(instance_); instance_ = nullptr; } } -std::size_t Ogg::get_samples(tcb::span> buffer) { +std::size_t Ogg::get_samples(tcb::span> buffer) +{ SRB2_ASSERT(instance_ != nullptr); size_t read = stb_vorbis_get_samples_float_interleaved( - instance_, 1, reinterpret_cast(buffer.data()), buffer.size() * 1); + instance_, + 1, + reinterpret_cast(buffer.data()), + buffer.size() * 1 + ); return read; } -std::size_t Ogg::get_samples(tcb::span> buffer) { +std::size_t Ogg::get_samples(tcb::span> buffer) +{ SRB2_ASSERT(instance_ != nullptr); size_t read = stb_vorbis_get_samples_float_interleaved( - instance_, 2, reinterpret_cast(buffer.data()), buffer.size() * 2); + instance_, + 2, + reinterpret_cast(buffer.data()), + buffer.size() * 2 + ); stb_vorbis_info info = stb_vorbis_get_info(instance_); - if (info.channels == 1) { - for (auto& sample : buffer.subspan(0, read)) { + if (info.channels == 1) + { + for (auto& sample : buffer.subspan(0, read)) + { sample.amplitudes[1] = sample.amplitudes[0]; } } @@ -123,7 +145,8 @@ std::size_t Ogg::get_samples(tcb::span> buffer) { return read; } -OggComment Ogg::comment() const { +OggComment Ogg::comment() const +{ SRB2_ASSERT(instance_ != nullptr); stb_vorbis_comment c_comment = stb_vorbis_get_comment(instance_); @@ -133,50 +156,59 @@ OggComment Ogg::comment() const { std::vector(c_comment.comment_list, c_comment.comment_list + c_comment.comment_list_length)}; } -std::size_t Ogg::sample_rate() const { +std::size_t Ogg::sample_rate() const +{ SRB2_ASSERT(instance_ != nullptr); stb_vorbis_info info = stb_vorbis_get_info(instance_); return info.sample_rate; } -void Ogg::seek(std::size_t sample) { +void Ogg::seek(std::size_t sample) +{ SRB2_ASSERT(instance_ != nullptr); stb_vorbis_seek(instance_, sample); } -std::size_t Ogg::position() const { +std::size_t Ogg::position() const +{ SRB2_ASSERT(instance_ != nullptr); return stb_vorbis_get_sample_offset(instance_); } -float Ogg::position_seconds() const { +float Ogg::position_seconds() const +{ return position() / static_cast(sample_rate()); } -std::size_t Ogg::duration_samples() const { +std::size_t Ogg::duration_samples() const +{ SRB2_ASSERT(instance_ != nullptr); return stb_vorbis_stream_length_in_samples(instance_); } -float Ogg::duration_seconds() const { +float Ogg::duration_seconds() const +{ SRB2_ASSERT(instance_ != nullptr); return stb_vorbis_stream_length_in_seconds(instance_); } -std::size_t Ogg::channels() const { +std::size_t Ogg::channels() const +{ SRB2_ASSERT(instance_ != nullptr); stb_vorbis_info info = stb_vorbis_get_info(instance_); return info.channels; } -void Ogg::_init_with_data() { - if (instance_) { +void Ogg::_init_with_data() +{ + if (instance_) + { return; } @@ -187,7 +219,11 @@ void Ogg::_init_with_data() { int vorbis_result; instance_ = stb_vorbis_open_memory( - reinterpret_cast(memory_data_.data()), memory_data_.size(), &vorbis_result, NULL); + reinterpret_cast(memory_data_.data()), + memory_data_.size(), + &vorbis_result, + NULL + ); if (vorbis_result != VORBIS__no_error) throw StbVorbisException(vorbis_result); diff --git a/src/audio/ogg.hpp b/src/audio/ogg.hpp index d4b8b9275..bd8c9a86c 100644 --- a/src/audio/ogg.hpp +++ b/src/audio/ogg.hpp @@ -20,9 +20,11 @@ #include "../io/streams.hpp" #include "source.hpp" -namespace srb2::audio { +namespace srb2::audio +{ -class StbVorbisException final : public std::exception { +class StbVorbisException final : public std::exception +{ int code_; public: @@ -31,12 +33,14 @@ public: virtual const char* what() const noexcept; }; -struct OggComment { +struct OggComment +{ std::string vendor; std::vector comments; }; -class Ogg final { +class Ogg final +{ std::vector memory_data_; stb_vorbis* instance_; @@ -71,7 +75,8 @@ private: }; template , int> = 0> -inline Ogg load_ogg(I& stream) { +inline Ogg load_ogg(I& stream) +{ std::vector data = srb2::io::read_to_vec(stream); return Ogg {std::move(data)}; } diff --git a/src/audio/ogg_player.cpp b/src/audio/ogg_player.cpp index d9028dedb..e865d334e 100644 --- a/src/audio/ogg_player.cpp +++ b/src/audio/ogg_player.cpp @@ -18,35 +18,46 @@ using namespace srb2; using namespace srb2::audio; -namespace { +namespace +{ -std::optional find_loop_point(const Ogg& ogg) { +std::optional find_loop_point(const Ogg& ogg) +{ OggComment comment = ogg.comment(); std::size_t rate = ogg.sample_rate(); - for (auto& comment : comment.comments) { - if (comment.find("LOOPPOINT=") == 0) { + for (auto& comment : comment.comments) + { + if (comment.find("LOOPPOINT=") == 0) + { std::string_view comment_view(comment); comment_view.remove_prefix(10); std::string copied {comment_view}; - try { + try + { int loop_point = std::stoi(copied); return loop_point; - } catch (...) { + } + catch (...) + { } } - if (comment.find("LOOPMS=") == 0) { + if (comment.find("LOOPMS=") == 0) + { std::string_view comment_view(comment); comment_view.remove_prefix(7); std::string copied {comment_view}; - try { + try + { int loop_ms = std::stoi(copied); int loop_point = std::round(static_cast(loop_ms) / (rate / 1000.)); return loop_point; - } catch (...) { + } + catch (...) + { } } } @@ -58,7 +69,8 @@ std::optional find_loop_point(const Ogg& ogg) { template OggPlayer::OggPlayer(Ogg&& ogg) noexcept - : playing_(false), looping_(false), loop_point_(std::nullopt), ogg_(std::forward(ogg)) { + : playing_(false), looping_(false), loop_point_(std::nullopt), ogg_(std::forward(ogg)) +{ loop_point_ = find_loop_point(ogg_); } @@ -72,25 +84,30 @@ template OggPlayer::~OggPlayer() = default; template -std::size_t OggPlayer::generate(tcb::span> buffer) { +std::size_t OggPlayer::generate(tcb::span> buffer) +{ if (!playing_) return 0; std::size_t total = 0; - do { + do + { std::size_t read = ogg_.get_samples(buffer.subspan(total)); total += read; - if (read == 0 && !looping_) { + if (read == 0 && !looping_) + { playing_ = false; break; } - if (read == 0 && loop_point_) { + if (read == 0 && loop_point_) + { ogg_.seek(*loop_point_); } - if (read == 0 && !loop_point_) { + if (read == 0 && !loop_point_) + { ogg_.seek(0); } } while (total < buffer.size()); @@ -99,33 +116,39 @@ std::size_t OggPlayer::generate(tcb::span> buffer) { } template -void OggPlayer::seek(float position_seconds) { +void OggPlayer::seek(float position_seconds) +{ ogg_.seek(static_cast(position_seconds * sample_rate())); } template -void OggPlayer::loop_point_seconds(float loop_point) { +void OggPlayer::loop_point_seconds(float loop_point) +{ std::size_t rate = sample_rate(); loop_point = static_cast(std::round(loop_point * rate)); } template -void OggPlayer::reset() { +void OggPlayer::reset() +{ ogg_.seek(0); } template -std::size_t OggPlayer::sample_rate() const { +std::size_t OggPlayer::sample_rate() const +{ return ogg_.sample_rate(); } template -float OggPlayer::duration_seconds() const { +float OggPlayer::duration_seconds() const +{ return ogg_.duration_seconds(); } template -std::optional OggPlayer::loop_point_seconds() const { +std::optional OggPlayer::loop_point_seconds() const +{ if (!loop_point_) return std::nullopt; @@ -133,7 +156,8 @@ std::optional OggPlayer::loop_point_seconds() const { } template -float OggPlayer::position_seconds() const { +float OggPlayer::position_seconds() const +{ return ogg_.position_seconds(); } diff --git a/src/audio/ogg_player.hpp b/src/audio/ogg_player.hpp index 049d39862..f80ae7734 100644 --- a/src/audio/ogg_player.hpp +++ b/src/audio/ogg_player.hpp @@ -25,10 +25,12 @@ #include "ogg.hpp" #include "source.hpp" -namespace srb2::audio { +namespace srb2::audio +{ template -class OggPlayer final : public Source { +class OggPlayer final : public Source +{ bool playing_; bool looping_; std::optional loop_point_; diff --git a/src/audio/resample.cpp b/src/audio/resample.cpp index a64d0af13..d82282ba6 100644 --- a/src/audio/resample.cpp +++ b/src/audio/resample.cpp @@ -23,7 +23,8 @@ using namespace srb2::audio; template Resampler::Resampler(std::shared_ptr>&& source, float ratio) - : source_(std::forward>>(source)), ratio_(ratio) { + : source_(std::forward>>(source)), ratio_(ratio) +{ } template @@ -36,11 +37,13 @@ template Resampler& Resampler::operator=(Resampler&& r) = default; template -size_t Resampler::generate(tcb::span> buffer) { +size_t Resampler::generate(tcb::span> buffer) +{ if (!source_) return 0; - if (ratio_ == 1.f) { + if (ratio_ == 1.f) + { // fast path - generate directly from source size_t source_read = source_->generate(buffer); return source_read; @@ -48,21 +51,25 @@ size_t Resampler::generate(tcb::span> buffer) { size_t written = 0; - while (written < buffer.size()) { + while (written < buffer.size()) + { // do we need a refill? - if (buf_.size() == 0 || pos_ >= static_cast(buf_.size() - 1)) { + if (buf_.size() == 0 || pos_ >= static_cast(buf_.size() - 1)) + { pos_ -= buf_.size(); last_ = buf_.size() == 0 ? Sample {} : buf_.back(); buf_.clear(); buf_.resize(512); size_t source_read = source_->generate(buf_); buf_.resize(source_read); - if (source_read == 0) { + if (source_read == 0) + { break; } } - if (pos_ < 0) { + if (pos_ < 0) + { buffer[written] = (buf_[0] - last_) * pos_frac_ + last_; advance(ratio_); written++; diff --git a/src/audio/resample.hpp b/src/audio/resample.hpp index 7aab4f674..0936db7b8 100644 --- a/src/audio/resample.hpp +++ b/src/audio/resample.hpp @@ -21,10 +21,12 @@ #include "sound_chunk.hpp" #include "source.hpp" -namespace srb2::audio { +namespace srb2::audio +{ template -class Resampler : public Source { +class Resampler : public Source +{ public: Resampler(std::shared_ptr>&& source_, float ratio); Resampler(const Resampler& r) = delete; @@ -44,7 +46,8 @@ private: int pos_ {0}; float pos_frac_ {0.f}; - void advance(float samples) { + void advance(float samples) + { pos_frac_ += samples; float integer; std::modf(pos_frac_, &integer); diff --git a/src/audio/sample.hpp b/src/audio/sample.hpp index b1f0298b5..7f671bc7a 100644 --- a/src/audio/sample.hpp +++ b/src/audio/sample.hpp @@ -12,21 +12,27 @@ #include -namespace srb2::audio { +namespace srb2::audio +{ template -struct Sample { +struct Sample +{ std::array amplitudes; - constexpr Sample& operator+=(const Sample& rhs) noexcept { - for (std::size_t i = 0; i < C; i++) { + constexpr Sample& operator+=(const Sample& rhs) noexcept + { + for (std::size_t i = 0; i < C; i++) + { amplitudes[i] += rhs.amplitudes[i]; } return *this; } - constexpr Sample& operator*=(float rhs) noexcept { - for (std::size_t i = 0; i < C; i++) { + constexpr Sample& operator*=(float rhs) noexcept + { + for (std::size_t i = 0; i < C; i++) + { amplitudes[i] *= rhs; } return *this; @@ -34,27 +40,33 @@ struct Sample { }; template -constexpr Sample operator+(const Sample& lhs, const Sample& rhs) noexcept { +constexpr Sample operator+(const Sample& lhs, const Sample& rhs) noexcept +{ Sample out; - for (std::size_t i = 0; i < C; i++) { + for (std::size_t i = 0; i < C; i++) + { out.amplitudes[i] = lhs.amplitudes[i] + rhs.amplitudes[i]; } return out; } template -constexpr Sample operator-(const Sample& lhs, const Sample& rhs) noexcept { +constexpr Sample operator-(const Sample& lhs, const Sample& rhs) noexcept +{ Sample out; - for (std::size_t i = 0; i < C; i++) { + for (std::size_t i = 0; i < C; i++) + { out.amplitudes[i] = lhs.amplitudes[i] - rhs.amplitudes[i]; } return out; } template -constexpr Sample operator*(const Sample& lhs, float rhs) noexcept { +constexpr Sample operator*(const Sample& lhs, float rhs) noexcept +{ Sample out; - for (std::size_t i = 0; i < C; i++) { + for (std::size_t i = 0; i < C; i++) + { out.amplitudes[i] = lhs.amplitudes[i] * rhs; } return out; @@ -64,12 +76,14 @@ template static constexpr float sample_to_float(T sample) noexcept; template <> -constexpr float sample_to_float(uint8_t sample) noexcept { +constexpr float sample_to_float(uint8_t sample) noexcept +{ return (sample / 128.f) - 1.f; } template <> -constexpr float sample_to_float(int16_t sample) noexcept { +constexpr float sample_to_float(int16_t sample) noexcept +{ return sample / 32768.f; } diff --git a/src/audio/sound_chunk.hpp b/src/audio/sound_chunk.hpp index 7fc0a45eb..8bae962da 100644 --- a/src/audio/sound_chunk.hpp +++ b/src/audio/sound_chunk.hpp @@ -14,9 +14,11 @@ #include "source.hpp" -namespace srb2::audio { +namespace srb2::audio +{ -struct SoundChunk { +struct SoundChunk +{ std::vector> samples; }; diff --git a/src/audio/sound_effect_player.cpp b/src/audio/sound_effect_player.cpp index a038ee3d8..620a22688 100644 --- a/src/audio/sound_effect_player.cpp +++ b/src/audio/sound_effect_player.cpp @@ -20,15 +20,18 @@ using srb2::audio::Sample; using srb2::audio::SoundEffectPlayer; using srb2::audio::Source; -size_t SoundEffectPlayer::generate(tcb::span> buffer) { +size_t SoundEffectPlayer::generate(tcb::span> buffer) +{ if (!chunk_) return 0; - if (position_ >= chunk_->samples.size()) { + if (position_ >= chunk_->samples.size()) + { return 0; } size_t written = 0; - for (; position_ < chunk_->samples.size() && written < buffer.size(); position_++) { + for (; position_ < chunk_->samples.size() && written < buffer.size(); position_++) + { float mono_sample = chunk_->samples[position_].amplitudes[0]; float sep_pan = ((sep_ + 1.f) / 2.f) * (3.14159 / 2.f); @@ -41,23 +44,27 @@ size_t SoundEffectPlayer::generate(tcb::span> buffer) { return written; } -void SoundEffectPlayer::start(const SoundChunk* chunk, float volume, float sep) { +void SoundEffectPlayer::start(const SoundChunk* chunk, float volume, float sep) +{ this->update(volume, sep); position_ = 0; chunk_ = chunk; } -void SoundEffectPlayer::update(float volume, float sep) { +void SoundEffectPlayer::update(float volume, float sep) +{ volume_ = volume; sep_ = sep; } -void SoundEffectPlayer::reset() { +void SoundEffectPlayer::reset() +{ position_ = 0; chunk_ = nullptr; } -bool SoundEffectPlayer::finished() const { +bool SoundEffectPlayer::finished() const +{ if (!chunk_) return true; if (position_ >= chunk_->samples.size()) @@ -65,7 +72,8 @@ bool SoundEffectPlayer::finished() const { return false; } -bool SoundEffectPlayer::is_playing_chunk(const SoundChunk* chunk) const { +bool SoundEffectPlayer::is_playing_chunk(const SoundChunk* chunk) const +{ return chunk_ == chunk; } diff --git a/src/audio/sound_effect_player.hpp b/src/audio/sound_effect_player.hpp index 99f5edb9e..6fce34700 100644 --- a/src/audio/sound_effect_player.hpp +++ b/src/audio/sound_effect_player.hpp @@ -17,9 +17,11 @@ #include "sound_chunk.hpp" #include "source.hpp" -namespace srb2::audio { +namespace srb2::audio +{ -class SoundEffectPlayer : public Source<2> { +class SoundEffectPlayer : public Source<2> +{ public: virtual std::size_t generate(tcb::span> buffer) override final; diff --git a/src/audio/source.hpp b/src/audio/source.hpp index ea4be8761..9f9471f94 100644 --- a/src/audio/source.hpp +++ b/src/audio/source.hpp @@ -16,10 +16,12 @@ #include "sample.hpp" -namespace srb2::audio { +namespace srb2::audio +{ template -class Source { +class Source +{ public: virtual std::size_t generate(tcb::span> buffer) = 0; diff --git a/src/audio/wav.cpp b/src/audio/wav.cpp index 751c87b41..c1bcd7977 100644 --- a/src/audio/wav.cpp +++ b/src/audio/wav.cpp @@ -18,7 +18,8 @@ using namespace srb2; using srb2::audio::Wav; -namespace { +namespace +{ constexpr const uint32_t kMagicRIFF = 0x46464952; constexpr const uint32_t kMagicWAVE = 0x45564157; @@ -29,17 +30,20 @@ constexpr const uint16_t kFormatPcm = 1; constexpr const std::size_t kRiffHeaderLength = 8; -struct RiffHeader { +struct RiffHeader +{ uint32_t magic; std::size_t filesize; }; -struct TagHeader { +struct TagHeader +{ uint32_t type; std::size_t length; }; -struct FmtTag { +struct FmtTag +{ uint16_t format; uint16_t channels; uint32_t rate; @@ -48,9 +52,12 @@ struct FmtTag { uint16_t bit_width; }; -struct DataTag {}; +struct DataTag +{ +}; -RiffHeader parse_riff_header(io::SpanStream& stream) { +RiffHeader parse_riff_header(io::SpanStream& stream) +{ if (io::remaining(stream) < kRiffHeaderLength) throw std::runtime_error("insufficient bytes remaining in stream"); @@ -60,7 +67,8 @@ RiffHeader parse_riff_header(io::SpanStream& stream) { return ret; } -TagHeader parse_tag_header(io::SpanStream& stream) { +TagHeader parse_tag_header(io::SpanStream& stream) +{ if (io::remaining(stream) < 8) throw std::runtime_error("insufficient bytes remaining in stream"); @@ -70,7 +78,8 @@ TagHeader parse_tag_header(io::SpanStream& stream) { return header; } -FmtTag parse_fmt_tag(io::SpanStream& stream) { +FmtTag parse_fmt_tag(io::SpanStream& stream) +{ if (io::remaining(stream) < 16) throw std::runtime_error("insufficient bytes in stream"); @@ -86,14 +95,16 @@ FmtTag parse_fmt_tag(io::SpanStream& stream) { } template -void visit_tag(Visitor& visitor, io::SpanStream& stream, const TagHeader& header) { +void visit_tag(Visitor& visitor, io::SpanStream& stream, const TagHeader& header) +{ if (io::remaining(stream) < header.length) throw std::runtime_error("insufficient bytes in stream"); const io::StreamSize start = stream.seek(io::SeekFrom::kCurrent, 0); const io::StreamSize dest = start + header.length; - switch (header.type) { + switch (header.type) + { case kMagicFmt: { FmtTag fmt_tag {parse_fmt_tag(stream)}; @@ -114,19 +125,23 @@ void visit_tag(Visitor& visitor, io::SpanStream& stream, const TagHeader& header stream.seek(io::SeekFrom::kStart, dest); } -std::vector read_uint8_samples_from_stream(io::SpanStream& stream, std::size_t count) { +std::vector read_uint8_samples_from_stream(io::SpanStream& stream, std::size_t count) +{ std::vector samples; samples.reserve(count); - for (std::size_t i = 0; i < count; i++) { + for (std::size_t i = 0; i < count; i++) + { samples.push_back(io::read_uint8(stream)); } return samples; } -std::vector read_int16_samples_from_stream(io::SpanStream& stream, std::size_t count) { +std::vector read_int16_samples_from_stream(io::SpanStream& stream, std::size_t count) +{ std::vector samples; samples.reserve(count); - for (std::size_t i = 0; i < count; i++) { + for (std::size_t i = 0; i < count; i++) + { samples.push_back(io::read_int16(stream)); } return samples; @@ -136,57 +151,70 @@ std::vector read_int16_samples_from_stream(io::SpanStream& stream, std: Wav::Wav() = default; -Wav::Wav(tcb::span data) { +Wav::Wav(tcb::span data) +{ io::SpanStream stream {data}; auto [magic, filesize] = parse_riff_header(stream); - if (magic != kMagicRIFF) { + if (magic != kMagicRIFF) + { throw std::runtime_error("invalid RIFF magic"); } - if (io::remaining(stream) < filesize) { + if (io::remaining(stream) < filesize) + { throw std::runtime_error("insufficient data in stream for RIFF's reported filesize"); } const io::StreamSize riff_end = stream.seek(io::SeekFrom::kCurrent, 0) + filesize; uint32_t type = io::read_uint32(stream); - if (type != kMagicWAVE) { + if (type != kMagicWAVE) + { throw std::runtime_error("RIFF in stream is not a WAVE"); } std::optional read_fmt; std::variant, std::vector> interleaved_samples; - while (stream.seek(io::SeekFrom::kCurrent, 0) < riff_end) { + while (stream.seek(io::SeekFrom::kCurrent, 0) < riff_end) + { TagHeader tag_header {parse_tag_header(stream)}; - if (io::remaining(stream) < tag_header.length) { + if (io::remaining(stream) < tag_header.length) + { throw std::runtime_error("WAVE tag length exceeds stream length"); } auto tag_visitor = srb2::Overload { - [&](const FmtTag& fmt) { - if (read_fmt) { + [&](const FmtTag& fmt) + { + if (read_fmt) + { throw std::runtime_error("WAVE has multiple 'fmt' tags"); } - if (fmt.format != kFormatPcm) { + if (fmt.format != kFormatPcm) + { throw std::runtime_error("Unsupported WAVE format (only PCM is supported)"); } read_fmt = fmt; }, - [&](const DataTag& data) { - if (!read_fmt) { + [&](const DataTag& data) + { + if (!read_fmt) + { throw std::runtime_error("unable to read data tag because no fmt tag was read"); } - if (tag_header.length % read_fmt->bytes_per_sample != 0) { + if (tag_header.length % read_fmt->bytes_per_sample != 0) + { throw std::runtime_error("data tag length not divisible by bytes_per_sample"); } const std::size_t sample_count = tag_header.length / read_fmt->bytes_per_sample; - switch (read_fmt->bit_width) { + switch (read_fmt->bit_width) + { case 8: interleaved_samples = std::move(read_uint8_samples_from_stream(stream, sample_count)); break; @@ -201,7 +229,8 @@ Wav::Wav(tcb::span data) { visit_tag(tag_visitor, stream, tag_header); } - if (!read_fmt) { + if (!read_fmt) + { throw std::runtime_error("WAVE did not have a fmt tag"); } @@ -210,27 +239,34 @@ Wav::Wav(tcb::span data) { sample_rate_ = read_fmt->rate; } -namespace { +namespace +{ template -std::size_t read_samples(std::size_t channels, - std::size_t offset, - const std::vector& samples, - tcb::span> buffer) noexcept { +std::size_t read_samples( + std::size_t channels, + std::size_t offset, + const std::vector& samples, + tcb::span> buffer +) noexcept +{ const std::size_t offset_interleaved = offset * channels; const std::size_t samples_size = samples.size(); const std::size_t buffer_size = buffer.size(); - if (offset_interleaved >= samples_size) { + if (offset_interleaved >= samples_size) + { return 0; } const std::size_t remainder = (samples_size - offset_interleaved) / channels; const std::size_t samples_to_read = std::min(buffer_size, remainder); - for (std::size_t i = 0; i < samples_to_read; i++) { + for (std::size_t i = 0; i < samples_to_read; i++) + { buffer[i].amplitudes[0] = 0.f; - for (std::size_t j = 0; j < channels; j++) { + for (std::size_t j = 0; j < channels; j++) + { buffer[i].amplitudes[0] += audio::sample_to_float(samples[i * channels + j + offset_interleaved]); } buffer[i].amplitudes[0] /= static_cast(channels); @@ -241,18 +277,20 @@ std::size_t read_samples(std::size_t channels, } // namespace -std::size_t Wav::get_samples(std::size_t offset, tcb::span> buffer) const noexcept { +std::size_t Wav::get_samples(std::size_t offset, tcb::span> buffer) const noexcept +{ auto samples_visitor = srb2::Overload { [&](const std::vector& samples) { return read_samples(channels(), offset, samples, buffer); }, - [&](const std::vector& samples) { - return read_samples(channels(), offset, samples, buffer); - }}; + [&](const std::vector& samples) + { return read_samples(channels(), offset, samples, buffer); }}; return std::visit(samples_visitor, interleaved_samples_); } -std::size_t Wav::interleaved_length() const noexcept { - auto samples_visitor = srb2::Overload {[](const std::vector& samples) { return samples.size(); }, - [](const std::vector& samples) { return samples.size(); }}; +std::size_t Wav::interleaved_length() const noexcept +{ + auto samples_visitor = srb2::Overload { + [](const std::vector& samples) { return samples.size(); }, + [](const std::vector& samples) { return samples.size(); }}; return std::visit(samples_visitor, interleaved_samples_); } diff --git a/src/audio/wav.hpp b/src/audio/wav.hpp index e571969e7..1dd2504d8 100644 --- a/src/audio/wav.hpp +++ b/src/audio/wav.hpp @@ -21,9 +21,11 @@ #include "../io/streams.hpp" #include "sample.hpp" -namespace srb2::audio { +namespace srb2::audio +{ -class Wav final { +class Wav final +{ std::variant, std::vector> interleaved_samples_; std::size_t channels_ = 1; std::size_t sample_rate_ = 44100; @@ -41,7 +43,8 @@ public: }; template , int> = 0> -inline Wav load_wav(I& stream) { +inline Wav load_wav(I& stream) +{ std::vector data = srb2::io::read_to_vec(stream); return Wav {data}; } diff --git a/src/audio/wav_player.cpp b/src/audio/wav_player.cpp index 64f9831f0..61bb95fea 100644 --- a/src/audio/wav_player.cpp +++ b/src/audio/wav_player.cpp @@ -13,7 +13,8 @@ using namespace srb2; using srb2::audio::WavPlayer; -WavPlayer::WavPlayer() : WavPlayer(audio::Wav {}) { +WavPlayer::WavPlayer() : WavPlayer(audio::Wav {}) +{ } WavPlayer::WavPlayer(const WavPlayer& rhs) = default; @@ -24,20 +25,25 @@ WavPlayer& WavPlayer::operator=(const WavPlayer& rhs) = default; WavPlayer& WavPlayer::operator=(WavPlayer&& rhs) noexcept = default; -WavPlayer::WavPlayer(audio::Wav&& wav) noexcept : wav_(std::forward(wav)), position_(0), looping_(false) { +WavPlayer::WavPlayer(audio::Wav&& wav) noexcept : wav_(std::forward(wav)), position_(0), looping_(false) +{ } -std::size_t WavPlayer::generate(tcb::span> buffer) { +std::size_t WavPlayer::generate(tcb::span> buffer) +{ std::size_t samples_read = 0; - while (samples_read < buffer.size()) { + while (samples_read < buffer.size()) + { const std::size_t read_this_time = wav_.get_samples(position_, buffer.subspan(samples_read)); position_ += read_this_time; samples_read += read_this_time; - if (position_ > wav_.length() && looping_) { + if (position_ > wav_.length() && looping_) + { position_ = 0; } - if (read_this_time == 0 && !looping_) { + if (read_this_time == 0 && !looping_) + { break; } } diff --git a/src/audio/wav_player.hpp b/src/audio/wav_player.hpp index dc6a98864..d7b12a23b 100644 --- a/src/audio/wav_player.hpp +++ b/src/audio/wav_player.hpp @@ -17,9 +17,11 @@ #include "source.hpp" #include "wav.hpp" -namespace srb2::audio { +namespace srb2::audio +{ -class WavPlayer final : public Source<1> { +class WavPlayer final : public Source<1> +{ Wav wav_; std::size_t position_; bool looping_; diff --git a/src/audio/xmp.cpp b/src/audio/xmp.cpp index 9e88f2a7f..6c1031a9a 100644 --- a/src/audio/xmp.cpp +++ b/src/audio/xmp.cpp @@ -16,11 +16,14 @@ using namespace srb2; using namespace srb2::audio; -XmpException::XmpException(int code) : code_(code) { +XmpException::XmpException(int code) : code_(code) +{ } -const char* XmpException::what() const noexcept { - switch (code_) { +const char* XmpException::what() const noexcept +{ + switch (code_) + { case -XMP_ERROR_INTERNAL: return "XMP_ERROR_INTERNAL"; case -XMP_ERROR_FORMAT: @@ -41,23 +44,27 @@ const char* XmpException::what() const noexcept { } template -Xmp::Xmp() : data_(), instance_(nullptr), module_loaded_(false), looping_(false) { +Xmp::Xmp() : data_(), instance_(nullptr), module_loaded_(false), looping_(false) +{ } template Xmp::Xmp(std::vector data) - : data_(std::move(data)), instance_(nullptr), module_loaded_(false), looping_(false) { + : data_(std::move(data)), instance_(nullptr), module_loaded_(false), looping_(false) +{ _init(); } template Xmp::Xmp(tcb::span data) - : data_(data.begin(), data.end()), instance_(nullptr), module_loaded_(false), looping_(false) { + : data_(data.begin(), data.end()), instance_(nullptr), module_loaded_(false), looping_(false) +{ _init(); } template -Xmp::Xmp(Xmp&& rhs) noexcept : Xmp() { +Xmp::Xmp(Xmp&& rhs) noexcept : Xmp() +{ std::swap(data_, rhs.data_); std::swap(instance_, rhs.instance_); std::swap(module_loaded_, rhs.module_loaded_); @@ -65,7 +72,8 @@ Xmp::Xmp(Xmp&& rhs) noexcept : Xmp() { } template -Xmp& Xmp::operator=(Xmp&& rhs) noexcept { +Xmp& Xmp::operator=(Xmp&& rhs) noexcept +{ std::swap(data_, rhs.data_); std::swap(instance_, rhs.instance_); std::swap(module_loaded_, rhs.module_loaded_); @@ -75,15 +83,18 @@ Xmp& Xmp::operator=(Xmp&& rhs) noexcept { }; template -Xmp::~Xmp() { - if (instance_) { +Xmp::~Xmp() +{ + if (instance_) + { xmp_free_context(instance_); instance_ = nullptr; } } template -std::size_t Xmp::play_buffer(tcb::span> buffer) { +std::size_t Xmp::play_buffer(tcb::span> buffer) +{ SRB2_ASSERT(instance_ != nullptr); SRB2_ASSERT(module_loaded_ == true); @@ -99,7 +110,8 @@ std::size_t Xmp::play_buffer(tcb::span> buffer) { } template -void Xmp::reset() { +void Xmp::reset() +{ SRB2_ASSERT(instance_ != nullptr); SRB2_ASSERT(module_loaded_ == true); @@ -107,7 +119,8 @@ void Xmp::reset() { } template -float Xmp::duration_seconds() const { +float Xmp::duration_seconds() const +{ SRB2_ASSERT(instance_ != nullptr); SRB2_ASSERT(module_loaded_ == true); @@ -117,7 +130,8 @@ float Xmp::duration_seconds() const { } template -void Xmp::seek(int position_ms) { +void Xmp::seek(int position_ms) +{ SRB2_ASSERT(instance_ != nullptr); SRB2_ASSERT(module_loaded_ == true); @@ -127,7 +141,8 @@ void Xmp::seek(int position_ms) { } template -void Xmp::_init() { +void Xmp::_init() +{ if (instance_) return; @@ -137,12 +152,14 @@ void Xmp::_init() { throw std::logic_error("Insufficient data from stream"); instance_ = xmp_create_context(); - if (instance_ == nullptr) { + if (instance_ == nullptr) + { throw std::bad_alloc(); } int result = xmp_load_module_from_memory(instance_, data_.data(), data_.size()); - if (result != 0) { + if (result != 0) + { xmp_free_context(instance_); instance_ = nullptr; throw XmpException(result); @@ -150,11 +167,13 @@ void Xmp::_init() { module_loaded_ = true; int flags = 0; - if constexpr (C == 1) { + if constexpr (C == 1) + { flags |= XMP_FORMAT_MONO; } result = xmp_start_player(instance_, 44100, flags); - if (result != 0) { + if (result != 0) + { xmp_release_module(instance_); module_loaded_ = false; xmp_free_context(instance_); diff --git a/src/audio/xmp.hpp b/src/audio/xmp.hpp index a5b443bfa..dc22550c4 100644 --- a/src/audio/xmp.hpp +++ b/src/audio/xmp.hpp @@ -7,7 +7,7 @@ // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- - #ifndef __SRB2_AUDIO_XMP_HPP__ +#ifndef __SRB2_AUDIO_XMP_HPP__ #define __SRB2_AUDIO_XMP_HPP__ #include @@ -22,9 +22,11 @@ #include "../io/streams.hpp" -namespace srb2::audio { +namespace srb2::audio +{ -class XmpException : public std::exception { +class XmpException : public std::exception +{ int code_; public: @@ -33,7 +35,8 @@ public: }; template -class Xmp final { +class Xmp final +{ std::vector data_; xmp_context instance_; bool module_loaded_; @@ -68,7 +71,8 @@ extern template class Xmp<1>; extern template class Xmp<2>; template , int> = 0> -inline Xmp load_xmp(I& stream) { +inline Xmp load_xmp(I& stream) +{ std::vector data = srb2::io::read_to_vec(stream); return Xmp {std::move(data)}; } diff --git a/src/audio/xmp_player.cpp b/src/audio/xmp_player.cpp index a08ee8bb5..2d869857a 100644 --- a/src/audio/xmp_player.cpp +++ b/src/audio/xmp_player.cpp @@ -15,7 +15,8 @@ using namespace srb2; using namespace srb2::audio; template -XmpPlayer::XmpPlayer(Xmp&& xmp) : xmp_(std::move(xmp)), buf_() { +XmpPlayer::XmpPlayer(Xmp&& xmp) : xmp_(std::move(xmp)), buf_() +{ } template @@ -28,14 +29,17 @@ template XmpPlayer::~XmpPlayer() = default; template -std::size_t XmpPlayer::generate(tcb::span> buffer) { +std::size_t XmpPlayer::generate(tcb::span> buffer) +{ buf_.resize(buffer.size()); std::size_t read = xmp_.play_buffer(tcb::make_span(buf_)); buf_.resize(read); std::size_t ret = std::min(buffer.size(), buf_.size()); - for (std::size_t i = 0; i < ret; i++) { - for (std::size_t j = 0; j < C; j++) { + for (std::size_t i = 0; i < ret; i++) + { + for (std::size_t j = 0; j < C; j++) + { buffer[i].amplitudes[j] = buf_[i][j] / 32768.f; } } @@ -44,12 +48,14 @@ std::size_t XmpPlayer::generate(tcb::span> buffer) { } template -float XmpPlayer::duration_seconds() const { +float XmpPlayer::duration_seconds() const +{ return xmp_.duration_seconds(); } template -void XmpPlayer::seek(float position_seconds) { +void XmpPlayer::seek(float position_seconds) +{ xmp_.seek(static_cast(std::round(position_seconds * 1000.f))); } diff --git a/src/audio/xmp_player.hpp b/src/audio/xmp_player.hpp index 5829dbd8a..865eabb5e 100644 --- a/src/audio/xmp_player.hpp +++ b/src/audio/xmp_player.hpp @@ -13,10 +13,12 @@ #include "source.hpp" #include "xmp.hpp" -namespace srb2::audio { +namespace srb2::audio +{ template -class XmpPlayer final : public Source { +class XmpPlayer final : public Source +{ Xmp xmp_; std::vector> buf_; diff --git a/src/cxxutil.hpp b/src/cxxutil.hpp index 82131768a..06f6f1adc 100644 --- a/src/cxxutil.hpp +++ b/src/cxxutil.hpp @@ -62,10 +62,12 @@ struct SourceLocation { class IErrorAssertHandler { public: static void handle(const SourceLocation& source_location, const char* expression) { - I_Error("Assertion failed at %s:%u: %s != true", - source_location.file_name, - source_location.line_number, - expression); + I_Error( + "Assertion failed at %s:%u: %s != true", + source_location.file_name, + source_location.line_number, + expression + ); } }; @@ -102,8 +104,10 @@ class NotNull final { T ptr_; public: - static_assert(std::is_convertible_v() != nullptr), bool>, - "T is not comparable with nullptr_t"); + static_assert( + std::is_convertible_v() != nullptr), bool>, + "T is not comparable with nullptr_t" + ); /// @brief Move-construct from the pointer value U, asserting that it is not null. Allows construction of a /// NotNull from any compatible pointer U, for example with polymorphic classes. diff --git a/src/sdl/new_sound.cpp b/src/sdl/new_sound.cpp index 3052ee587..4d77b180d 100644 --- a/src/sdl/new_sound.cpp +++ b/src/sdl/new_sound.cpp @@ -59,7 +59,8 @@ static vector> sound_effect_channels; static void (*music_fade_callback)(); -void* I_GetSfx(sfxinfo_t* sfx) { +void* I_GetSfx(sfxinfo_t* sfx) +{ if (sfx->lumpnum == LUMPERROR) sfx->lumpnum = S_GetSfxLumpNum(sfx); sfx->length = W_LumpLength(sfx->lumpnum); @@ -78,14 +79,18 @@ void* I_GetSfx(sfxinfo_t* sfx) { return heap_chunk; } -void I_FreeSfx(sfxinfo_t* sfx) { - if (sfx->data) { +void I_FreeSfx(sfxinfo_t* sfx) +{ + if (sfx->data) + { SoundChunk* chunk = static_cast(sfx->data); auto _ = srb2::finally([chunk]() { delete chunk; }); // Stop any channels playing this chunk - for (auto& player : sound_effect_channels) { - if (player->is_playing_chunk(chunk)) { + for (auto& player : sound_effect_channels) + { + if (player->is_playing_chunk(chunk)) + { player->reset(); } } @@ -94,22 +99,27 @@ void I_FreeSfx(sfxinfo_t* sfx) { sfx->lumpnum = LUMPERROR; } -namespace { +namespace +{ -class SdlAudioLockHandle { +class SdlAudioLockHandle +{ public: SdlAudioLockHandle() { SDL_LockAudio(); } ~SdlAudioLockHandle() { SDL_UnlockAudio(); } }; -void audio_callback(void* userdata, Uint8* buffer, int len) { +void audio_callback(void* userdata, Uint8* buffer, int len) +{ // The SDL Audio lock is implied to be held during callback. - try { + try + { Sample<2>* float_buffer = reinterpret_cast*>(buffer); size_t float_len = len / 8; - for (size_t i = 0; i < float_len; i++) { + for (size_t i = 0; i < float_len; i++) + { float_buffer[i] = Sample<2> {0.f, 0.f}; } @@ -118,20 +128,25 @@ void audio_callback(void* userdata, Uint8* buffer, int len) { master->generate(tcb::span {float_buffer, float_len}); - for (size_t i = 0; i < float_len; i++) { + for (size_t i = 0; i < float_len; i++) + { float_buffer[i] = { std::clamp(float_buffer[i].amplitudes[0], -1.f, 1.f), std::clamp(float_buffer[i].amplitudes[1], -1.f, 1.f), }; } - } catch (...) { + } + catch (...) + { } return; } -void initialize_sound() { - if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { +void initialize_sound() +{ + if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) + { CONS_Alert(CONS_ERROR, "Error initializing SDL Audio: %s\n", SDL_GetError()); return; } @@ -143,7 +158,8 @@ void initialize_sound() { desired.freq = 44100; desired.callback = audio_callback; - if (SDL_OpenAudio(&desired, NULL) < 0) { + if (SDL_OpenAudio(&desired, NULL) < 0) + { CONS_Alert(CONS_ERROR, "Failed to open SDL Audio device: %s\n", SDL_GetError()); SDL_QuitSubSystem(SDL_INIT_AUDIO); return; @@ -165,7 +181,8 @@ void initialize_sound() { master->add_source(gain_sound_effects); master->add_source(gain_music); mixer_music->add_source(music_player); - for (size_t i = 0; i < static_cast(cv_numChannels.value); i++) { + for (size_t i = 0; i < static_cast(cv_numChannels.value); i++) + { shared_ptr player = make_shared(); sound_effect_channels.push_back(player); mixer_sound_effects->add_source(player); @@ -177,25 +194,30 @@ void initialize_sound() { } // namespace -void I_StartupSound(void) { +void I_StartupSound(void) +{ if (!sound_started) initialize_sound(); } -void I_ShutdownSound(void) { +void I_ShutdownSound(void) +{ SdlAudioLockHandle _; - for (auto& channel : sound_effect_channels) { + for (auto& channel : sound_effect_channels) + { *channel = audio::SoundEffectPlayer(); } } -void I_UpdateSound(void) { +void I_UpdateSound(void) +{ // The SDL audio lock is re-entrant, so it is safe to lock twice // for the "fade to stop music" callback later. SdlAudioLockHandle _; - if (music_fade_callback && !music_player->fading()) { + if (music_fade_callback && !music_player->fading()) + { auto old_callback = music_fade_callback; music_fade_callback = nullptr; (old_callback()); @@ -207,7 +229,8 @@ void I_UpdateSound(void) { // SFX I/O // -INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel) { +INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel) +{ (void) pitch; (void) priority; @@ -217,16 +240,21 @@ INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priori return -1; shared_ptr player_channel; - if (channel < 0) { + if (channel < 0) + { // find a free sfx channel - for (size_t i = 0; i < sound_effect_channels.size(); i++) { - if (sound_effect_channels[i]->finished()) { + for (size_t i = 0; i < sound_effect_channels.size(); i++) + { + if (sound_effect_channels[i]->finished()) + { player_channel = sound_effect_channels[i]; channel = i; break; } } - } else { + } + else + { player_channel = sound_effect_channels[channel]; } @@ -245,7 +273,8 @@ INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priori return channel; } -void I_StopSound(INT32 handle) { +void I_StopSound(INT32 handle) +{ SdlAudioLockHandle _; if (sound_effect_channels.empty()) @@ -262,7 +291,8 @@ void I_StopSound(INT32 handle) { sound_effect_channels[index]->reset(); } -boolean I_SoundIsPlaying(INT32 handle) { +boolean I_SoundIsPlaying(INT32 handle) +{ SdlAudioLockHandle _; // Handle is channel index @@ -280,7 +310,8 @@ boolean I_SoundIsPlaying(INT32 handle) { return sound_effect_channels[index]->finished() ? 0 : 1; } -void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch) { +void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch) +{ (void) pitch; SdlAudioLockHandle _; @@ -297,18 +328,21 @@ void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch) { return; shared_ptr& channel = sound_effect_channels[index]; - if (!channel->finished()) { + if (!channel->finished()) + { float vol_float = static_cast(vol) / 255.f; float sep_float = static_cast(sep) / 127.f - 1.f; channel->update(vol_float, sep_float); } } -void I_SetSfxVolume(int volume) { +void I_SetSfxVolume(int volume) +{ SdlAudioLockHandle _; float vol = static_cast(volume) / 100.f; - if (gain_sound_effects) { + if (gain_sound_effects) + { gain_sound_effects->gain(vol * vol * vol); } } @@ -317,7 +351,8 @@ void I_SetSfxVolume(int volume) { // MUSIC SYSTEM /// ------------------------ -void I_InitMusic(void) { +void I_InitMusic(void) +{ if (!sound_started) initialize_sound(); @@ -326,7 +361,8 @@ void I_InitMusic(void) { *music_player = audio::MusicPlayer(); } -void I_ShutdownMusic(void) { +void I_ShutdownMusic(void) +{ SdlAudioLockHandle _; *music_player = audio::MusicPlayer(); @@ -336,7 +372,8 @@ void I_ShutdownMusic(void) { // MUSIC PROPERTIES /// ------------------------ -musictype_t I_SongType(void) { +musictype_t I_SongType(void) +{ if (!music_player) return MU_NONE; @@ -344,11 +381,13 @@ musictype_t I_SongType(void) { std::optional music_type = music_player->music_type(); - if (music_type == std::nullopt) { + if (music_type == std::nullopt) + { return MU_NONE; } - switch (*music_type) { + switch (*music_type) + { case audio::MusicType::kOgg: return MU_OGG; case audio::MusicType::kGme: @@ -360,7 +399,8 @@ musictype_t I_SongType(void) { } } -boolean I_SongPlaying(void) { +boolean I_SongPlaying(void) +{ if (!music_player) return false; @@ -369,7 +409,8 @@ boolean I_SongPlaying(void) { return music_player->music_type().has_value(); } -boolean I_SongPaused(void) { +boolean I_SongPaused(void) +{ if (!music_player) return false; @@ -382,7 +423,8 @@ boolean I_SongPaused(void) { // MUSIC EFFECTS /// ------------------------ -boolean I_SetSongSpeed(float speed) { +boolean I_SetSongSpeed(float speed) +{ (void) speed; return false; } @@ -391,7 +433,8 @@ boolean I_SetSongSpeed(float speed) { // MUSIC SEEKING /// ------------------------ -UINT32 I_GetSongLength(void) { +UINT32 I_GetSongLength(void) +{ if (!music_player) return 0; @@ -405,13 +448,15 @@ UINT32 I_GetSongLength(void) { return static_cast(std::round(*duration * 1000.f)); } -boolean I_SetSongLoopPoint(UINT32 looppoint) { +boolean I_SetSongLoopPoint(UINT32 looppoint) +{ if (!music_player) return 0; SdlAudioLockHandle _; - if (music_player->music_type() == audio::MusicType::kOgg) { + if (music_player->music_type() == audio::MusicType::kOgg) + { music_player->loop_point_seconds(looppoint / 1000.f); return true; } @@ -419,7 +464,8 @@ boolean I_SetSongLoopPoint(UINT32 looppoint) { return false; } -UINT32 I_GetSongLoopPoint(void) { +UINT32 I_GetSongLoopPoint(void) +{ if (!music_player) return 0; @@ -433,7 +479,8 @@ UINT32 I_GetSongLoopPoint(void) { return static_cast(std::round(*loop_point_seconds * 1000.f)); } -boolean I_SetSongPosition(UINT32 position) { +boolean I_SetSongPosition(UINT32 position) +{ if (!music_player) return false; @@ -443,7 +490,8 @@ boolean I_SetSongPosition(UINT32 position) { return true; } -UINT32 I_GetSongPosition(void) { +UINT32 I_GetSongPosition(void) +{ if (!music_player) return 0; @@ -457,50 +505,66 @@ UINT32 I_GetSongPosition(void) { return static_cast(std::round(*position_seconds * 1000.f)); } -void I_UpdateSongLagThreshold(void) { +void I_UpdateSongLagThreshold(void) +{ } -void I_UpdateSongLagConditions(void) { +void I_UpdateSongLagConditions(void) +{ } /// ------------------------ // MUSIC PLAYBACK /// ------------------------ -namespace { -void print_walk_ex_stack(const std::exception& ex) { +namespace +{ +void print_walk_ex_stack(const std::exception& ex) +{ CONS_Alert(CONS_WARNING, " Caused by: %s\n", ex.what()); - try { + try + { std::rethrow_if_nested(ex); - } catch (const std::exception& ex) { + } + catch (const std::exception& ex) + { print_walk_ex_stack(ex); } } -void print_ex(const std::exception& ex) { +void print_ex(const std::exception& ex) +{ CONS_Alert(CONS_WARNING, "Exception loading music: %s\n", ex.what()); - try { + try + { std::rethrow_if_nested(ex); - } catch (const std::exception& ex) { + } + catch (const std::exception& ex) + { print_walk_ex_stack(ex); } } } // namespace -boolean I_LoadSong(char* data, size_t len) { +boolean I_LoadSong(char* data, size_t len) +{ if (!music_player) return false; tcb::span data_span(reinterpret_cast(data), len); audio::MusicPlayer new_player; - try { + try + { new_player = audio::MusicPlayer {data_span}; - } catch (const std::exception& ex) { + } + catch (const std::exception& ex) + { print_ex(ex); return false; } - if (music_fade_callback && music_player->fading()) { + if (music_fade_callback && music_player->fading()) + { auto old_callback = music_fade_callback; music_fade_callback = nullptr; (old_callback)(); @@ -508,9 +572,12 @@ boolean I_LoadSong(char* data, size_t len) { SdlAudioLockHandle _; - try { + try + { *music_player = std::move(new_player); - } catch (const std::exception& ex) { + } + catch (const std::exception& ex) + { print_ex(ex); return false; } @@ -518,11 +585,13 @@ boolean I_LoadSong(char* data, size_t len) { return true; } -void I_UnloadSong(void) { +void I_UnloadSong(void) +{ if (!music_player) return; - if (music_fade_callback && music_player->fading()) { + if (music_fade_callback && music_player->fading()) + { auto old_callback = music_fade_callback; music_fade_callback = nullptr; (old_callback)(); @@ -533,7 +602,8 @@ void I_UnloadSong(void) { *music_player = audio::MusicPlayer(); } -boolean I_PlaySong(boolean looping) { +boolean I_PlaySong(boolean looping) +{ if (!music_player) return false; @@ -544,7 +614,8 @@ boolean I_PlaySong(boolean looping) { return true; } -void I_StopSong(void) { +void I_StopSong(void) +{ if (!music_player) return; @@ -553,7 +624,8 @@ void I_StopSong(void) { music_player->stop(); } -void I_PauseSong(void) { +void I_PauseSong(void) +{ if (!music_player) return; @@ -562,7 +634,8 @@ void I_PauseSong(void) { music_player->pause(); } -void I_ResumeSong(void) { +void I_ResumeSong(void) +{ if (!music_player) return; @@ -571,15 +644,18 @@ void I_ResumeSong(void) { music_player->unpause(); } -void I_SetMusicVolume(int volume) { +void I_SetMusicVolume(int volume) +{ float vol = static_cast(volume) / 100.f; - if (gain_music) { + if (gain_music) + { gain_music->gain(vol * vol * vol); } } -boolean I_SetSongTrack(int track) { +boolean I_SetSongTrack(int track) +{ (void) track; return false; } @@ -588,7 +664,8 @@ boolean I_SetSongTrack(int track) { // MUSIC FADING /// ------------------------ -void I_SetInternalMusicVolume(UINT8 volume) { +void I_SetInternalMusicVolume(UINT8 volume) +{ if (!music_player) return; @@ -598,7 +675,8 @@ void I_SetInternalMusicVolume(UINT8 volume) { music_player->internal_gain(gain); } -void I_StopFadingSong(void) { +void I_StopFadingSong(void) +{ if (!music_player) return; @@ -607,7 +685,8 @@ void I_StopFadingSong(void) { music_player->stop_fade(); } -boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void)) { +boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void)) +{ if (!music_player) return false; @@ -626,7 +705,8 @@ boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms return true; } -boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)) { +boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)) +{ if (!music_player) return false; @@ -644,7 +724,8 @@ boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)) { return true; } -static void stop_song_cb(void) { +static void stop_song_cb(void) +{ if (!music_player) return; @@ -653,11 +734,13 @@ static void stop_song_cb(void) { music_player->stop(); } -boolean I_FadeOutStopSong(UINT32 ms) { +boolean I_FadeOutStopSong(UINT32 ms) +{ return I_FadeSong(0.f, ms, stop_song_cb); } -boolean I_FadeInPlaySong(UINT32 ms, boolean looping) { +boolean I_FadeInPlaySong(UINT32 ms, boolean looping) +{ if (I_PlaySong(looping)) return I_FadeSongFromVolume(100, 0, ms, nullptr); else From be7cabc50f7e9792d2824a3392e3d1d747e2249c Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 9 Jan 2023 19:30:23 -0800 Subject: [PATCH 12/32] d_netfil: use CURLOPT_PROTOCOLS_STR if libcurl >= 7.85.0 (2022-08-31) --- src/d_netfil.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/d_netfil.c b/src/d_netfil.c index 5238f7028..5d99493de 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -56,6 +56,14 @@ #include +#ifdef HAVE_CURL +# if LIBCURL_VERSION_MAJOR >= 7 && LIBCURL_VERSION_MINOR >= 85 +# define PROTOCOLS_CURLOPT CURLOPT_PROTOCOLS_STR +# else +# define PROTOCOLS_CURLOPT CURLOPT_PROTOCOLS // deprecated in 7.85.0 +# endif +#endif + // Prototypes static boolean AddFileToSendQueue(INT32 node, const char *filename, UINT8 fileid); @@ -1802,7 +1810,7 @@ void CURLPrepareFile(const char* url, int dfilenum) curl_easy_setopt(http_handle, CURLOPT_URL, va("%s/%s", url, curl_realname)); // Only allow HTTP and HTTPS - curl_easy_setopt(http_handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS); + curl_easy_setopt(http_handle, PROTOCOLS_CURLOPT, CURLPROTO_HTTP|CURLPROTO_HTTPS); curl_easy_setopt(http_handle, CURLOPT_USERAGENT, va("Ring Racers/v%d.%d", VERSION, SUBVERSION)); // Set user agent as some servers won't accept invalid user agents. From 567bd2a84a3a385342aaad301771dd26e9b128ea Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 9 Jan 2023 19:32:28 -0800 Subject: [PATCH 13/32] d_netfil: use CURLOPT_XFERINFOFUNCTION Fixes deprecated warning since libcurl 7.32.0 (2013-08-12). --- src/d_netfil.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/d_netfil.c b/src/d_netfil.c index 5d99493de..3723ca75b 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -69,7 +69,7 @@ static boolean AddFileToSendQueue(INT32 node, const char *filename, UINT8 fileid #ifdef HAVE_CURL size_t curlwrite_data(void *ptr, size_t size, size_t nmemb, FILE *stream); -int curlprogress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow); +int curlprogress_callback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow); #endif // Sender structure @@ -131,8 +131,8 @@ static CURL *http_handle; static CURLM *multi_handle; boolean curl_running = false; boolean curl_failedwebdownload = false; -static double curl_dlnow; -static double curl_dltotal; +static curl_off_t curl_dlnow; +static curl_off_t curl_dltotal; static time_t curl_starttime; INT32 curl_transfers = 0; static int curl_runninghandles = 0; @@ -1771,7 +1771,7 @@ size_t curlwrite_data(void *ptr, size_t size, size_t nmemb, FILE *stream) return written; } -int curlprogress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) +int curlprogress_callback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { (void)clientp; (void)ultotal; @@ -1834,7 +1834,7 @@ void CURLPrepareFile(const char* url, int dfilenum) curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, curl_curfile->file); curl_easy_setopt(http_handle, CURLOPT_WRITEFUNCTION, curlwrite_data); curl_easy_setopt(http_handle, CURLOPT_NOPROGRESS, 0L); - curl_easy_setopt(http_handle, CURLOPT_PROGRESSFUNCTION, curlprogress_callback); + curl_easy_setopt(http_handle, CURLOPT_XFERINFOFUNCTION, curlprogress_callback); curl_curfile->status = FS_DOWNLOADING; lastfilenum = dfilenum; From dbdda14061a2450d95767dada915a462067f1acd Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 12 Jan 2023 04:33:33 -0800 Subject: [PATCH 14/32] Fix LOOPMS loop point for OGG player --- src/audio/ogg_player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/ogg_player.cpp b/src/audio/ogg_player.cpp index d9028dedb..a77146fbf 100644 --- a/src/audio/ogg_player.cpp +++ b/src/audio/ogg_player.cpp @@ -43,7 +43,7 @@ std::optional find_loop_point(const Ogg& ogg) { try { int loop_ms = std::stoi(copied); - int loop_point = std::round(static_cast(loop_ms) / (rate / 1000.)); + int loop_point = std::round(static_cast(rate) * (loop_ms / 1000.)); return loop_point; } catch (...) { From e194353da9d77b65b63e116aa58aee202f3c7b1f Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 12 Jan 2023 07:55:42 -0800 Subject: [PATCH 15/32] d_netfil.c: fix usage of CURLOPT_PROTOCOLS_STR blame be7cabc50 --- src/d_netfil.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/d_netfil.c b/src/d_netfil.c index 3723ca75b..ef99a2321 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -56,14 +56,6 @@ #include -#ifdef HAVE_CURL -# if LIBCURL_VERSION_MAJOR >= 7 && LIBCURL_VERSION_MINOR >= 85 -# define PROTOCOLS_CURLOPT CURLOPT_PROTOCOLS_STR -# else -# define PROTOCOLS_CURLOPT CURLOPT_PROTOCOLS // deprecated in 7.85.0 -# endif -#endif - // Prototypes static boolean AddFileToSendQueue(INT32 node, const char *filename, UINT8 fileid); @@ -1810,7 +1802,11 @@ void CURLPrepareFile(const char* url, int dfilenum) curl_easy_setopt(http_handle, CURLOPT_URL, va("%s/%s", url, curl_realname)); // Only allow HTTP and HTTPS - curl_easy_setopt(http_handle, PROTOCOLS_CURLOPT, CURLPROTO_HTTP|CURLPROTO_HTTPS); +#if LIBCURL_VERSION_MAJOR > 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 85) + curl_easy_setopt(http_handle, CURLOPT_PROTOCOLS_STR, "http,https"); +#else + curl_easy_setopt(http_handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS); // deprecated in 7.85.0 +#endif curl_easy_setopt(http_handle, CURLOPT_USERAGENT, va("Ring Racers/v%d.%d", VERSION, SUBVERSION)); // Set user agent as some servers won't accept invalid user agents. From b26cd786ec4deca1b50b51b543261b22ec738663 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 9 Jan 2023 20:13:59 -0800 Subject: [PATCH 16/32] Move all specialized code out of k_menufunc.c Adds new files: - menus/extras-statistics.c - menus/play-online-room-select.c - menus/transient/cup-select.c - menus/transient/explosions.c - menus/transient/gametype.c - menus/transient/message-box.c - menus/transient/virtual-keyboard.c --- src/k_menu.h | 20 + src/k_menufunc.c | 6801 +------------------- src/menus/CMakeLists.txt | 2 + src/menus/extras-1.c | 102 + src/menus/extras-addons.c | 332 + src/menus/extras-challenges.c | 562 ++ src/menus/extras-replay-hut.c | 230 + src/menus/extras-statistics.c | 99 + src/menus/main-1.c | 78 + src/menus/options-1.c | 181 + src/menus/options-data-addons.c | 7 + src/menus/options-data-erase-1.c | 42 + src/menus/options-data-erase-profile.c | 83 + src/menus/options-data-screenshots.c | 40 + src/menus/options-gameplay-item-toggles.c | 120 + src/menus/options-profiles-1.c | 193 + src/menus/options-profiles-edit-1.c | 143 + src/menus/options-profiles-edit-controls.c | 338 + src/menus/options-video-modes.c | 168 + src/menus/play-char-select.c | 1460 +++++ src/menus/play-local-1.c | 46 + src/menus/play-local-race-1.c | 20 + src/menus/play-local-race-difficulty.c | 63 + src/menus/play-local-race-time-attack.c | 94 + src/menus/play-online-1.c | 52 + src/menus/play-online-host.c | 71 + src/menus/play-online-join-ip.c | 67 + src/menus/play-online-room-select.c | 66 + src/menus/play-online-server-browser.c | 485 +- src/menus/transient/CMakeLists.txt | 5 + src/menus/transient/cup-select.c | 195 + src/menus/transient/explosions.c | 63 + src/menus/transient/gametype.c | 34 + src/menus/transient/level-select.c | 547 +- src/menus/transient/manual.c | 50 + src/menus/transient/message-box.c | 200 + src/menus/transient/pause-game.c | 285 + src/menus/transient/pause-replay.c | 156 + src/menus/transient/virtual-keyboard.c | 226 + 39 files changed, 6889 insertions(+), 6837 deletions(-) create mode 100644 src/menus/extras-statistics.c create mode 100644 src/menus/play-online-room-select.c create mode 100644 src/menus/transient/cup-select.c create mode 100644 src/menus/transient/explosions.c create mode 100644 src/menus/transient/gametype.c create mode 100644 src/menus/transient/message-box.c create mode 100644 src/menus/transient/virtual-keyboard.c diff --git a/src/k_menu.h b/src/k_menu.h index f7a9c9725..52319ee18 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -556,6 +556,7 @@ extern boolean menuwipe; extern consvar_t cv_showfocuslost; extern consvar_t cv_chooseskin, cv_serversort, cv_menujam_update; +extern consvar_t cv_autorecord; void M_SetMenuDelay(UINT8 i); @@ -569,6 +570,17 @@ void M_MapMenuControls(event_t *ev); boolean M_Responder(event_t *ev); boolean M_MenuButtonPressed(UINT8 pid, UINT32 bt); boolean M_MenuButtonHeld(UINT8 pid, UINT32 bt); + +boolean M_ChangeStringCvar(INT32 choice); + +boolean M_NextOpt(void); +boolean M_PrevOpt(void); + +boolean M_MenuConfirmPressed(UINT8 pid); +boolean M_MenuBackPressed(UINT8 pid); +boolean M_MenuExtraPressed(UINT8 pid); +boolean M_MenuExtraHeld(UINT8 pid); + void M_StartControlPanel(void); void M_ClearMenus(boolean callexitmenufunc); void M_SelectableClearMenus(INT32 choice); @@ -577,6 +589,8 @@ void M_GoBack(INT32 choice); void M_Ticker(void); void M_Init(void); +void M_MenuTypingInput(INT32 key); + extern menu_t MessageDef; void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtype); void M_StopMessage(INT32 choice); @@ -679,6 +693,7 @@ extern consvar_t *setup_playercvars[MAXSPLITSCREENPLAYERS][SPLITCV_MAX]; void M_CharacterSelectInit(void); void M_CharacterSelect(INT32 choice); +void M_SetupReadyExplosions(boolean charsel, UINT16 basex, UINT16 basey, UINT16 color); boolean M_CharacterSelectHandler(INT32 choice); void M_CharacterSelectTick(void); boolean M_CharacterSelectQuit(void); @@ -723,6 +738,8 @@ boolean M_CanShowLevelInList(INT16 mapnum, levelsearch_t *levelsearch); UINT16 M_CountLevelsToShowInList(levelsearch_t *levelsearch); UINT16 M_GetFirstLevelInList(UINT8 *i, levelsearch_t *levelsearch); UINT16 M_GetNextLevelInList(UINT16 mapnum, UINT8 *i, levelsearch_t *levelsearch); +void M_LevelSelectScrollDest(void); +boolean M_LevelListFromGametype(INT16 gt); void M_LevelSelectInit(INT32 choice); void M_CupSelectHandler(INT32 choice); @@ -730,6 +747,8 @@ void M_CupSelectTick(void); void M_LevelSelectHandler(INT32 choice); void M_LevelSelectTick(void); +void M_LevelSelected(INT16 add); + // dummy consvars for GP & match race setup extern consvar_t cv_dummygpdifficulty; extern consvar_t cv_dummykartspeed; @@ -916,6 +935,7 @@ void M_CheckProfileData(INT32 choice); // check if we have profiles. // profile selection menu void M_ProfileSelectInit(INT32 choice); +void M_FirstPickProfile(INT32 c); void M_HandleProfileSelect(INT32 ch); // profile edition diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 321dfcb31..ba2d02ce5 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -9,65 +9,12 @@ #include "doomdef.h" #include "d_main.h" -#include "d_netcmd.h" #include "console.h" -#include "r_local.h" #include "hu_stuff.h" -#include "g_game.h" -#include "g_input.h" -#include "m_argv.h" - -// Data. -#include "sounds.h" #include "s_sound.h" -#include "i_system.h" - -// Addfile -#include "filesrch.h" - #include "v_video.h" -#include "i_video.h" -#include "keys.h" -#include "z_zone.h" -#include "w_wad.h" -#include "p_local.h" -#include "p_setup.h" #include "f_finale.h" - -#ifdef HWRENDER -#include "hardware/hw_main.h" -#endif - -#include "d_net.h" -#include "mserv.h" #include "m_misc.h" -#include "m_anigif.h" -#include "byteptr.h" -#include "st_stuff.h" -#include "i_sound.h" -#include "i_time.h" -#include "k_kart.h" -#include "k_follower.h" -#include "d_player.h" // KITEM_ constants -#include "doomstat.h" // MAXSPLITSCREENPLAYERS -#include "k_grandprix.h" // MAXSPLITSCREENPLAYERS - -#include "i_joy.h" // for joystick menu controls - -// Condition Sets -#include "m_cond.h" - -// And just some randomness for the exits. -#include "m_random.h" - -#include "r_skins.h" - -#if defined(HAVE_SDL) -#include "SDL.h" -#if SDL_VERSION_ATLEAST(2,0,0) -#include "sdl/sdlmain.h" // JOYSTICK_HOTPLUG -#endif -#endif #ifdef PC_DOS #include // for snprintf @@ -98,30 +45,6 @@ struct menutransition_s menutransition; // Menu transition properties INT32 menuKey = -1; // keyboard key pressed for menu menucmd_t menucmd[MAXSPLITSCREENPLAYERS]; -// message prompt struct -struct menumessage_s menumessage; - -// Typing "sub"-menu -struct menutyping_s menutyping; - -// keyboard layouts -INT16 virtualKeyboard[5][13] = { - - {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0}, - {'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 0}, - {'a', 's', 'd', 'f', 'g', 'h', 'i', 'j', 'k', 'l', ';', '\'', '\\'}, - {'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, 0, 0}, - {KEY_SPACE, KEY_RSHIFT, KEY_BACKSPACE, KEY_CAPSLOCK, KEY_ENTER, 0, 0, 0, 0, 0, 0, 0, 0} -}; - -INT16 shift_virtualKeyboard[5][13] = { - - {'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 0}, - {'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', 0}, - {'A', 'S', 'D', 'F', 'G', 'H', 'I', 'J', 'K', 'L', ':', '\"', '|'}, - {'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 0, 0, 0}, - {KEY_SPACE, KEY_RSHIFT, KEY_BACKSPACE, KEY_CAPSLOCK, KEY_ENTER, 0, 0, 0, 0, 0, 0, 0, 0} -}; // finish wipes between screens boolean menuwipe = false; @@ -135,114 +58,37 @@ static boolean noFurtherInput = false; // ========================================================================== // Consvar onchange functions -static void Dummymenuplayer_OnChange(void); static void Dummystaff_OnChange(void); consvar_t cv_showfocuslost = CVAR_INIT ("showfocuslost", "Yes", CV_SAVE, CV_YesNo, NULL); -static CV_PossibleValue_t skins_cons_t[MAXSKINS+1] = {{1, DEFAULTSKIN}}; -consvar_t cv_chooseskin = CVAR_INIT ("chooseskin", DEFAULTSKIN, CV_HIDDEN, skins_cons_t, NULL); - consvar_t cv_menujam_update = CVAR_INIT ("menujam_update", "Off", CV_SAVE, CV_OnOff, NULL); static CV_PossibleValue_t menujam_cons_t[] = {{0, "menu"}, {1, "menu2"}, {2, "menu3"}, {0, NULL}}; static consvar_t cv_menujam = CVAR_INIT ("menujam", "0", CV_SAVE, menujam_cons_t, NULL); -static CV_PossibleValue_t serversort_cons_t[] = { - {0,"Ping"}, - {1,"AVG. Power Level"}, - {2,"Most Players"}, - {3,"Least Players"}, - {4,"Max Player Slots"}, - {5,"Gametype"}, - {0,NULL} -}; -consvar_t cv_serversort = CVAR_INIT ("serversort", "Ping", CV_CALL, serversort_cons_t, M_SortServerList); - // first time memory consvar_t cv_tutorialprompt = CVAR_INIT ("tutorialprompt", "On", CV_SAVE, CV_OnOff, NULL); -// autorecord demos for time attack -static consvar_t cv_autorecord = CVAR_INIT ("autorecord", "Yes", 0, CV_YesNo, NULL); - -CV_PossibleValue_t ghost_cons_t[] = {{0, "Hide"}, {1, "Show Character"}, {2, "Show All"}, {0, NULL}}; -CV_PossibleValue_t ghost2_cons_t[] = {{0, "Hide"}, {1, "Show"}, {0, NULL}}; - -consvar_t cv_ghost_besttime = CVAR_INIT ("ghost_besttime", "Show All", CV_SAVE, ghost_cons_t, NULL); -consvar_t cv_ghost_bestlap = CVAR_INIT ("ghost_bestlap", "Show All", CV_SAVE, ghost_cons_t, NULL); -consvar_t cv_ghost_last = CVAR_INIT ("ghost_last", "Show All", CV_SAVE, ghost_cons_t, NULL); -consvar_t cv_ghost_guest = CVAR_INIT ("ghost_guest", "Show", CV_SAVE, ghost2_cons_t, NULL); -consvar_t cv_ghost_staff = CVAR_INIT ("ghost_staff", "Show", CV_SAVE, ghost2_cons_t, NULL); - //Console variables used solely in the menu system. //todo: add a way to use non-console variables in the menu // or make these consvars legitimate like color or skin. -static void Splitplayers_OnChange(void); -CV_PossibleValue_t splitplayers_cons_t[] = {{1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}, {0, NULL}}; -consvar_t cv_splitplayers = CVAR_INIT ("splitplayers", "One", CV_CALL, splitplayers_cons_t, Splitplayers_OnChange); -static CV_PossibleValue_t dummymenuplayer_cons_t[] = {{0, "NOPE"}, {1, "P1"}, {2, "P2"}, {3, "P3"}, {4, "P4"}, {0, NULL}}; static CV_PossibleValue_t dummyteam_cons_t[] = {{0, "Spectator"}, {1, "Red"}, {2, "Blue"}, {0, NULL}}; static CV_PossibleValue_t dummyspectate_cons_t[] = {{0, "Spectator"}, {1, "Playing"}, {0, NULL}}; static CV_PossibleValue_t dummyscramble_cons_t[] = {{0, "Random"}, {1, "Points"}, {0, NULL}}; static CV_PossibleValue_t dummystaff_cons_t[] = {{0, "MIN"}, {100, "MAX"}, {0, NULL}}; -//static consvar_t cv_dummymenuplayer = CVAR_INIT ("dummymenuplayer", "P1", CV_HIDDEN|CV_CALL, dummymenuplayer_cons_t, Dummymenuplayer_OnChange); static consvar_t cv_dummyteam = CVAR_INIT ("dummyteam", "Spectator", CV_HIDDEN, dummyteam_cons_t, NULL); //static cv_dummyspectate = CVAR_INITconsvar_t ("dummyspectate", "Spectator", CV_HIDDEN, dummyspectate_cons_t, NULL); static consvar_t cv_dummyscramble = CVAR_INIT ("dummyscramble", "Random", CV_HIDDEN, dummyscramble_cons_t, NULL); static consvar_t cv_dummystaff = CVAR_INIT ("dummystaff", "0", CV_HIDDEN|CV_CALL, dummystaff_cons_t, Dummystaff_OnChange); -consvar_t cv_dummyip = CVAR_INIT ("dummyip", "", CV_HIDDEN, NULL, NULL); -consvar_t cv_dummymenuplayer = CVAR_INIT ("dummymenuplayer", "P1", CV_HIDDEN|CV_CALL, dummymenuplayer_cons_t, Dummymenuplayer_OnChange); consvar_t cv_dummyspectate = CVAR_INIT ("dummyspectate", "Spectator", CV_HIDDEN, dummyspectate_cons_t, NULL); -INT16 menugametype = GT_RACE; - -consvar_t cv_dummyprofilename = CVAR_INIT ("dummyprofilename", "", CV_HIDDEN, NULL, NULL); -consvar_t cv_dummyprofileplayername = CVAR_INIT ("dummyprofileplayername", "", CV_HIDDEN, NULL, NULL); -consvar_t cv_dummyprofilekickstart = CVAR_INIT ("dummyprofilekickstart", "Off", CV_HIDDEN, CV_OnOff, NULL); - -consvar_t cv_dummygpdifficulty = CVAR_INIT ("dummygpdifficulty", "Normal", CV_HIDDEN, gpdifficulty_cons_t, NULL); -consvar_t cv_dummykartspeed = CVAR_INIT ("dummykartspeed", "Normal", CV_HIDDEN, dummykartspeed_cons_t, NULL); -consvar_t cv_dummygpencore = CVAR_INIT ("dummygpencore", "Off", CV_HIDDEN, CV_OnOff, NULL); - -static void M_UpdateAddonsSearch(void); -consvar_t cv_dummyaddonsearch = CVAR_INIT ("dummyaddonsearch", "", CV_HIDDEN|CV_CALL|CV_NOINIT, NULL, M_UpdateAddonsSearch); - -static CV_PossibleValue_t dummymatchbots_cons_t[] = { - {0, "Off"}, - {1, "Lv.1"}, - {2, "Lv.2"}, - {3, "Lv.3"}, - {4, "Lv.4"}, - {5, "Lv.5"}, - {6, "Lv.6"}, - {7, "Lv.7"}, - {8, "Lv.8"}, - {9, "Lv.9"}, - {10, "Lv.10"}, - {11, "Lv.11"}, - {12, "Lv.12"}, - {13, "Lv.MAX"}, - {0, NULL} -}; -consvar_t cv_dummymatchbots = CVAR_INIT ("dummymatchbots", "Off", CV_HIDDEN, dummymatchbots_cons_t, NULL); - -// for server fetch threads... -M_waiting_mode_t m_waiting_mode = M_NOT_WAITING; - // ========================================================================== // CVAR ONCHANGE EVENTS GO HERE // ========================================================================== // (there's only a couple anyway) -static void Dummymenuplayer_OnChange(void) -{ - if (cv_dummymenuplayer.value < 1) - CV_StealthSetValue(&cv_dummymenuplayer, splitscreen+1); - else if (cv_dummymenuplayer.value > splitscreen+1) - CV_StealthSetValue(&cv_dummymenuplayer, 1); -} - static void Dummystaff_OnChange(void) { #ifdef STAFFGHOSTS @@ -280,357 +126,11 @@ static void Dummystaff_OnChange(void) #endif //#ifdef STAFFGHOSTS } -void Screenshot_option_Onchange(void) -{ - // Screenshot opt is at #3, 0 based array obv. - OPTIONS_DataScreenshot[2].status = - (cv_screenshot_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED); - -} - -void Moviemode_mode_Onchange(void) -{ -#if 0 - INT32 i, cstart, cend; - for (i = op_screenshot_gif_start; i <= op_screenshot_apng_end; ++i) - OP_ScreenshotOptionsMenu[i].status = IT_DISABLED; - - switch (cv_moviemode.value) - { - case MM_GIF: - cstart = op_screenshot_gif_start; - cend = op_screenshot_gif_end; - break; - case MM_APNG: - cstart = op_screenshot_apng_start; - cend = op_screenshot_apng_end; - break; - default: - return; - } - for (i = cstart; i <= cend; ++i) - OP_ScreenshotOptionsMenu[i].status = IT_STRING|IT_CVAR; -#endif -} - -void Moviemode_option_Onchange(void) -{ - // opt 7 in a 0 based array, you get the idea... - OPTIONS_DataScreenshot[6].status = - (cv_movie_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED); -} - -void Addons_option_Onchange(void) -{ - // Option 2 will always be the textbar. - // (keep in mind this is a 0 indexed array and the first element is a header...) - OPTIONS_DataAddon[2].status = - (cv_addons_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED); -} - -static void M_EraseDataResponse(INT32 ch) -{ - if (ch == MA_NO) - return; - - S_StartSound(NULL, sfx_itrole); // bweh heh heh - - // Delete the data - if (optionsmenu.erasecontext == 2) - { - // SRB2Kart: This actually needs to be done FIRST, so that you don't immediately regain playtime/matches secrets - gamedata->totalplaytime = 0; - gamedata->matchesplayed = 0; - } - if (optionsmenu.erasecontext != 1) - G_ClearRecords(); - if (optionsmenu.erasecontext != 0) - M_ClearSecrets(); - - F_StartIntro(); - M_ClearMenus(true); -} - -void M_EraseData(INT32 choice) -{ - const char *eschoice, *esstr = M_GetText("Are you sure you want to erase\n%s?\n\nPress (A) to confirm or (B) to cancel\n"); - - optionsmenu.erasecontext = (UINT8)choice; - - if (choice == 0) - eschoice = M_GetText("Time Attack data"); - else if (choice == 1) - eschoice = M_GetText("Secrets data"); - else - eschoice = M_GetText("ALL game data"); - - M_StartMessage(va(esstr, eschoice), FUNCPTRCAST(M_EraseDataResponse), MM_YESNO); -} - // ========================================================================= // BASIC MENU HANDLING // ========================================================================= -UINT16 nummenucolors = 0; - -void M_AddMenuColor(UINT16 color) { - menucolor_t *c; - - if (color >= numskincolors) { - CONS_Printf("M_AddMenuColor: color %d does not exist.",color); - return; - } - - // SRB2Kart: I do not understand vanilla doesn't need this but WE do???!?!??! - if (!skincolors[color].accessible) { - return; - } - - c = (menucolor_t *)malloc(sizeof(menucolor_t)); - c->color = color; - if (menucolorhead == NULL) { - c->next = c; - c->prev = c; - menucolorhead = c; - menucolortail = c; - } else { - c->next = menucolorhead; - c->prev = menucolortail; - menucolortail->next = c; - menucolorhead->prev = c; - menucolortail = c; - } - - nummenucolors++; -} - -void M_MoveColorBefore(UINT16 color, UINT16 targ) { - menucolor_t *look, *c = NULL, *t = NULL; - - if (color == targ) - return; - if (color >= numskincolors) { - CONS_Printf("M_MoveColorBefore: color %d does not exist.",color); - return; - } - if (targ >= numskincolors) { - CONS_Printf("M_MoveColorBefore: target color %d does not exist.",targ); - return; - } - - for (look=menucolorhead;;look=look->next) { - if (look->color == color) - c = look; - else if (look->color == targ) - t = look; - if (c != NULL && t != NULL) - break; - if (look==menucolortail) - return; - } - - if (c == t->prev) - return; - - if (t==menucolorhead) - menucolorhead = c; - if (c==menucolortail) - menucolortail = c->prev; - - c->prev->next = c->next; - c->next->prev = c->prev; - - c->prev = t->prev; - c->next = t; - t->prev->next = c; - t->prev = c; -} - -void M_MoveColorAfter(UINT16 color, UINT16 targ) { - menucolor_t *look, *c = NULL, *t = NULL; - - if (color == targ) - return; - if (color >= numskincolors) { - CONS_Printf("M_MoveColorAfter: color %d does not exist.\n",color); - return; - } - if (targ >= numskincolors) { - CONS_Printf("M_MoveColorAfter: target color %d does not exist.\n",targ); - return; - } - - for (look=menucolorhead;;look=look->next) { - if (look->color == color) - c = look; - else if (look->color == targ) - t = look; - if (c != NULL && t != NULL) - break; - if (look==menucolortail) - return; - } - - if (t == c->prev) - return; - - if (t==menucolortail) - menucolortail = c; - else if (c==menucolortail) - menucolortail = c->prev; - - c->prev->next = c->next; - c->next->prev = c->prev; - - c->next = t->next; - c->prev = t; - t->next->prev = c; - t->next = c; -} - -UINT16 M_GetColorBefore(UINT16 color, UINT16 amount, boolean follower) -{ - menucolor_t *look = NULL; - - for (; amount > 0; amount--) - { - if (follower == true) - { - if (color == FOLLOWERCOLOR_OPPOSITE) - { - look = menucolortail; - color = menucolortail->color; - continue; - } - - if (color == FOLLOWERCOLOR_MATCH) - { - look = NULL; - color = FOLLOWERCOLOR_OPPOSITE; - continue; - } - - if (color == menucolorhead->color) - { - look = NULL; - color = FOLLOWERCOLOR_MATCH; - continue; - } - } - - if (color == 0 || color >= numskincolors) - { - CONS_Printf("M_GetColorBefore: color %d does not exist.\n",color); - return 0; - } - - if (look == NULL) - { - for (look = menucolorhead;; look = look->next) - { - if (look->color == color) - { - break; - } - if (look == menucolortail) - { - return 0; - } - } - } - - look = look->prev; - color = look->color; - } - return color; -} - -UINT16 M_GetColorAfter(UINT16 color, UINT16 amount, boolean follower) -{ - menucolor_t *look = NULL; - - for (; amount > 0; amount--) - { - if (follower == true) - { - if (color == menucolortail->color) - { - look = NULL; - color = FOLLOWERCOLOR_OPPOSITE; - continue; - } - - if (color == FOLLOWERCOLOR_OPPOSITE) - { - look = NULL; - color = FOLLOWERCOLOR_MATCH; - continue; - } - - if (color == FOLLOWERCOLOR_MATCH) - { - look = menucolorhead; - color = menucolorhead->color; - continue; - } - } - - if (color == 0 || color >= numskincolors) - { - CONS_Printf("M_GetColorAfter: color %d does not exist.\n",color); - return 0; - } - - if (look == NULL) - { - for (look = menucolorhead;; look = look->next) - { - if (look->color == color) - { - break; - } - if (look == menucolortail) - { - return 0; - } - } - } - - look = look->next; - color = look->color; - } - return color; -} - -void M_InitPlayerSetupColors(void) { - UINT8 i; - numskincolors = SKINCOLOR_FIRSTFREESLOT; - menucolorhead = menucolortail = NULL; - for (i=0; inext; - free(tmp); - } else { - free(look); - return; - } - } - - menucolorhead = menucolortail = NULL; -} - static void M_ChangeCvar(INT32 choice) { consvar_t *cv = currentMenu->menuitems[itemOn].itemaction.cvar; @@ -669,55 +169,7 @@ static void M_ChangeCvar(INT32 choice) } } -static boolean M_ChangeStringCvar(INT32 choice) -{ - consvar_t *cv = currentMenu->menuitems[itemOn].itemaction.cvar; - char buf[MAXSTRINGLENGTH]; - size_t len; - - if (shiftdown && choice >= 32 && choice <= 127) - choice = shiftxform[choice]; - - switch (choice) - { - case KEY_BACKSPACE: - len = strlen(cv->string); - if (len > 0) - { - S_StartSound(NULL, sfx_s3k5b); // Tails - M_Memcpy(buf, cv->string, len); - buf[len-1] = 0; - CV_Set(cv, buf); - } - return true; - case KEY_DEL: - if (cv->string[0]) - { - S_StartSound(NULL, sfx_s3k5b); // Tails - CV_Set(cv, ""); - } - return true; - default: - if (choice >= 32 && choice <= 127) - { - len = strlen(cv->string); - if (len < MAXSTRINGLENGTH - 1) - { - S_StartSound(NULL, sfx_s3k5b); // Tails - M_Memcpy(buf, cv->string, len); - buf[len++] = (char)choice; - buf[len] = 0; - CV_Set(cv, buf); - } - return true; - } - break; - } - - return false; -} - -static boolean M_NextOpt(void) +boolean M_NextOpt(void) { INT16 oldItemOn = itemOn; // prevent infinite loop @@ -744,7 +196,7 @@ static boolean M_NextOpt(void) return true; } -static boolean M_PrevOpt(void) +boolean M_PrevOpt(void) { INT16 oldItemOn = itemOn; // prevent infinite loop @@ -1214,7 +666,7 @@ boolean M_MenuButtonHeld(UINT8 pid, UINT32 bt) } // Returns true if we press the confirmation button -static boolean M_MenuConfirmPressed(UINT8 pid) +boolean M_MenuConfirmPressed(UINT8 pid) { return M_MenuButtonPressed(pid, MBT_A); } @@ -1225,7 +677,7 @@ static boolean M_MenuConfirmPressed(UINT8 pid) }*/ // Returns true if we press the Cancel button -static boolean M_MenuBackPressed(UINT8 pid) +boolean M_MenuBackPressed(UINT8 pid) { return (M_MenuButtonPressed(pid, MBT_B) || M_MenuButtonPressed(pid, MBT_X)); } @@ -1236,167 +688,17 @@ static boolean M_MenuBackPressed(UINT8 pid) }*/ // Retrurns true if we press the tertiary option button (C) -static boolean M_MenuExtraPressed(UINT8 pid) +boolean M_MenuExtraPressed(UINT8 pid) { return M_MenuButtonPressed(pid, MBT_C); } -static boolean M_MenuExtraHeld(UINT8 pid) +boolean M_MenuExtraHeld(UINT8 pid) { return M_MenuButtonHeld(pid, MBT_C); } -// Updates the x coordinate of the keybord so prevent it from going in weird places -static void M_UpdateKeyboardX(void) -{ - // 0s are only at the rightmost edges of the keyboard table, so just go backwards until we get something. - while (!virtualKeyboard[menutyping.keyboardy][menutyping.keyboardx]) - menutyping.keyboardx--; -} - -static boolean M_IsTypingKey(INT32 key) -{ - return key == KEY_BACKSPACE || key == KEY_ENTER || - key == KEY_ESCAPE || key == KEY_DEL || isprint(key); -} - -static void M_MenuTypingInput(INT32 key) -{ - - const UINT8 pid = 0; - - // Fade-in - - if (menutyping.menutypingclose) // closing - { - menutyping.menutypingfade--; - if (!menutyping.menutypingfade) - menutyping.active = false; - - return; // prevent inputs while closing the menu. - } - else // opening - { - menutyping.menutypingfade++; - if (menutyping.menutypingfade > 9) // Don't fade all the way, but have it VERY strong to be readable - menutyping.menutypingfade = 9; - else if (menutyping.menutypingfade < 9) - return; // Don't allow typing until it's fully opened. - } - - // Determine when to check for keyboard inputs or controller inputs using menuKey, which is the key passed here as argument. - if (!menutyping.keyboardtyping) // controller inputs - { - // we pressed a keyboard input that's not any of our buttons - if (M_IsTypingKey(key) && menucmd[pid].dpad_lr == 0 && menucmd[pid].dpad_ud == 0 - && !(menucmd[pid].buttons & MBT_A) - && !(menucmd[pid].buttons & MBT_B) - && !(menucmd[pid].buttons & MBT_C) - && !(menucmd[pid].buttons & MBT_X) - && !(menucmd[pid].buttons & MBT_Y) - && !(menucmd[pid].buttons & MBT_Z)) - { - menutyping.keyboardtyping = true; - } - } - else // Keyboard inputs. - { - // On the flipside, if we're pressing any keyboard input, switch to controller inputs. - if (!M_IsTypingKey(key) && ( - M_MenuButtonPressed(pid, MBT_A) - || M_MenuButtonPressed(pid, MBT_B) - || M_MenuButtonPressed(pid, MBT_C) - || M_MenuButtonPressed(pid, MBT_X) - || M_MenuButtonPressed(pid, MBT_Y) - || M_MenuButtonPressed(pid, MBT_Z) - || menucmd[pid].dpad_lr != 0 - || menucmd[pid].dpad_ud != 0 - )) - { - menutyping.keyboardtyping = false; - return; - } - - // OTHERWISE, process keyboard inputs for typing! - if (key == KEY_ENTER || key == KEY_ESCAPE) - { - menutyping.menutypingclose = true; // close menu. - return; - } - - } - - if (menucmd[pid].delay == 0 && !menutyping.keyboardtyping) // We must check for this here because we bypass the normal delay check to allow for normal keyboard inputs - { - if (menucmd[pid].dpad_ud > 0) // down - { - menutyping.keyboardy++; - if (menutyping.keyboardy > 4) - menutyping.keyboardy = 0; - - M_UpdateKeyboardX(); - M_SetMenuDelay(pid); - S_StartSound(NULL, sfx_s3k5b); - } - else if (menucmd[pid].dpad_ud < 0) // up - { - menutyping.keyboardy--; - if (menutyping.keyboardy < 0) - menutyping.keyboardy = 4; - - M_UpdateKeyboardX(); - M_SetMenuDelay(pid); - S_StartSound(NULL, sfx_s3k5b); - } - else if (menucmd[pid].dpad_lr > 0) // right - { - menutyping.keyboardx++; - if (!virtualKeyboard[menutyping.keyboardy][menutyping.keyboardx]) - menutyping.keyboardx = 0; - - M_SetMenuDelay(pid); - S_StartSound(NULL, sfx_s3k5b); - } - else if (menucmd[pid].dpad_lr < 0) // left - { - menutyping.keyboardx--; - if (menutyping.keyboardx < 0) - { - menutyping.keyboardx = 12; - M_UpdateKeyboardX(); - } - M_SetMenuDelay(pid); - S_StartSound(NULL, sfx_s3k5b); - } - else if (M_MenuConfirmPressed(pid)) - { - // Add the character. First though, check what we're pressing.... - INT16 c = virtualKeyboard[menutyping.keyboardy][menutyping.keyboardx]; - if (menutyping.keyboardshift ^ menutyping.keyboardcapslock) - c = shift_virtualKeyboard[menutyping.keyboardy][menutyping.keyboardx]; - - if (c == KEY_RSHIFT) - menutyping.keyboardshift = !menutyping.keyboardshift; - else if (c == KEY_CAPSLOCK) - menutyping.keyboardcapslock = !menutyping.keyboardcapslock; - else if (c == KEY_ENTER) - { - menutyping.menutypingclose = true; // close menu. - return; - } - else - { - M_ChangeStringCvar((INT32)c); // Write! - menutyping.keyboardshift = false; // undo shift if it had been pressed - } - - M_SetMenuDelay(pid); - S_StartSound(NULL, sfx_s3k5b); - } - } -} - static void M_HandleMenuInput(void) { void (*routine)(INT32 choice); // for some casting problem @@ -1741,6094 +1043,3 @@ void M_Init(void) M_UpdateMenuBGImage(true); } - -// ================================================== -// MESSAGE BOX (aka: a hacked, cobbled together menu) -// ================================================== -// Because this is just a "fake" menu, these definitions are not with the others -static menuitem_t MessageMenu[] = -{ - // TO HACK - {0, NULL, NULL, NULL, {NULL}, 0, 0} -}; - -menu_t MessageDef = -{ - 1, // # of menu items - NULL, // previous menu (TO HACK) - 0, // lastOn, flags (TO HACK) - MessageMenu, // menuitem_t -> - 0, 0, // x, y (TO HACK) - 0, 0, // extra1, extra2 - 0, 0, // transition tics - NULL, // drawing routine -> - NULL, // ticker routine - NULL, // init routine - NULL, // quit routine - NULL // input routine -}; - -// -// M_StringHeight -// -// Find string height from hu_font chars -// -static inline size_t M_StringHeight(const char *string) -{ - size_t h = 8, i; - - for (i = 0; i < strlen(string); i++) - if (string[i] == '\n') - h += 8; - - return h; -} - -// default message handler -void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtype) -{ - const UINT8 pid = 0; - size_t max = 0, start = 0, strlines = 0, i; - static char *message = NULL; - Z_Free(message); - message = Z_StrDup(string); - DEBFILE(message); - - // Rudementary word wrapping. - // Simple and effective. Does not handle nonuniform letter sizes, etc. but who cares. - for (i = 0; message[i]; i++) - { - if (message[i] == ' ') - { - start = i; - max += 4; - } - else if (message[i] == '\n') - { - strlines = i; - start = 0; - max = 0; - continue; - } - else if (message[i] & 0x80) - continue; - else - max += 8; - - // Start trying to wrap if presumed length exceeds the screen width. - if (max >= BASEVIDWIDTH && start > 0) - { - message[start] = '\n'; - max -= (start-strlines)*8; - strlines = start; - start = 0; - } - } - - strncpy(menumessage.message, string, MAXMENUMESSAGE); - menumessage.flags = itemtype; - *(void**)&menumessage.routine = routine; - menumessage.fadetimer = (gamestate == GS_WAITINGPLAYERS) ? 9 : 1; - menumessage.active = true; - - start = 0; - max = 0; - - if (!routine || menumessage.flags == MM_NOTHING) - { - menumessage.flags = MM_NOTHING; - menumessage.routine = M_StopMessage; - } - - // event routine - if (menumessage.flags == MM_EVENTHANDLER) - { - *(void**)&menumessage.eroutine = routine; - menumessage.routine = NULL; - } - - //added : 06-02-98: now draw a textbox around the message - // compute lenght max and the numbers of lines - for (strlines = 0; *(message+start); strlines++) - { - for (i = 0;i < strlen(message+start);i++) - { - if (*(message+start+i) == '\n') - { - if (i > max) - max = i; - start += i; - i = (size_t)-1; //added : 07-02-98 : damned! - start++; - break; - } - } - - if (i == strlen(message+start)) - { - start += i; - if (i > max) - max = i; - } - } - - menumessage.x = (INT16)((BASEVIDWIDTH - 8*max-16)/2); - menumessage.y = (INT16)((BASEVIDHEIGHT - M_StringHeight(message))/2); - - menumessage.m = (INT16)((strlines<<8)+max); - - M_SetMenuDelay(pid); // Set menu delay to avoid setting off any of the handlers. -} - -void M_StopMessage(INT32 choice) -{ - const char pid = 0; - (void) choice; - - menumessage.active = false; - M_SetMenuDelay(pid); -} - -// regular handler for MM_NOTHING and MM_YESNO -void M_HandleMenuMessage(void) -{ - const UINT8 pid = 0; - boolean btok = M_MenuConfirmPressed(pid); - boolean btnok = M_MenuBackPressed(pid); - - if (menumessage.fadetimer < 9) - menumessage.fadetimer++; - - switch (menumessage.flags) - { - // Send 1 to the routine if we're pressing A/B/X/Y - case MM_NOTHING: - { - // send 1 if any button is pressed, 0 otherwise. - if (btok || btnok) - menumessage.routine(0); - - break; - } - // Send 1 to the routine if we're pressing A/X, 2 if B/Y, 0 otherwise. - case MM_YESNO: - { - INT32 answer = MA_NONE; - if (btok) - answer = MA_YES; - else if (btnok) - answer = MA_NO; - - // send 1 if btok is pressed, 2 if nok is pressed, 0 otherwise. - if (answer) - { - menumessage.routine(answer); - M_StopMessage(0); - } - - break; - } - // MM_EVENTHANDLER: In M_Responder to allow full event compat. - default: - break; - } - - // if we detect any keypress, don't forget to set the menu delay regardless. - if (btok || btnok) - M_SetMenuDelay(pid); -} - -// ========= -// IMAGEDEFS -// ========= - -// Handles the ImageDefs. Just a specialized function that -// uses left and right movement. -void M_HandleImageDef(INT32 choice) -{ - const UINT8 pid = 0; - boolean exitmenu = false; - (void) choice; - - if (menucmd[pid].dpad_lr > 0) - { - if (itemOn >= (INT16)(currentMenu->numitems-1)) - return; - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - itemOn++; - } - else if (menucmd[pid].dpad_lr < 0) - { - if (!itemOn) - return; - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - itemOn--; - } - else if (M_MenuConfirmPressed(pid) || M_MenuButtonPressed(pid, MBT_X) || M_MenuButtonPressed(pid, MBT_Y)) - { - exitmenu = true; - M_SetMenuDelay(pid); - } - - - if (exitmenu) - { - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu, false); - else - M_ClearMenus(true); - } -} - -// ========= -// MAIN MENU -// ========= - -// Quit Game -static INT32 quitsounds[] = -{ - // holy shit we're changing things up! - // srb2kart: you ain't seen nothing yet - sfx_kc2e, - sfx_kc2f, - sfx_cdfm01, - sfx_ddash, - sfx_s3ka2, - sfx_s3k49, - sfx_slip, - sfx_tossed, - sfx_s3k7b, - sfx_itrolf, - sfx_itrole, - sfx_cdpcm9, - sfx_s3k4e, - sfx_s259, - sfx_3db06, - sfx_s3k3a, - sfx_peel, - sfx_cdfm28, - sfx_s3k96, - sfx_s3kc0s, - sfx_cdfm39, - sfx_hogbom, - sfx_kc5a, - sfx_kc46, - sfx_s3k92, - sfx_s3k42, - sfx_kpogos, - sfx_screec -}; - -void M_QuitResponse(INT32 ch) -{ - tic_t ptime; - INT32 mrand; - - if (ch == MA_YES) - { - if (!(netgame || cht_debug)) - { - mrand = M_RandomKey(sizeof(quitsounds) / sizeof(INT32)); - if (quitsounds[mrand]) - S_StartSound(NULL, quitsounds[mrand]); - - //added : 12-02-98: do that instead of I_WaitVbl which does not work - ptime = I_GetTime() + NEWTICRATE*2; // Shortened the quit time, used to be 2 seconds Tails 03-26-2001 - while (ptime > I_GetTime()) - { - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); - V_DrawSmallScaledPatch(0, 0, 0, W_CachePatchName("GAMEQUIT", PU_CACHE)); // Demo 3 Quit Screen Tails 06-16-2001 - I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001 - I_Sleep(cv_sleep.value); - I_UpdateTime(cv_timescale.value); - } - } - I_Quit(); - } -} - -void M_QuitSRB2(INT32 choice) -{ - // We pick index 0 which is language sensitive, or one at random, - // between 1 and maximum number. - (void)choice; - M_StartMessage("Are you sure you want to quit playing?\n\nPress (A) to confirm or (B) to cancel", FUNCPTRCAST(M_QuitResponse), MM_YESNO); -} - -// ========= -// PLAY MENU -// ========= - -// Character Select! -// @TODO: Splitscreen handling when profiles are added into the game. ...I probably won't be the one to handle this however. -Lat' - -struct setup_chargrid_s setup_chargrid[9][9]; -setup_player_t setup_player[MAXSPLITSCREENPLAYERS]; -struct setup_explosions_s setup_explosions[CSEXPLOSIONS]; - -UINT8 setup_followercategories[MAXFOLLOWERCATEGORIES][2]; -UINT8 setup_numfollowercategories; - -UINT8 setup_numplayers = 0; // This variable is very important, it was extended to determine how many players exist in ALL menus. -tic_t setup_animcounter = 0; - -UINT8 setup_page = 0; -UINT8 setup_maxpage = 0; // For charsel page to identify alts easier... - -// sets up the grid pos for the skin used by the profile. -static void M_SetupProfileGridPos(setup_player_t *p) -{ - profile_t *pr = PR_GetProfile(p->profilen); - INT32 i = R_SkinAvailable(pr->skinname); - INT32 alt = 0; // Hey it's my character's name! - - // While we're here, read follower values. - p->followern = K_FollowerAvailable(pr->follower); - - if (p->followern < 0 || p->followern >= numfollowers || followers[p->followern].category >= numfollowercategories || !K_FollowerUsable(p->followern)) - p->followercategory = p->followern = -1; - else - p->followercategory = followers[p->followern].category; - - p->followercolor = pr->followercolor; - - if (!R_SkinUsable(g_localplayers[0], i, false)) - { - i = GetSkinNumClosestToStats(skins[i].kartspeed, skins[i].kartweight, skins[i].flags, false); - } - - // Now position the grid for skin - p->gridx = skins[i].kartspeed-1; - p->gridy = skins[i].kartweight-1; - - // Now this put our cursor on the good alt - while (alt < setup_chargrid[p->gridx][p->gridy].numskins && setup_chargrid[p->gridx][p->gridy].skinlist[alt] != i) - alt++; - - p->clonenum = alt; - p->color = PR_GetProfileColor(pr); -} - -static void M_SetupMidGameGridPos(setup_player_t *p, UINT8 num) -{ - INT32 i = R_SkinAvailable(cv_skin[num].zstring); - INT32 alt = 0; // Hey it's my character's name! - - // While we're here, read follower values. - p->followern = cv_follower[num].value; - p->followercolor = cv_followercolor[num].value; - - if (p->followern < 0 || p->followern >= numfollowers || followers[p->followern].category >= numfollowercategories || !K_FollowerUsable(p->followern)) - p->followercategory = p->followern = -1; - else - p->followercategory = followers[p->followern].category; - - // Now position the grid for skin - p->gridx = skins[i].kartspeed-1; - p->gridy = skins[i].kartweight-1; - - // Now this put our cursor on the good alt - while (alt < setup_chargrid[p->gridx][p->gridy].numskins && setup_chargrid[p->gridx][p->gridy].skinlist[alt] != i) - alt++; - - p->clonenum = alt; - p->color = cv_playercolor[num].value; - return; // we're done here -} - - -void M_CharacterSelectInit(void) -{ - UINT8 i, j; - setup_maxpage = 0; - - // While we're editing profiles, don't unset the devices for p1 - if (gamestate == GS_MENU) - { - for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) - { - // Un-set devices for other players. - if (i != 0 || optionsmenu.profile) - { - CV_SetValue(&cv_usejoystick[i], -1); - CONS_Printf("M_CharacterSelectInit: Device for %d set to %d\n", i, -1); - } - } - } - - memset(setup_chargrid, -1, sizeof(setup_chargrid)); - for (i = 0; i < 9; i++) - { - for (j = 0; j < 9; j++) - setup_chargrid[i][j].numskins = 0; - } - - memset(setup_player, 0, sizeof(setup_player)); - setup_numplayers = 0; - - memset(setup_explosions, 0, sizeof(setup_explosions)); - setup_animcounter = 0; - - for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) - { - // Default to no follower / match colour. - setup_player[i].followern = -1; - setup_player[i].followercategory = -1; - setup_player[i].followercolor = FOLLOWERCOLOR_MATCH; - - // Set default selected profile to the last used profile for each player: - // (Make sure we don't overshoot it somehow if we deleted profiles or whatnot) - setup_player[i].profilen = min(cv_lastprofile[i].value, PR_GetNumProfiles()); - } - - for (i = 0; i < numskins; i++) - { - UINT8 x = skins[i].kartspeed-1; - UINT8 y = skins[i].kartweight-1; - - if (!R_SkinUsable(g_localplayers[0], i, false)) - continue; - - if (setup_chargrid[x][y].numskins >= MAXCLONES) - CONS_Alert(CONS_ERROR, "Max character alts reached for %d,%d\n", x+1, y+1); - else - { - setup_chargrid[x][y].skinlist[setup_chargrid[x][y].numskins] = i; - setup_chargrid[x][y].numskins++; - - setup_maxpage = max(setup_maxpage, setup_chargrid[x][y].numskins-1); - } - - for (j = 0; j < MAXSPLITSCREENPLAYERS; j++) - { - if (!strcmp(cv_skin[j].string, skins[i].name)) - { - setup_player[j].gridx = x; - setup_player[j].gridy = y; - setup_player[j].color = skins[i].prefcolor; - - // If we're on prpfile select, skip straight to CSSTEP_CHARS - // do the same if we're midgame, but make sure to consider splitscreen properly. - if ((optionsmenu.profile && j == 0) || (gamestate != GS_MENU && j <= splitscreen)) - { - if (optionsmenu.profile) // In menu, setting up profile character/follower - { - setup_player[j].profilen = optionsmenu.profilen; - PR_ApplyProfileLight(setup_player[j].profilen, 0); - M_SetupProfileGridPos(&setup_player[j]); - } - else // gamestate != GS_MENU, in that case, assume this is whatever profile we chose to play with. - { - setup_player[j].profilen = cv_lastprofile[j].value; - M_SetupMidGameGridPos(&setup_player[j], j); - } - - // Don't reapply the profile here, it was already applied. - setup_player[j].mdepth = CSSTEP_CHARS; - } - } - } - } - - setup_numfollowercategories = 0; - for (i = 0; i < numfollowercategories; i++) - { - if (followercategories[i].numincategory == 0) - continue; - - setup_followercategories[setup_numfollowercategories][0] = 0; - - for (j = 0; j < numfollowers; j++) - { - if (followers[j].category != i) - continue; - - if (!K_FollowerUsable(j)) - continue; - - setup_followercategories[setup_numfollowercategories][0]++; - setup_followercategories[setup_numfollowercategories][1] = i; - } - - if (!setup_followercategories[setup_numfollowercategories][0]) - continue; - - setup_numfollowercategories++; - } - - setup_page = 0; -} - -void M_CharacterSelect(INT32 choice) -{ - (void)choice; - PLAY_CharSelectDef.prevMenu = currentMenu; - M_SetupNextMenu(&PLAY_CharSelectDef, false); -} - -static void M_SetupReadyExplosions(boolean charsel, UINT16 basex, UINT16 basey, UINT16 color) -{ - UINT8 i, j; - UINT8 e = 0; - UINT16 maxx = (charsel ? 9 : gamedata->challengegridwidth); - UINT16 maxy = (charsel ? 9 : CHALLENGEGRIDHEIGHT); - - while (setup_explosions[e].tics) - { - e++; - if (e == CSEXPLOSIONS) - return; - } - - for (i = 0; i < 3; i++) - { - UINT8 t = 5 + (i*2); - UINT8 offset = (i+1); - - for (j = 0; j < 4; j++) - { - INT16 x = basex, y = basey; - - switch (j) - { - case 0: x += offset; break; - case 1: x -= offset; break; - case 2: y += offset; break; - case 3: y -= offset; break; - } - - if ((y < 0 || y >= maxy)) - continue; - - if (charsel || !challengegridloops) - { - if (x < 0 || x >= maxx) - continue; - } - - setup_explosions[e].tics = t; - setup_explosions[e].color = color; - setup_explosions[e].x = x; - setup_explosions[e].y = y; - - while (setup_explosions[e].tics) - { - e++; - if (e == CSEXPLOSIONS) - return; - } - } - } -} - - -// Gets the selected follower's state for a given setup player. -static void M_GetFollowerState(setup_player_t *p) -{ - - p->follower_state = &states[followers[p->followern].followstate]; - - if (p->follower_state->frame & FF_ANIMATE) - p->follower_tics = p->follower_state->var2; // support for FF_ANIMATE - else - p->follower_tics = p->follower_state->tics; - - p->follower_frame = p->follower_state->frame & FF_FRAMEMASK; -} - -static boolean M_DeviceAvailable(INT32 deviceID, UINT8 numPlayers) -{ - INT32 i; - - if (numPlayers == 0) - { - // All of them are available! - return true; - } - - for (i = 0; i < numPlayers; i++) - { - if (cv_usejoystick[i].value == deviceID) - { - // This one's already being used. - return false; - } - } - - // This device is good to go. - return true; -} - -static boolean M_HandlePressStart(setup_player_t *p, UINT8 num) -{ - INT32 i, j; - - if (optionsmenu.profile) - return false; // Don't allow for the possibility of SOMEHOW another player joining in. - - // Detect B press first ... this means P1 can actually exit out of the menu. - if (M_MenuBackPressed(num)) - { - M_SetMenuDelay(num); - - if (num == 0) - { - // We're done here. - memset(setup_player, 0, sizeof(setup_player)); // Reset this to avoid funky things with profile display. - M_GoBack(0); - return true; - } - - // Don't allow this press to ever count as "start". - return false; - } - - if (num != setup_numplayers) - { - // Only detect devices for the last player. - return false; - } - - // Now detect new devices trying to join. - for (i = 0; i < MAXDEVICES; i++) - { - if (deviceResponding[i] != true) - { - // No buttons are being pushed. - continue; - } - - if (M_DeviceAvailable(i, setup_numplayers) == true) - { - // Available!! Let's use this one!! - - // if P1 is setting up using keyboard (device 0), save their last used device. - // this is to allow them to retain controller usage when they play alone. - // Because let's face it, when you test mods, you're often lazy to grab your controller for menuing :) - if (!i && !num) - { - setup_player[num].ponedevice = cv_usejoystick[num].value; - } - else if (num) - { - // For any player past player 1, set controls to default profile controls, otherwise it's generally awful to do any menuing... - memcpy(&gamecontrol[num], gamecontroldefault, sizeof(gamecontroldefault)); - } - - - CV_SetValue(&cv_usejoystick[num], i); - CONS_Printf("M_HandlePressStart: Device for %d set to %d\n", num, i); - - for (j = num+1; j < MAXSPLITSCREENPLAYERS; j++) - { - // Un-set devices for other players. - CV_SetValue(&cv_usejoystick[j], -1); - CONS_Printf("M_HandlePressStart: Device for %d set to %d\n", j, -1); - } - - //setup_numplayers++; - p->mdepth = CSSTEP_PROFILE; - S_StartSound(NULL, sfx_s3k65); - - // Prevent quick presses for multiple players - for (j = 0; j < MAXSPLITSCREENPLAYERS; j++) - { - setup_player[j].delay = MENUDELAYTIME; - M_SetMenuDelay(j); - menucmd[j].buttonsHeld |= MBT_X; - } - - memset(deviceResponding, false, sizeof(deviceResponding)); - return true; - } - } - - return false; -} - -static boolean M_HandleCSelectProfile(setup_player_t *p, UINT8 num) -{ - const UINT8 maxp = PR_GetNumProfiles() -1; - UINT8 realnum = num; // Used for profile when using splitdevice. - UINT8 i; - - if (cv_splitdevice.value) - num = 0; - - if (menucmd[num].dpad_ud > 0) - { - p->profilen++; - if (p->profilen > maxp) - p->profilen = 0; - - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(num); - } - else if (menucmd[num].dpad_ud < 0) - { - if (p->profilen == 0) - p->profilen = maxp; - else - p->profilen--; - - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(num); - } - else if (M_MenuBackPressed(num)) - { - if (num == setup_numplayers-1) - { - - p->mdepth = CSSTEP_NONE; - S_StartSound(NULL, sfx_s3k5b); - - // Prevent quick presses for multiple players - for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) - { - setup_player[i].delay = MENUDELAYTIME; - M_SetMenuDelay(i); - menucmd[i].buttonsHeld |= MBT_X; - } - - if (num > 0) - { - CV_StealthSetValue(&cv_usejoystick[num], -1); - CONS_Printf("M_HandleCSelectProfile: Device for %d set to %d\n", num, -1); - } - - return true; - } - else - { - S_StartSound(NULL, sfx_s3kb2); - } - - M_SetMenuDelay(num); - } - else if (M_MenuConfirmPressed(num)) - { - SINT8 belongsTo = -1; - - if (p->profilen != PROFILE_GUEST) - { - for (i = 0; i < setup_numplayers; i++) - { - if (setup_player[i].mdepth > CSSTEP_PROFILE - && setup_player[i].profilen == p->profilen) - { - belongsTo = i; - break; - } - } - } - - if (belongsTo != -1 && belongsTo != num) - { - S_StartSound(NULL, sfx_s3k7b); - M_SetMenuDelay(num); - return false; - } - - // Apply the profile. - PR_ApplyProfile(p->profilen, realnum); // Otherwise P1 would inherit the last player's profile in splitdevice and that's not what we want... - M_SetupProfileGridPos(p); - - p->changeselect = 0; - - if (p->profilen == PROFILE_GUEST) - { - // Guest profile, always ask for options. - p->mdepth = CSSTEP_CHARS; - } - else - { - p->mdepth = CSSTEP_ASKCHANGES; - } - - S_StartSound(NULL, sfx_s3k63); - } - else if (M_MenuExtraPressed(num)) - { - UINT8 yourprofile = min(cv_lastprofile[realnum].value, PR_GetNumProfiles()); - if (p->profilen == yourprofile) - p->profilen = PROFILE_GUEST; - else - p->profilen = yourprofile; - S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s - M_SetMenuDelay(num); - } - - return false; - -} - - -static void M_HandleCharAskChange(setup_player_t *p, UINT8 num) -{ - - if (cv_splitdevice.value) - num = 0; - - // there's only 2 options so lol - if (menucmd[num].dpad_ud != 0) - { - p->changeselect = (p->changeselect == 0) ? 1 : 0; - - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(num); - } - else if (M_MenuBackPressed(num)) - { - p->changeselect = 0; - p->mdepth = CSSTEP_PROFILE; - - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(num); - } - else if (M_MenuConfirmPressed(num)) - { - if (!p->changeselect) - { - // no changes - M_GetFollowerState(p); - p->mdepth = CSSTEP_READY; - p->delay = TICRATE; - - S_StartSound(NULL, sfx_s3k4e); - M_SetupReadyExplosions(true, p->gridx, p->gridy, p->color); - } - else - { - // changes - p->mdepth = CSSTEP_CHARS; - S_StartSound(NULL, sfx_s3k63); - } - - M_SetMenuDelay(num); - } -} - -static boolean M_HandleCharacterGrid(setup_player_t *p, UINT8 num) -{ - UINT8 numclones; - INT32 skin; - - if (cv_splitdevice.value) - num = 0; - - if (menucmd[num].dpad_ud > 0) - { - p->gridy++; - if (p->gridy > 8) - p->gridy = 0; - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(num); - } - else if (menucmd[num].dpad_ud < 0) - { - p->gridy--; - if (p->gridy < 0) - p->gridy = 8; - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(num); - } - - if (menucmd[num].dpad_lr > 0) - { - p->gridx++; - if (p->gridx > 8) - p->gridx = 0; - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(num); - } - else if (menucmd[num].dpad_lr < 0) - { - p->gridx--; - if (p->gridx < 0) - p->gridx = 8; - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(num); - } - else if (M_MenuExtraPressed(num)) - { - p->gridx /= 3; - p->gridx = (3*p->gridx) + 1; - p->gridy /= 3; - p->gridy = (3*p->gridy) + 1; - S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s - M_SetMenuDelay(num); - } - - // try to set the clone num to the page # if possible. - p->clonenum = setup_page; - - // Process this after possible pad movement, - // this makes sure we don't have a weird ghost hover on a character with no clones. - numclones = setup_chargrid[p->gridx][p->gridy].numskins; - - if (p->clonenum >= numclones) - p->clonenum = 0; - - if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/) - { - skin = setup_chargrid[p->gridx][p->gridy].skinlist[setup_page]; - if (setup_page >= setup_chargrid[p->gridx][p->gridy].numskins || skin == -1) - { - S_StartSound(NULL, sfx_s3k7b); //sfx_s3kb2 - } - else - { - if (setup_page+1 == setup_chargrid[p->gridx][p->gridy].numskins) - p->mdepth = CSSTEP_COLORS; // Skip clones menu if there are none on this page. - else - p->mdepth = CSSTEP_ALTS; - - S_StartSound(NULL, sfx_s3k63); - } - - M_SetMenuDelay(num); - } - else if (M_MenuBackPressed(num)) - { - // for profiles / gameplay, exit out of the menu instantly, - // we don't want to go to the input detection menu. - if (optionsmenu.profile || gamestate != GS_MENU) - { - memset(setup_player, 0, sizeof(setup_player)); // Reset setup_player otherwise it does some VERY funky things. - M_SetMenuDelay(0); - M_GoBack(0); - return true; - } - else // in main menu - { - p->mdepth = CSSTEP_PROFILE; - S_StartSound(NULL, sfx_s3k5b); - } - M_SetMenuDelay(num); - } - - if (num == 0 && setup_numplayers == 1 && setup_maxpage) // ONLY one player. - { - if (M_MenuButtonPressed(num, MBT_L)) - { - if (setup_page == 0) - setup_page = setup_maxpage; - else - setup_page--; - - S_StartSound(NULL, sfx_s3k63); - M_SetMenuDelay(num); - } - else if (M_MenuButtonPressed(num, MBT_R)) - { - if (setup_page == setup_maxpage) - setup_page = 0; - else - setup_page++; - - S_StartSound(NULL, sfx_s3k63); - M_SetMenuDelay(num); - } - } - - return false; -} - -static void M_HandleCharRotate(setup_player_t *p, UINT8 num) -{ - UINT8 numclones = setup_chargrid[p->gridx][p->gridy].numskins; - - if (cv_splitdevice.value) - num = 0; - - if (menucmd[num].dpad_lr > 0) - { - p->clonenum++; - if (p->clonenum >= numclones) - p->clonenum = 0; - p->rotate = CSROTATETICS; - p->delay = CSROTATETICS; - S_StartSound(NULL, sfx_s3kc3s); - } - else if (menucmd[num].dpad_lr < 0) - { - p->clonenum--; - if (p->clonenum < 0) - p->clonenum = numclones-1; - p->rotate = -CSROTATETICS; - p->delay = CSROTATETICS; - S_StartSound(NULL, sfx_s3kc3s); - } - - if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/) - { - p->mdepth = CSSTEP_COLORS; - S_StartSound(NULL, sfx_s3k63); - M_SetMenuDelay(num); - } - else if (M_MenuBackPressed(num)) - { - p->mdepth = CSSTEP_CHARS; - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(num); - } - else if (M_MenuExtraPressed(num)) - { - p->clonenum = 0; - p->rotate = CSROTATETICS; - p->hitlag = true; - S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s - M_SetMenuDelay(num); - } -} - -static void M_HandleColorRotate(setup_player_t *p, UINT8 num) -{ - if (cv_splitdevice.value) - num = 0; - - if (menucmd[num].dpad_lr > 0) - { - p->color = M_GetColorAfter(p->color, 1, false); - p->rotate = CSROTATETICS; - M_SetMenuDelay(num); //CSROTATETICS - S_StartSound(NULL, sfx_s3k5b); //sfx_s3kc3s - } - else if (menucmd[num].dpad_lr < 0) - { - p->color = M_GetColorBefore(p->color, 1, false); - p->rotate = -CSROTATETICS; - M_SetMenuDelay(num); //CSROTATETICS - S_StartSound(NULL, sfx_s3k5b); //sfx_s3kc3s - } - - if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/) - { - p->mdepth = CSSTEP_FOLLOWERCATEGORY; - S_StartSound(NULL, sfx_s3k63); - M_SetMenuDelay(num); - } - else if (M_MenuBackPressed(num)) - { - if (setup_chargrid[p->gridx][p->gridy].numskins == 1) - { - p->mdepth = CSSTEP_CHARS; // Skip clones menu - } - else - { - p->mdepth = CSSTEP_ALTS; - } - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(num); - } - else if (M_MenuExtraPressed(num)) - { - if (p->skin >= 0) - { - p->color = skins[p->skin].prefcolor; - p->rotate = CSROTATETICS; - p->hitlag = true; - S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s - M_SetMenuDelay(num); - } - } -} - -static void M_AnimateFollower(setup_player_t *p) -{ - if (--p->follower_tics <= 0) - { - - // FF_ANIMATE; cycle through FRAMES and get back afterwards. This will be prominent amongst followers hence why it's being supported here. - if (p->follower_state->frame & FF_ANIMATE) - { - p->follower_frame++; - p->follower_tics = p->follower_state->var2; - if (p->follower_frame > (p->follower_state->frame & FF_FRAMEMASK) + p->follower_state->var1) // that's how it works, right? - p->follower_frame = p->follower_state->frame & FF_FRAMEMASK; - } - else - { - if (p->follower_state->nextstate != S_NULL) - p->follower_state = &states[p->follower_state->nextstate]; - p->follower_tics = p->follower_state->tics; - /*if (p->follower_tics == -1) - p->follower_tics = 15; // er, what?*/ - // get spritedef: - p->follower_frame = p->follower_state->frame & FF_FRAMEMASK; - } - } - - p->follower_timer++; -} - -static void M_HandleFollowerCategoryRotate(setup_player_t *p, UINT8 num) -{ - if (cv_splitdevice.value) - num = 0; - - if (menucmd[num].dpad_lr > 0) - { - p->followercategory++; - if (p->followercategory >= setup_numfollowercategories) - p->followercategory = -1; - - p->rotate = CSROTATETICS; - p->delay = CSROTATETICS; - S_StartSound(NULL, sfx_s3kc3s); - } - else if (menucmd[num].dpad_lr < 0) - { - p->followercategory--; - if (p->followercategory < -1) - p->followercategory = setup_numfollowercategories-1; - - p->rotate = -CSROTATETICS; - p->delay = CSROTATETICS; - S_StartSound(NULL, sfx_s3kc3s); - } - - if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/) - { - if (p->followercategory < 0) - { - p->followern = -1; - p->mdepth = CSSTEP_READY; - p->delay = TICRATE; - M_SetupReadyExplosions(true, p->gridx, p->gridy, p->color); - S_StartSound(NULL, sfx_s3k4e); - } - else - { - if (p->followern < 0 || followers[p->followern].category != p->followercategory) - { - p->followern = 0; - while (p->followern < numfollowers - && (followers[p->followern].category != setup_followercategories[p->followercategory][1] - || !K_FollowerUsable(p->followern))) - p->followern++; - } - - if (p->followern >= numfollowers) - { - p->followern = -1; - S_StartSound(NULL, sfx_s3kb2); - } - else - { - M_GetFollowerState(p); - p->mdepth = CSSTEP_FOLLOWER; - S_StartSound(NULL, sfx_s3k63); - } - } - - M_SetMenuDelay(num); - } - else if (M_MenuBackPressed(num)) - { - p->mdepth = CSSTEP_COLORS; - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(num); - } - else if (M_MenuExtraPressed(num)) - { - if (p->followercategory >= 0 || p->followern < 0 || p->followern >= numfollowers || followers[p->followern].category >= numfollowercategories) - p->followercategory = -1; - else - p->followercategory = followers[p->followern].category; - p->rotate = CSROTATETICS; - p->hitlag = true; - S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s - M_SetMenuDelay(num); - } -} - -static void M_HandleFollowerRotate(setup_player_t *p, UINT8 num) -{ - INT16 startfollowern = p->followern; - - if (cv_splitdevice.value) - num = 0; - - if (menucmd[num].dpad_lr > 0) - { - do - { - p->followern++; - if (p->followern >= numfollowers) - p->followern = 0; - if (p->followern == startfollowern) - break; - } - while (followers[p->followern].category != setup_followercategories[p->followercategory][1] || !K_FollowerUsable(p->followern)); - - M_GetFollowerState(p); - - p->rotate = CSROTATETICS; - p->delay = CSROTATETICS; - S_StartSound(NULL, sfx_s3kc3s); - } - else if (menucmd[num].dpad_lr < 0) - { - do - { - p->followern--; - if (p->followern < 0) - p->followern = numfollowers-1; - if (p->followern == startfollowern) - break; - } - while (followers[p->followern].category != setup_followercategories[p->followercategory][1] || !K_FollowerUsable(p->followern)); - - M_GetFollowerState(p); - - p->rotate = -CSROTATETICS; - p->delay = CSROTATETICS; - S_StartSound(NULL, sfx_s3kc3s); - } - - if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/) - { - if (p->followern > -1) - { - p->mdepth = CSSTEP_FOLLOWERCOLORS; - S_StartSound(NULL, sfx_s3k63); - } - else - { - p->mdepth = CSSTEP_READY; - p->delay = TICRATE; - M_SetupReadyExplosions(true, p->gridx, p->gridy, p->color); - S_StartSound(NULL, sfx_s3k4e); - } - - M_SetMenuDelay(num); - } - else if (M_MenuBackPressed(num)) - { - p->mdepth = CSSTEP_FOLLOWERCATEGORY; - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(num); - } - else if (M_MenuExtraPressed(num)) - { - p->mdepth = CSSTEP_FOLLOWERCATEGORY; - p->followercategory = -1; - p->rotate = CSROTATETICS; - p->hitlag = true; - S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s - M_SetMenuDelay(num); - } -} - -static void M_HandleFollowerColorRotate(setup_player_t *p, UINT8 num) -{ - if (cv_splitdevice.value) - num = 0; - - M_AnimateFollower(p); - - if (menucmd[num].dpad_lr > 0) - { - p->followercolor = M_GetColorAfter(p->followercolor, 1, true); - p->rotate = CSROTATETICS; - M_SetMenuDelay(num); //CSROTATETICS - S_StartSound(NULL, sfx_s3k5b); //sfx_s3kc3s - } - else if (menucmd[num].dpad_lr < 0) - { - p->followercolor = M_GetColorBefore(p->followercolor, 1, true); - p->rotate = -CSROTATETICS; - M_SetMenuDelay(num); //CSROTATETICS - S_StartSound(NULL, sfx_s3k5b); //sfx_s3kc3s - } - - if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/) - { - p->mdepth = CSSTEP_READY; - p->delay = TICRATE; - M_SetupReadyExplosions(true, p->gridx, p->gridy, p->color); - S_StartSound(NULL, sfx_s3k4e); - M_SetMenuDelay(num); - } - else if (M_MenuBackPressed(num)) - { - M_GetFollowerState(p); - p->mdepth = CSSTEP_FOLLOWER; - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(num); - } - else if (M_MenuExtraPressed(num)) - { - if (p->followercolor == FOLLOWERCOLOR_MATCH) - p->followercolor = FOLLOWERCOLOR_OPPOSITE; - else if (p->followercolor == followers[p->followern].defaultcolor) - p->followercolor = FOLLOWERCOLOR_MATCH; - else - p->followercolor = followers[p->followern].defaultcolor; - p->rotate = CSROTATETICS; - p->hitlag = true; - S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s - M_SetMenuDelay(num); - } -} - -boolean M_CharacterSelectHandler(INT32 choice) -{ - INT32 i; - - (void)choice; - - for (i = MAXSPLITSCREENPLAYERS-1; i >= 0; i--) - { - setup_player_t *p = &setup_player[i]; - boolean playersChanged = false; - - if (p->delay == 0 && menucmd[i].delay == 0) - { - if (!optionsmenu.profile) - { - // If splitdevice is true, only do the last non-ready setups. - if (cv_splitdevice.value) - { - // Previous setup isn't ready, go there. - // In any case, do setup 0 first. - if (i > 0 && setup_player[i-1].mdepth < CSSTEP_READY) - continue; - } - } - - switch (p->mdepth) - { - case CSSTEP_NONE: // Enter Game - if (gamestate == GS_MENU) // do NOT handle that outside of GS_MENU. - playersChanged = M_HandlePressStart(p, i); - break; - case CSSTEP_PROFILE: - playersChanged = M_HandleCSelectProfile(p, i); - break; - case CSSTEP_ASKCHANGES: - M_HandleCharAskChange(p, i); - break; - case CSSTEP_CHARS: // Character Select grid - M_HandleCharacterGrid(p, i); - break; - case CSSTEP_ALTS: // Select clone - M_HandleCharRotate(p, i); - break; - case CSSTEP_COLORS: // Select color - M_HandleColorRotate(p, i); - break; - case CSSTEP_FOLLOWERCATEGORY: - M_HandleFollowerCategoryRotate(p, i); - break; - case CSSTEP_FOLLOWER: - M_HandleFollowerRotate(p, i); - break; - case CSSTEP_FOLLOWERCOLORS: - M_HandleFollowerColorRotate(p, i); - break; - case CSSTEP_READY: - default: // Unready - if (M_MenuBackPressed(i)) - { - p->mdepth = CSSTEP_COLORS; - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(i); - } - break; - } - } - - // Just makes it easier to access later - p->skin = setup_chargrid[p->gridx][p->gridy].skinlist[p->clonenum]; - - // Keep profile colour. - /*if (p->mdepth < CSSTEP_COLORS) - { - p->color = skins[p->skin].prefcolor; - - }*/ - - if (playersChanged == true) - { - setup_page = 0; // reset that. - break; - } - } - - // Setup new numplayers - setup_numplayers = 0; - for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) - { - if (setup_player[i].mdepth == CSSTEP_NONE) - break; - - setup_numplayers = i+1; - } - - return true; -} - -// Apply character skin and colour changes while ingame (we just call the skin / color commands.) -// ...Will this cause command buffer issues? -Lat' -static void M_MPConfirmCharacterSelection(void) -{ - UINT8 i; - INT16 col; - - for (i = 0; i < splitscreen +1; i++) - { - // colour - // (convert the number that's saved to a string we can use) - col = setup_player[i].color; - CV_StealthSetValue(&cv_playercolor[i], col); - - // follower - if (setup_player[i].followern < 0) - CV_StealthSet(&cv_follower[i], "None"); - else - CV_StealthSet(&cv_follower[i], followers[setup_player[i].followern].name); - - // finally, call the skin[x] console command. - // This will call SendNameAndColor which will synch everything we sent here and apply the changes! - - CV_StealthSet(&cv_skin[i], skins[setup_player[i].skin].name); - - // ...actually, let's do this last - Skin_OnChange has some return-early occasions - // follower color - CV_SetValue(&cv_followercolor[i], setup_player[i].followercolor); - - } - M_ClearMenus(true); -} - -void M_CharacterSelectTick(void) -{ - UINT8 i; - boolean setupnext = true; - - setup_animcounter++; - - for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) - { - if (setup_player[i].delay) - setup_player[i].delay--; - - if (setup_player[i].rotate > 0) - setup_player[i].rotate--; - else if (setup_player[i].rotate < 0) - setup_player[i].rotate++; - else - setup_player[i].hitlag = false; - - if (i >= setup_numplayers) - continue; - - if (setup_player[i].mdepth < CSSTEP_READY || setup_player[i].delay > 0) - { - // Someone's not ready yet. - setupnext = false; - } - } - - for (i = 0; i < CSEXPLOSIONS; i++) - { - if (setup_explosions[i].tics > 0) - setup_explosions[i].tics--; - } - - if (setupnext && setup_numplayers > 0) - { - // Selecting from the menu - if (gamestate == GS_MENU) - { - // in a profile; update the selected profile and then go back to the profile menu. - if (optionsmenu.profile) - { - // save player - strcpy(optionsmenu.profile->skinname, skins[setup_player[0].skin].name); - optionsmenu.profile->color = setup_player[0].color; - - // save follower - strcpy(optionsmenu.profile->follower, followers[setup_player[0].followern].name); - optionsmenu.profile->followercolor = setup_player[0].followercolor; - - // reset setup_player - memset(setup_player, 0, sizeof(setup_player)); - setup_numplayers = 0; - - M_GoBack(0); - return; - } - else // in a normal menu, stealthset the cvars and then go to the play menu. - { - for (i = 0; i < setup_numplayers; i++) - { - CV_StealthSet(&cv_skin[i], skins[setup_player[i].skin].name); - CV_StealthSetValue(&cv_playercolor[i], setup_player[i].color); - - if (setup_player[i].followern < 0) - CV_StealthSet(&cv_follower[i], "None"); - else - CV_StealthSet(&cv_follower[i], followers[setup_player[i].followern].name); - CV_StealthSetValue(&cv_followercolor[i], setup_player[i].followercolor); - } - - CV_StealthSetValue(&cv_splitplayers, setup_numplayers); - - // P1 is alone, set their old device just in case. - if (setup_numplayers < 2 && setup_player[0].ponedevice) - { - CV_StealthSetValue(&cv_usejoystick[0], setup_player[0].ponedevice); - } - - M_SetupNextMenu(&PLAY_MainDef, false); - } - } - else // In a game - { - // 23/05/2022: Since there's already restrictskinchange, just allow this to happen regardless. - M_MPConfirmCharacterSelection(); - } - } -} - -boolean M_CharacterSelectQuit(void) -{ - return true; -} - -void M_SetupGametypeMenu(INT32 choice) -{ - (void)choice; - - PLAY_GamemodesDef.prevMenu = currentMenu; - - // Battle and Capsules (and Special) disabled - PLAY_GamemodesMenu[1].status = IT_DISABLED; - PLAY_GamemodesMenu[2].status = IT_DISABLED; - PLAY_GamemodesMenu[3].status = IT_DISABLED; - - if (cv_splitplayers.value > 1) - { - // Re-add Battle - PLAY_GamemodesMenu[1].status = IT_STRING | IT_CALL; - } - else - { - boolean anyunlocked = false; - - if (M_SecretUnlocked(SECRET_BREAKTHECAPSULES, true)) - { - // Re-add Capsules - PLAY_GamemodesMenu[2].status = IT_STRING | IT_CALL; - anyunlocked = true; - } - - if (M_SecretUnlocked(SECRET_SPECIALATTACK, true)) - { - // Re-add Special - PLAY_GamemodesMenu[3].status = IT_STRING | IT_CALL; - anyunlocked = true; - } - - if (!anyunlocked) - { - // Only one non-Back entry, let's skip straight to Race. - M_SetupRaceMenu(-1); - return; - } - } - - M_SetupNextMenu(&PLAY_GamemodesDef, false); -} - -void M_SetupRaceMenu(INT32 choice) -{ - (void)choice; - - PLAY_RaceGamemodesDef.prevMenu = currentMenu; - - // Time Attack disabled - PLAY_RaceGamemodesMenu[2].status = IT_DISABLED; - - // Time Attack is 1P only - if (cv_splitplayers.value <= 1 - && M_SecretUnlocked(SECRET_TIMEATTACK, true)) - { - PLAY_RaceGamemodesMenu[2].status = IT_STRING | IT_CALL; - } - - M_SetupNextMenu(&PLAY_RaceGamemodesDef, false); -} - -// DIFFICULTY SELECT - -void M_SetupDifficultySelect(INT32 choice) -{ - // check what we picked. - choice = currentMenu->menuitems[itemOn].mvar1; - - // setup the difficulty menu and then remove choices depending on choice - PLAY_RaceDifficultyDef.prevMenu = currentMenu; - - PLAY_RaceDifficulty[drace_gpdifficulty].status = IT_DISABLED; - PLAY_RaceDifficulty[drace_mrkartspeed].status = IT_DISABLED; - PLAY_RaceDifficulty[drace_mrcpu].status = IT_DISABLED; - PLAY_RaceDifficulty[drace_mrracers].status = IT_DISABLED; - PLAY_RaceDifficulty[drace_encore].status = IT_DISABLED; - PLAY_RaceDifficulty[drace_cupselect].status = IT_DISABLED; - PLAY_RaceDifficulty[drace_mapselect].status = IT_DISABLED; - - if (choice) // Match Race - { - PLAY_RaceDifficulty[drace_mrkartspeed].status = IT_STRING|IT_CVAR; // Kart Speed - PLAY_RaceDifficulty[drace_mrcpu].status = IT_STRING2|IT_CVAR; // CPUs on/off - PLAY_RaceDifficulty[drace_mrracers].status = IT_STRING2|IT_CVAR; // CPU amount - PLAY_RaceDifficulty[drace_mapselect].status = IT_STRING|IT_CALL; // Level Select (Match Race) - PLAY_RaceDifficultyDef.lastOn = drace_mapselect; // Select map select by default. - } - else // GP - { - PLAY_RaceDifficulty[drace_gpdifficulty].status = IT_STRING|IT_CVAR; // Difficulty - PLAY_RaceDifficulty[drace_cupselect].status = IT_STRING|IT_CALL; // Level Select (GP) - PLAY_RaceDifficultyDef.lastOn = drace_cupselect; // Select cup select by default. - } - - if (M_SecretUnlocked(SECRET_ENCORE, false)) - { - PLAY_RaceDifficulty[drace_encore].status = IT_STRING2|IT_CVAR; // Encore on/off - } - - M_SetupNextMenu(&PLAY_RaceDifficultyDef, false); -} - -// LEVEL SELECT - -// -// M_CanShowLevelInList -// -// Determines whether to show a given map in the various level-select lists. -// -boolean M_CanShowLevelInList(INT16 mapnum, levelsearch_t *levelsearch) -{ - if (!levelsearch) - return false; - - if (mapnum >= nummapheaders) - return false; - - // Does the map exist? - if (!mapheaderinfo[mapnum]) - return false; - - // Does the map have a name? - if (!mapheaderinfo[mapnum]->lvlttl[0]) - return false; - - // Does the map have a LUMP? - if (mapheaderinfo[mapnum]->lumpnum == LUMPERROR) - return false; - - // Check for TOL - if (!(mapheaderinfo[mapnum]->typeoflevel & levelsearch->typeoflevel)) - return false; - - // Should the map be hidden? - if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU) - return false; - - // I don't know why, but some may have exceptions. - if (levelsearch->timeattack && (mapheaderinfo[mapnum]->menuflags & LF2_NOTIMEATTACK)) - return false; - - // Don't permit cup when no cup requested (also no dupes in time attack) - if (levelsearch->cupmode - && (levelsearch->timeattack || !levelsearch->cup) - && mapheaderinfo[mapnum]->cup != levelsearch->cup) - return false; - - // Finally, the most complex check: does the map have lock conditions? - if (levelsearch->checklocked) - { - // Check for completion - if ((mapheaderinfo[mapnum]->menuflags & LF2_FINISHNEEDED) - && !(mapheaderinfo[mapnum]->mapvisited & MV_BEATEN)) - return false; - - // Check for unlock - if (M_MapLocked(mapnum+1)) - return false; - } - - // Survived our checks. - return true; -} - -UINT16 M_CountLevelsToShowInList(levelsearch_t *levelsearch) -{ - INT16 i, count = 0; - - if (!levelsearch) - return false; - - if (levelsearch->cup) - { - if (levelsearch->checklocked && M_CupLocked(levelsearch->cup)) - return 0; - - for (i = 0; i < CUPCACHE_MAX; i++) - { - if (!M_CanShowLevelInList(levelsearch->cup->cachedlevels[i], levelsearch)) - continue; - count++; - } - - return count; - } - - for (i = 0; i < nummapheaders; i++) - if (M_CanShowLevelInList(i, levelsearch)) - count++; - - return count; -} - -UINT16 M_GetFirstLevelInList(UINT8 *i, levelsearch_t *levelsearch) -{ - INT16 mapnum = NEXTMAP_INVALID; - - if (!levelsearch) - return false; - - if (levelsearch->cup) - { - if (levelsearch->checklocked && M_CupLocked(levelsearch->cup)) - { - *i = CUPCACHE_MAX; - return NEXTMAP_INVALID; - } - - *i = 0; - mapnum = NEXTMAP_INVALID; - for (; *i < CUPCACHE_MAX; (*i)++) - { - if (!M_CanShowLevelInList(levelsearch->cup->cachedlevels[*i], levelsearch)) - continue; - mapnum = levelsearch->cup->cachedlevels[*i]; - break; - } - } - else - { - for (mapnum = 0; mapnum < nummapheaders; mapnum++) - if (M_CanShowLevelInList(mapnum, levelsearch)) - break; - } - - return mapnum; -} - -UINT16 M_GetNextLevelInList(UINT16 mapnum, UINT8 *i, levelsearch_t *levelsearch) -{ - if (!levelsearch) - return false; - - if (levelsearch->cup) - { - mapnum = NEXTMAP_INVALID; - (*i)++; - for (; *i < CUPCACHE_MAX; (*i)++) - { - if (!M_CanShowLevelInList(levelsearch->cup->cachedlevels[*i], levelsearch)) - continue; - mapnum = levelsearch->cup->cachedlevels[*i]; - break; - } - } - else - { - mapnum++; - while (!M_CanShowLevelInList(mapnum, levelsearch) && mapnum < nummapheaders) - mapnum++; - } - - return mapnum; -} - -struct cupgrid_s cupgrid; -struct levellist_s levellist; - -static void M_LevelSelectScrollDest(void) -{ - UINT16 m = M_CountLevelsToShowInList(&levellist.levelsearch)-1; - - levellist.dest = (6*levellist.cursor); - - if (levellist.dest < 3) - levellist.dest = 3; - - if (levellist.dest > (6*m)-3) - levellist.dest = (6*m)-3; -} - -// Builds the level list we'll be using from the gametype we're choosing and send us to the apropriate menu. -static boolean M_LevelListFromGametype(INT16 gt) -{ - static boolean first = true; - UINT8 temp = 0; - - if (first || gt != levellist.newgametype || levellist.guessgt != MAXGAMETYPES) - { - if (first) - { - cupgrid.cappages = 0; - cupgrid.builtgrid = NULL; - } - - levellist.newgametype = gt; - - levellist.levelsearch.typeoflevel = G_TOLFlag(gt); - if (levellist.levelsearch.timeattack == true && gt == GT_SPECIAL) - { - // Sneak in an extra. - levellist.levelsearch.typeoflevel |= G_TOLFlag(GT_VERSUS); - levellist.guessgt = gt; - } - else - { - levellist.guessgt = MAXGAMETYPES; - } - - levellist.levelsearch.cupmode = (!(gametypes[gt]->rules & GTR_NOCUPSELECT)); - levellist.levelsearch.cup = NULL; - - first = false; - } - - // Obviously go to Cup Select in gametypes that have cups. - // Use a really long level select in gametypes that don't use cups. - - if (levellist.levelsearch.cupmode) - { - levelsearch_t templevelsearch = levellist.levelsearch; // full copy - size_t currentid = 0, highestunlockedid = 0; - const size_t pagelen = sizeof(cupheader_t*) * (CUPMENU_COLUMNS * CUPMENU_ROWS); - boolean foundany = false; - - templevelsearch.cup = kartcupheaders; - -#if 0 - // Make sure there's valid cups before going to this menu. -- rip sweet prince - if (templevelsearch.cup == NULL) - I_Error("Can you really call this a racing game, I didn't recieve any Cups on my pillow or anything"); -#endif - - if (cupgrid.cappages == 0) - { - cupgrid.cappages = 2; - cupgrid.builtgrid = Z_Calloc( - cupgrid.cappages * pagelen, - PU_STATIC, - NULL); - - if (!cupgrid.builtgrid) - { - I_Error("M_LevelListFromGametype: Not enough memory to allocate builtgrid"); - } - } - memset(cupgrid.builtgrid, 0, cupgrid.cappages * pagelen); - - while (templevelsearch.cup) - { - templevelsearch.checklocked = false; - if (!M_CountLevelsToShowInList(&templevelsearch)) - { - // No valid maps, skip. - templevelsearch.cup = templevelsearch.cup->next; - continue; - } - - foundany = true; - - if ((currentid * sizeof(cupheader_t*)) >= cupgrid.cappages * pagelen) - { - // Double the size of the buffer, and clear the other stuff. - const size_t firstlen = cupgrid.cappages * pagelen; - cupgrid.builtgrid = Z_Realloc(cupgrid.builtgrid, - firstlen * 2, - PU_STATIC, NULL); - - if (!cupgrid.builtgrid) - { - I_Error("M_LevelListFromGametype: Not enough memory to reallocate builtgrid"); - } - - memset(cupgrid.builtgrid + firstlen, 0, firstlen); - cupgrid.cappages *= 2; - } - - cupgrid.builtgrid[currentid] = templevelsearch.cup; - - templevelsearch.checklocked = true; - if (M_GetFirstLevelInList(&temp, &templevelsearch) != NEXTMAP_INVALID) - { - highestunlockedid = currentid; - if (Playing() && mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->cup == templevelsearch.cup) - { - cupgrid.x = currentid % CUPMENU_COLUMNS; - cupgrid.y = (currentid / CUPMENU_COLUMNS) % CUPMENU_ROWS; - cupgrid.pageno = currentid / (CUPMENU_COLUMNS * CUPMENU_ROWS); - } - } - - currentid++; - templevelsearch.cup = templevelsearch.cup->next; - } - - if (foundany == false) - { - return false; - } - - cupgrid.numpages = (highestunlockedid / (CUPMENU_COLUMNS * CUPMENU_ROWS)) + 1; - if (cupgrid.pageno >= cupgrid.numpages) - { - cupgrid.pageno = 0; - } - - PLAY_CupSelectDef.prevMenu = currentMenu; - PLAY_LevelSelectDef.prevMenu = &PLAY_CupSelectDef; - M_SetupNextMenu(&PLAY_CupSelectDef, false); - - return true; - } - - // Okay, just a list of maps then. - - if (M_GetFirstLevelInList(&temp, &levellist.levelsearch) == NEXTMAP_INVALID) - { - return false; - } - - // Reset position properly if you go back & forth between gametypes - if (levellist.levelsearch.cup) - { - levellist.cursor = 0; - levellist.levelsearch.cup = NULL; - } - - M_LevelSelectScrollDest(); - levellist.y = levellist.dest; - - PLAY_LevelSelectDef.prevMenu = currentMenu; - M_SetupNextMenu(&PLAY_LevelSelectDef, false); - - return true; -} - -// Init level select for use in local play using the last choice we made. -// For the online MP version used to START HOSTING A GAME, see M_MPSetupNetgameMapSelect() -// (We still use this one midgame) - -void M_LevelSelectInit(INT32 choice) -{ - INT32 gt = currentMenu->menuitems[itemOn].mvar2; - - (void)choice; - - // Make sure this is reset as we'll only be using this function for offline games! - levellist.netgame = false; - levellist.levelsearch.checklocked = true; - - switch (currentMenu->menuitems[itemOn].mvar1) - { - case 0: - cupgrid.grandprix = false; - levellist.levelsearch.timeattack = false; - break; - case 1: - cupgrid.grandprix = false; - levellist.levelsearch.timeattack = true; - break; - case 2: - cupgrid.grandprix = true; - levellist.levelsearch.timeattack = false; - break; - default: - CONS_Alert(CONS_WARNING, "Bad level select init\n"); - return; - } - - if (gt == -1) - { - gt = menugametype; - } - - if (!M_LevelListFromGametype(gt)) - { - S_StartSound(NULL, sfx_s3kb2); - M_StartMessage(va("No levels available for\n%s Mode!\n\nPress (B)\n", gametypes[gt]->name), NULL, MM_NOTHING); - } -} - -static void M_LevelSelected(INT16 add) -{ - UINT8 i = 0; - INT16 map = M_GetFirstLevelInList(&i, &levellist.levelsearch); - - while (add > 0) - { - map = M_GetNextLevelInList(map, &i, &levellist.levelsearch); - - if (map >= nummapheaders) - { - break; - } - - add--; - } - - if (map >= nummapheaders) - { - // This shouldn't happen - return; - } - - levellist.choosemap = map; - - if (levellist.levelsearch.timeattack) - { - S_StartSound(NULL, sfx_s3k63); - - if (levellist.guessgt != MAXGAMETYPES) - levellist.newgametype = G_GuessGametypeByTOL(levellist.levelsearch.typeoflevel); - - PLAY_TimeAttackDef.lastOn = ta_start; - PLAY_TimeAttackDef.prevMenu = currentMenu; - M_SetupNextMenu(&PLAY_TimeAttackDef, false); - } - else - { - if (gamestate == GS_MENU) - { - UINT8 ssplayers = cv_splitplayers.value-1; - - netgame = false; - multiplayer = true; - - strncpy(connectedservername, cv_servername.string, MAXSERVERNAME); - - // Still need to reset devmode - cht_debug = 0; - - if (demo.playback) - G_StopDemo(); - if (metalrecording) - G_StopMetalDemo(); - - /*if (levellist.choosemap == 0) - levellist.choosemap = G_RandMap(G_TOLFlag(levellist.newgametype), -1, 0, 0, false, NULL);*/ - - if (cv_maxconnections.value < ssplayers+1) - CV_SetValue(&cv_maxconnections, ssplayers+1); - - if (splitscreen != ssplayers) - { - splitscreen = ssplayers; - SplitScreen_OnChange(); - } - - S_StartSound(NULL, sfx_s3k63); - - paused = false; - - // Early fadeout to let the sound finish playing - F_WipeStartScreen(); - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); - F_WipeEndScreen(); - F_RunWipe(wipedefs[wipe_level_toblack], false, "FADEMAP0", false, false); - - SV_StartSinglePlayerServer(levellist.newgametype, levellist.netgame); - - CV_StealthSet(&cv_kartbot, cv_dummymatchbots.string); - CV_StealthSet(&cv_kartencore, (cv_dummygpencore.value == 1) ? "On" : "Auto"); - CV_StealthSet(&cv_kartspeed, (cv_dummykartspeed.value == KARTSPEED_NORMAL) ? "Auto" : cv_dummykartspeed.string); - - D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_kartencore.value == 1), 1, 1, false, false); - } - else - { - // directly do the map change - D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_kartencore.value == 1), 1, 1, false, false); - } - - M_ClearMenus(true); - } -} - -void M_CupSelectHandler(INT32 choice) -{ - const UINT8 pid = 0; - - (void)choice; - - if (menucmd[pid].dpad_lr > 0) - { - cupgrid.x++; - if (cupgrid.x >= CUPMENU_COLUMNS) - { - cupgrid.x = 0; - cupgrid.pageno++; - if (cupgrid.pageno >= cupgrid.numpages) - cupgrid.pageno = 0; - } - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - else if (menucmd[pid].dpad_lr < 0) - { - cupgrid.x--; - if (cupgrid.x < 0) - { - cupgrid.x = CUPMENU_COLUMNS-1; - if (cupgrid.pageno == 0) - cupgrid.pageno = cupgrid.numpages-1; - else - cupgrid.pageno--; - } - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - - if (menucmd[pid].dpad_ud > 0) - { - cupgrid.y++; - if (cupgrid.y >= CUPMENU_ROWS) - cupgrid.y = 0; - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - else if (menucmd[pid].dpad_ud < 0) - { - cupgrid.y--; - if (cupgrid.y < 0) - cupgrid.y = CUPMENU_ROWS-1; - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - - if (M_MenuConfirmPressed(pid) /*|| M_MenuButtonPressed(pid, MBT_START)*/) - { - INT16 count; - cupheader_t *newcup = cupgrid.builtgrid[CUPMENU_CURSORID]; - cupheader_t *oldcup = levellist.levelsearch.cup; - - M_SetMenuDelay(pid); - - levellist.levelsearch.cup = newcup; - count = M_CountLevelsToShowInList(&levellist.levelsearch); - - if ((!newcup) - || (count <= 0) - || (cupgrid.grandprix == true && newcup->cachedlevels[0] == NEXTMAP_INVALID)) - { - S_StartSound(NULL, sfx_s3kb2); - return; - } - - if (cupgrid.grandprix == true) - { - INT32 levelNum; - UINT8 ssplayers = cv_splitplayers.value-1; - - S_StartSound(NULL, sfx_s3k63); - - // Early fadeout to let the sound finish playing - F_WipeStartScreen(); - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); - F_WipeEndScreen(); - F_RunWipe(wipedefs[wipe_level_toblack], false, "FADEMAP0", false, false); - - memset(&grandprixinfo, 0, sizeof(struct grandprixinfo)); - - if (cv_maxconnections.value < ssplayers+1) - CV_SetValue(&cv_maxconnections, ssplayers+1); - - if (splitscreen != ssplayers) - { - splitscreen = ssplayers; - SplitScreen_OnChange(); - } - - // read our dummy cvars - - grandprixinfo.gamespeed = min(KARTSPEED_HARD, cv_dummygpdifficulty.value); - grandprixinfo.masterbots = (cv_dummygpdifficulty.value == 3); - grandprixinfo.encore = (boolean)cv_dummygpencore.value; - - grandprixinfo.cup = newcup; - - grandprixinfo.gp = true; - grandprixinfo.roundnum = 1; - grandprixinfo.initalize = true; - - paused = false; - - // Don't restart the server if we're already in a game lol - if (gamestate == GS_MENU) - { - SV_StartSinglePlayerServer(levellist.newgametype, levellist.netgame); - } - - levelNum = grandprixinfo.cup->cachedlevels[0]; - - D_MapChange( - levelNum + 1, - GT_RACE, - grandprixinfo.encore, - true, - 1, - false, - false - ); - - M_ClearMenus(true); - } - else if (count == 1) - { - PLAY_TimeAttackDef.transitionID = currentMenu->transitionID+1; - M_LevelSelected(0); - } - else - { - // Keep cursor position if you select the same cup again, reset if it's a different cup - if (oldcup != newcup || levellist.cursor >= count) - { - levellist.cursor = 0; - } - - M_LevelSelectScrollDest(); - levellist.y = levellist.dest; - - M_SetupNextMenu(&PLAY_LevelSelectDef, false); - S_StartSound(NULL, sfx_s3k63); - } - } - else if (M_MenuBackPressed(pid)) - { - M_SetMenuDelay(pid); - - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu, false); - else - M_ClearMenus(true); - } -} - -void M_CupSelectTick(void) -{ - cupgrid.previewanim++; -} - -void M_LevelSelectHandler(INT32 choice) -{ - INT16 maxlevels = M_CountLevelsToShowInList(&levellist.levelsearch); - const UINT8 pid = 0; - - (void)choice; - - if (levellist.y != levellist.dest) - { - return; - } - - if (menucmd[pid].dpad_ud > 0) - { - levellist.cursor++; - if (levellist.cursor >= maxlevels) - levellist.cursor = 0; - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - else if (menucmd[pid].dpad_ud < 0) - { - levellist.cursor--; - if (levellist.cursor < 0) - levellist.cursor = maxlevels-1; - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - - M_LevelSelectScrollDest(); - - if (M_MenuConfirmPressed(pid) /*|| M_MenuButtonPressed(pid, MBT_START)*/) - { - M_SetMenuDelay(pid); - - PLAY_TimeAttackDef.transitionID = currentMenu->transitionID; - M_LevelSelected(levellist.cursor); - } - else if (M_MenuBackPressed(pid)) - { - M_SetMenuDelay(pid); - - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu, false); - else - M_ClearMenus(true); - } -} - -void M_LevelSelectTick(void) -{ - - INT16 dist = levellist.dest - levellist.y; - - if (abs(dist) == 1) // cheating to avoid off by 1 errors with divisions. - levellist.y = levellist.dest; - else - levellist.y += dist/2; -} - - -// time attack stuff... -void M_HandleStaffReplay(INT32 choice) -{ - // @TODO: - (void) choice; -} - -void M_ReplayTimeAttack(INT32 choice) -{ - // @TODO: - (void) choice; -} - -void M_SetGuestReplay(INT32 choice) -{ - // @TODO: - (void) choice; -} - -void M_StartTimeAttack(INT32 choice) -{ - char *gpath; - char nameofdemo[256]; - - (void)choice; - - modeattacking = ATTACKING_TIME; - - if ((gametypes[levellist.newgametype]->rules & GTR_CIRCUIT) - && (mapheaderinfo[levellist.choosemap]->numlaps != 1)) - { - modeattacking |= ATTACKING_LAP; - } - - // Still need to reset devmode - cht_debug = 0; - emeralds = 0; - - if (demo.playback) - G_StopDemo(); - if (metalrecording) - G_StopMetalDemo(); - - splitscreen = 0; - SplitScreen_OnChange(); - - S_StartSound(NULL, sfx_s3k63); - - paused = false; - - // Early fadeout to let the sound finish playing - F_WipeStartScreen(); - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); - F_WipeEndScreen(); - F_RunWipe(wipedefs[wipe_level_toblack], false, "FADEMAP0", false, false); - - SV_StartSinglePlayerServer(levellist.newgametype, false); - - gpath = va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s", - srb2home, timeattackfolder); - M_MkdirEach(gpath, M_PathParts(gpath) - 3, 0755); - - strcat(gpath, PATHSEP); - strcat(gpath, G_BuildMapName(levellist.choosemap+1)); - - snprintf(nameofdemo, sizeof nameofdemo, "%s-%s-last", gpath, cv_skin[0].string); - - if (!cv_autorecord.value) - remove(va("%s"PATHSEP"%s.lmp", srb2home, nameofdemo)); - else - G_RecordDemo(nameofdemo); - - M_ClearMenus(true); - D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_dummygpencore.value == 1), 1, 1, false, false); -} - - -struct mpmenu_s mpmenu; - -// MULTIPLAYER OPTION SELECT - -// Use this as a quit routine within the HOST GAME and JOIN BY IP "sub" menus -boolean M_MPResetOpts(void) -{ - UINT8 i = 0; - - for (; i < 3; i++) - mpmenu.modewinextend[i][0] = 0; // Undo this - - return true; -} - -void M_MPOptSelectInit(INT32 choice) -{ - INT16 arrcpy[3][3] = {{0,68,0}, {0,12,0}, {0,74,0}}; - UINT8 i = 0, j = 0; // To copy the array into the struct - const UINT32 forbidden = GTR_FORBIDMP; - - (void)choice; - - mpmenu.modechoice = 0; - mpmenu.ticker = 0; - - for (; i < 3; i++) - for (j = 0; j < 3; j++) - mpmenu.modewinextend[i][j] = arrcpy[i][j]; // I miss Lua already - - // Guarantee menugametype is good - M_NextMenuGametype(forbidden); - M_PrevMenuGametype(forbidden); - - M_SetupNextMenu(&PLAY_MP_OptSelectDef, false); -} - -void M_MPOptSelectTick(void) -{ - UINT8 i = 0; - - // 3 Because we have 3 options in the menu - for (; i < 3; i++) - { - if (mpmenu.modewinextend[i][0]) - mpmenu.modewinextend[i][2] += 8; - else - mpmenu.modewinextend[i][2] -= 8; - - mpmenu.modewinextend[i][2] = min(mpmenu.modewinextend[i][1], max(0, mpmenu.modewinextend[i][2])); - //CONS_Printf("%d - %d,%d,%d\n", i, mpmenu.modewinextend[i][0], mpmenu.modewinextend[i][1], mpmenu.modewinextend[i][2]); - } -} - - -// MULTIPLAYER HOST -void M_MPHostInit(INT32 choice) -{ - - (void)choice; - mpmenu.modewinextend[0][0] = 1; - M_SetupNextMenu(&PLAY_MP_HostDef, true); - itemOn = mhost_go; -} - -void M_NextMenuGametype(UINT32 forbidden) -{ - const INT16 currentmenugametype = menugametype; - do - { - menugametype++; - if (menugametype >= numgametypes) - menugametype = 0; - - if (!(gametypes[menugametype]->rules & forbidden)) - break; - } while (menugametype != currentmenugametype); -} - -void M_PrevMenuGametype(UINT32 forbidden) -{ - const INT16 currentmenugametype = menugametype; - do - { - if (menugametype == 0) - menugametype = numgametypes; - menugametype--; - - if (!(gametypes[menugametype]->rules & forbidden)) - break; - } while (menugametype != currentmenugametype); -} - -void M_HandleHostMenuGametype(INT32 choice) -{ - const UINT8 pid = 0; - const UINT32 forbidden = GTR_FORBIDMP; - - (void)choice; - - if (M_MenuBackPressed(pid)) - { - M_GoBack(0); - M_SetMenuDelay(pid); - return; - } - else if (menucmd[pid].dpad_lr > 0 || M_MenuConfirmPressed(pid)) - { - M_NextMenuGametype(forbidden); - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - else if (menucmd[pid].dpad_lr < 0) - { - M_PrevMenuGametype(forbidden); - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - - if (menucmd[pid].dpad_ud > 0) - { - M_NextOpt(); - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - else if (menucmd[pid].dpad_ud < 0) - { - M_PrevOpt(); - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } -} - -void M_MPSetupNetgameMapSelect(INT32 choice) -{ - (void)choice; - - // Yep, we'll be starting a netgame. - levellist.netgame = true; - // Make sure we reset those - levellist.levelsearch.timeattack = false; - levellist.levelsearch.checklocked = true; - cupgrid.grandprix = false; - - // okay this is REALLY stupid but this fixes the host menu re-folding on itself when we go back. - mpmenu.modewinextend[0][0] = 1; - - if (!M_LevelListFromGametype(menugametype)) - { - S_StartSound(NULL, sfx_s3kb2); - M_StartMessage(va("No levels available for\n%s Mode!\n\nPress (B)\n", gametypes[menugametype]->name), NULL, MM_NOTHING); - } -} - -// MULTIPLAYER JOIN BY IP -void M_MPJoinIPInit(INT32 choice) -{ - - (void)choice; - mpmenu.modewinextend[2][0] = 1; - M_SetupNextMenu(&PLAY_MP_JoinIPDef, true); -} - -// Attempts to join a given IP from the menu. -void M_JoinIP(const char *ipa) -{ - if (*(ipa) == '\0') // Jack shit - { - M_StartMessage("Please specify an address.\n", NULL, MM_NOTHING); - return; - } - - COM_BufAddText(va("connect \"%s\"\n", ipa)); - - // A little "please wait" message. - M_DrawTextBox(56, BASEVIDHEIGHT/2-12, 24, 2); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, "Connecting to server..."); - I_OsPolling(); - I_UpdateNoBlit(); - if (rendermode == render_soft) - I_FinishUpdate(); // page flip or blit buffer -} - -boolean M_JoinIPInputs(INT32 ch) -{ - - const UINT8 pid = 0; - (void) ch; - - if (itemOn == 1) // connect field - { - // enter: connect - if (M_MenuConfirmPressed(pid)) - { - M_JoinIP(cv_dummyip.string); - M_SetMenuDelay(pid); - return true; - } - } - else if (currentMenu->numitems - itemOn <= NUMLOGIP && M_MenuConfirmPressed(pid)) // On one of the last 3 options for IP rejoining - { - UINT8 index = NUMLOGIP - (currentMenu->numitems - itemOn); - M_SetMenuDelay(pid); - - // Is there an address at this part of the table? - if (*joinedIPlist[index][0]) - M_JoinIP(joinedIPlist[index][0]); - else - S_StartSound(NULL, sfx_lose); - - return true; // eat input. - } - - return false; -} - -// MULTIPLAYER ROOM SELECT MENU - -void M_MPRoomSelect(INT32 choice) -{ - const UINT8 pid = 0; - (void) choice; - - if (menucmd[pid].dpad_lr) - { - mpmenu.room = (!mpmenu.room) ? 1 : 0; - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - else if (M_MenuBackPressed(pid)) - { - M_GoBack(0); - M_SetMenuDelay(pid); - } - - else if (M_MenuConfirmPressed(pid)) - { - M_ServersMenu(0); - M_SetMenuDelay(pid); - } -} - -void M_MPRoomSelectTick(void) -{ - mpmenu.ticker++; -} - -void M_MPRoomSelectInit(INT32 choice) -{ - (void)choice; - mpmenu.room = 0; - mpmenu.ticker = 0; - mpmenu.servernum = 0; - mpmenu.scrolln = 0; - mpmenu.slide = 0; - - M_SetupNextMenu(&PLAY_MP_RoomSelectDef, false); -} - -// MULTIPLAYER ROOM FETCH / REFRESH THREADS - -// depending on mpmenu.room, either allows only unmodded servers or modded ones. Remove others from the list. -// we do this by iterating backwards. -static void M_CleanServerList(void) -{ - UINT8 i = serverlistcount; - - while (i) - { - - if (serverlist[i].info.modifiedgame != mpmenu.room) - { - // move everything after this index 1 slot down... - if (i != serverlistcount) - memcpy(&serverlist[i], &serverlist[i+1], sizeof(serverelem_t)*(serverlistcount-i)); - - serverlistcount--; - } - - i--; - } -} - -void -M_SetWaitingMode (int mode) -{ -#ifdef HAVE_THREADS - I_lock_mutex(&k_menu_mutex); -#endif - { - m_waiting_mode = mode; - } -#ifdef HAVE_THREADS - I_unlock_mutex(k_menu_mutex); -#endif -} - -int -M_GetWaitingMode (void) -{ - int mode; - -#ifdef HAVE_THREADS - I_lock_mutex(&k_menu_mutex); -#endif - { - mode = m_waiting_mode; - } -#ifdef HAVE_THREADS - I_unlock_mutex(k_menu_mutex); -#endif - - return mode; -} - -#ifdef MASTERSERVER -#ifdef HAVE_THREADS -void -Spawn_masterserver_thread (const char *name, void (*thread)(int*)) -{ - int *id = malloc(sizeof *id); - - I_lock_mutex(&ms_QueryId_mutex); - { - *id = ms_QueryId; - } - I_unlock_mutex(ms_QueryId_mutex); - - I_spawn_thread(name, (I_thread_fn)thread, id); -} - -int -Same_instance (int id) -{ - int okay; - - I_lock_mutex(&ms_QueryId_mutex); - { - okay = ( id == ms_QueryId ); - } - I_unlock_mutex(ms_QueryId_mutex); - - return okay; -} -#endif/*HAVE_THREADS*/ - -void -Fetch_servers_thread (int *id) -{ - msg_server_t * server_list; - - (void)id; - - M_SetWaitingMode(M_WAITING_SERVERS); - -#ifdef HAVE_THREADS - server_list = GetShortServersList(*id); -#else - server_list = GetShortServersList(0); -#endif - - if (server_list) - { -#ifdef HAVE_THREADS - if (Same_instance(*id)) -#endif - { - M_SetWaitingMode(M_NOT_WAITING); - -#ifdef HAVE_THREADS - I_lock_mutex(&ms_ServerList_mutex); - { - ms_ServerList = server_list; - } - I_unlock_mutex(ms_ServerList_mutex); -#else - CL_QueryServerList(server_list); - free(server_list); -#endif - } -#ifdef HAVE_THREADS - else - { - free(server_list); - } -#endif - } - -#ifdef HAVE_THREADS - free(id); -#endif -} -#endif/*MASTERSERVER*/ - -// updates serverlist -void M_RefreshServers(INT32 choice) -{ - (void)choice; - - // Display a little "please wait" message. - M_DrawTextBox(52, BASEVIDHEIGHT/2-10, 25, 3); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, "Searching for servers..."); - V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2)+12, 0, "Please wait."); - I_OsPolling(); - I_UpdateNoBlit(); - if (rendermode == render_soft) - I_FinishUpdate(); // page flip or blit buffer - -#ifdef MASTERSERVER -#ifdef HAVE_THREADS - Spawn_masterserver_thread("fetch-servers", Fetch_servers_thread); -#else/*HAVE_THREADS*/ - Fetch_servers_thread(NULL); -#endif/*HAVE_THREADS*/ -#else/*MASTERSERVER*/ - CL_UpdateServerList(); -#endif/*MASTERSERVER*/ - -#ifdef SERVERLISTDEBUG - M_ServerListFillDebug(); -#endif - M_CleanServerList(); - M_SortServerList(); - -} - -#ifdef UPDATE_ALERT -static void M_CheckMODVersion(int id) -{ - char updatestring[500]; - const char *updatecheck = GetMODVersion(id); - if(updatecheck) - { - sprintf(updatestring, UPDATE_ALERT_STRING, VERSIONSTRING, updatecheck); -#ifdef HAVE_THREADS - I_lock_mutex(&k_menu_mutex); -#endif - M_StartMessage(updatestring, NULL, MM_NOTHING); -#ifdef HAVE_THREADS - I_unlock_mutex(k_menu_mutex); -#endif - } -} -#endif/*UPDATE_ALERT*/ - -#if defined (UPDATE_ALERT) && defined (HAVE_THREADS) -static void -Check_new_version_thread (int *id) -{ - M_SetWaitingMode(M_WAITING_VERSION); - - M_CheckMODVersion(*id); - - if (Same_instance(*id)) - { - Fetch_servers_thread(id); - } - else - { - free(id); - } -} -#endif/*defined (UPDATE_ALERT) && defined (HAVE_THREADS)*/ - - -// Initializes serverlist when entering the menu... -void M_ServersMenu(INT32 choice) -{ - (void)choice; - // modified game check: no longer handled - // we don't request a restart unless the filelist differs - - mpmenu.servernum = 0; - mpmenu.scrolln = 0; - mpmenu.slide = 0; - - M_SetupNextMenu(&PLAY_MP_ServerBrowserDef, false); - itemOn = 0; - -#if defined (MASTERSERVER) && defined (HAVE_THREADS) - I_lock_mutex(&ms_QueryId_mutex); - { - ms_QueryId++; - } - I_unlock_mutex(ms_QueryId_mutex); - - I_lock_mutex(&ms_ServerList_mutex); - { - if (ms_ServerList) - { - free(ms_ServerList); - ms_ServerList = NULL; - } - } - I_unlock_mutex(ms_ServerList_mutex); - -#ifdef UPDATE_ALERT - Spawn_masterserver_thread("check-new-version", Check_new_version_thread); -#else/*UPDATE_ALERT*/ - Spawn_masterserver_thread("fetch-servers", Fetch_servers_thread); -#endif/*UPDATE_ALERT*/ -#else/*defined (MASTERSERVER) && defined (HAVE_THREADS)*/ -#ifdef UPDATE_ALERT - M_CheckMODVersion(0); -#endif/*UPDATE_ALERT*/ - M_RefreshServers(0); -#endif/*defined (MASTERSERVER) && defined (HAVE_THREADS)*/ - -#ifdef SERVERLISTDEBUG - M_ServerListFillDebug(); -#endif - - M_CleanServerList(); - M_SortServerList(); -} - -#ifdef SERVERLISTDEBUG - -// Fill serverlist with a bunch of garbage to make our life easier in debugging -void M_ServerListFillDebug(void) -{ - UINT8 i = 0; - - serverlistcount = 10; - memset(serverlist, 0, sizeof(serverlist)); // zero out the array for convenience... - - for (i = 0; i < serverlistcount; i++) - { - // We don't really care about the server node for this, let's just fill in the info so that we have a visual... - serverlist[i].info.numberofplayer = min(i, 8); - serverlist[i].info.maxplayer = 8; - - serverlist[i].info.avgpwrlv = P_RandomRange(PR_UNDEFINED, 500, 1500); - serverlist[i].info.time = P_RandomRange(PR_UNDEFINED, 1, 8); // ping - - strcpy(serverlist[i].info.servername, va("Serv %d", i+1)); - - strcpy(serverlist[i].info.gametypename, i & 1 ? "Race" : "Battle"); - - P_RandomRange(PR_UNDEFINED, 0, 5); // change results... - serverlist[i].info.kartvars = P_RandomRange(PR_UNDEFINED, 0, 3) & SV_SPEEDMASK; - - serverlist[i].info.modifiedgame = P_RandomRange(PR_UNDEFINED, 0, 1); - - CONS_Printf("Serv %d | %d...\n", i, serverlist[i].info.modifiedgame); - } -} - -#endif // SERVERLISTDEBUG - -// Ascending order, not descending. -// The casts are safe as long as the caller doesn't do anything stupid. -#define SERVER_LIST_ENTRY_COMPARATOR(key) \ -static int ServerListEntryComparator_##key(const void *entry1, const void *entry2) \ -{ \ - const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2; \ - if (sa->info.key != sb->info.key) \ - return sa->info.key - sb->info.key; \ - return strcmp(sa->info.servername, sb->info.servername); \ -} - -// This does descending instead of ascending. -#define SERVER_LIST_ENTRY_COMPARATOR_REVERSE(key) \ -static int ServerListEntryComparator_##key##_reverse(const void *entry1, const void *entry2) \ -{ \ - const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2; \ - if (sb->info.key != sa->info.key) \ - return sb->info.key - sa->info.key; \ - return strcmp(sb->info.servername, sa->info.servername); \ -} - -SERVER_LIST_ENTRY_COMPARATOR(time) -SERVER_LIST_ENTRY_COMPARATOR(numberofplayer) -SERVER_LIST_ENTRY_COMPARATOR_REVERSE(numberofplayer) -SERVER_LIST_ENTRY_COMPARATOR_REVERSE(maxplayer) -SERVER_LIST_ENTRY_COMPARATOR(avgpwrlv) - - -static int ServerListEntryComparator_gametypename(const void *entry1, const void *entry2) -{ - const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2; - int c; - if (( c = strcasecmp(sa->info.gametypename, sb->info.gametypename) )) - return c; - return strcmp(sa->info.servername, sb->info.servername); \ -} - -void M_SortServerList(void) -{ - switch(cv_serversort.value) - { - case 0: // Ping. - qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_time); - break; - case 1: // AVG. Power Level - qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_avgpwrlv); - break; - case 2: // Most players. - qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_numberofplayer_reverse); - break; - case 3: // Least players. - qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_numberofplayer); - break; - case 4: // Max players. - qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_maxplayer_reverse); - break; - case 5: // Gametype. - qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_gametypename); - break; - } -} - - -// Server browser inputs & ticker -void M_MPServerBrowserTick(void) -{ - mpmenu.slide /= 2; -} - -// Input handler for server browser. -boolean M_ServerBrowserInputs(INT32 ch) -{ - UINT8 pid = 0; - UINT8 maxscroll = serverlistcount-(SERVERSPERPAGE/2); - (void) ch; - - if (!itemOn && menucmd[pid].dpad_ud < 0) - { - M_PrevOpt(); // go to itemOn 2 - if (serverlistcount) - { - UINT8 prevscroll = mpmenu.scrolln; - - mpmenu.servernum = serverlistcount; - mpmenu.scrolln = maxscroll; - mpmenu.slide = SERVERSPACE * (prevscroll - mpmenu.scrolln); - } - else - { - itemOn = 1; // Sike! If there are no servers, go to refresh instead. - } - - return true; // overwrite behaviour. - } - else if (itemOn == 2) // server browser itself... - { - // we have to manually do that here. - if (M_MenuBackPressed(pid)) - { - M_GoBack(0); - M_SetMenuDelay(pid); - } - - else if (menucmd[pid].dpad_ud > 0) // down - { - if (mpmenu.servernum >= serverlistcount-1) - { - UINT8 prevscroll = mpmenu.scrolln; - mpmenu.servernum = 0; - mpmenu.scrolln = 0; - mpmenu.slide = SERVERSPACE * (prevscroll - mpmenu.scrolln); - - M_NextOpt(); // Go back to the top of the real menu. - } - else - { - mpmenu.servernum++; - if (mpmenu.scrolln < maxscroll && mpmenu.servernum > SERVERSPERPAGE/2) - { - mpmenu.scrolln++; - mpmenu.slide += SERVERSPACE; - } - } - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - - } - else if (menucmd[pid].dpad_ud < 0) - { - - if (!mpmenu.servernum) - { - M_PrevOpt(); - } - else - { - if (mpmenu.servernum <= serverlistcount-(SERVERSPERPAGE/2) && mpmenu.scrolln) - { - mpmenu.scrolln--; - mpmenu.slide -= SERVERSPACE; - } - - mpmenu.servernum--; - } - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - - } - return true; // Overwrite behaviour. - } - return false; // use normal behaviour. -} - - -// Options menu: -struct optionsmenu_s optionsmenu; - -void M_ResetOptions(void) -{ - optionsmenu.ticker = 0; - optionsmenu.offset = 0; - - optionsmenu.optx = 0; - optionsmenu.opty = 0; - optionsmenu.toptx = 0; - optionsmenu.topty = 0; - - // BG setup: - optionsmenu.currcolour = OPTIONS_MainDef.extra1; - optionsmenu.lastcolour = 0; - optionsmenu.fade = 0; - - // For profiles: - memset(setup_player, 0, sizeof(setup_player)); - optionsmenu.profile = NULL; -} - -void M_InitOptions(INT32 choice) -{ - (void)choice; - - OPTIONS_MainDef.menuitems[mopt_gameplay].status = IT_STRING | IT_TRANSTEXT; - OPTIONS_MainDef.menuitems[mopt_server].status = IT_STRING | IT_TRANSTEXT; - - // enable gameplay & server options under the right circumstances. - if (gamestate == GS_MENU - || ((server || IsPlayerAdmin(consoleplayer)) && K_CanChangeRules(false))) - { - OPTIONS_MainDef.menuitems[mopt_gameplay].status = IT_STRING | IT_SUBMENU; - OPTIONS_MainDef.menuitems[mopt_server].status = IT_STRING | IT_SUBMENU; - OPTIONS_GameplayDef.menuitems[gopt_encore].status = - (M_SecretUnlocked(SECRET_ENCORE, false) ? (IT_STRING | IT_CVAR) : IT_DISABLED); - } - - OPTIONS_DataDef.menuitems[dopt_erase].status = (gamestate == GS_MENU - ? (IT_STRING | IT_SUBMENU) - : (IT_TRANSTEXT2 | IT_SPACE)); - - M_ResetOptions(); - - // So that pause doesn't go to the main menu... - OPTIONS_MainDef.prevMenu = currentMenu; - - // This will disable or enable the textboxes of the affected menus before we get to them. - Screenshot_option_Onchange(); - Moviemode_mode_Onchange(); - Moviemode_option_Onchange(); - Addons_option_Onchange(); - - M_SetupNextMenu(&OPTIONS_MainDef, false); -} - -// Prepares changing the colour of the background -void M_OptionsChangeBGColour(INT16 newcolour) -{ - optionsmenu.fade = 10; - optionsmenu.lastcolour = optionsmenu.currcolour; - optionsmenu.currcolour = newcolour; -} - -boolean M_OptionsQuit(void) -{ - optionsmenu.toptx = 140-1; - optionsmenu.topty = 70+1; - - // Reset button behaviour because profile menu is different, since of course it is. - if (optionsmenu.resetprofilemenu) - { - optionsmenu.profilemenu = false; - optionsmenu.profile = NULL; - optionsmenu.resetprofilemenu = false; - } - - return true; // Always allow quitting, duh. -} - -void M_OptionsTick(void) -{ - optionsmenu.offset /= 2; - optionsmenu.ticker++; - - optionsmenu.optx += (optionsmenu.toptx - optionsmenu.optx)/2; - optionsmenu.opty += (optionsmenu.topty - optionsmenu.opty)/2; - - if (abs(optionsmenu.optx - optionsmenu.opty) < 2) - { - optionsmenu.optx = optionsmenu.toptx; - optionsmenu.opty = optionsmenu.topty; // Avoid awkward 1 px errors. - } - - // Move the button for cool animations - if (currentMenu == &OPTIONS_MainDef) - { - M_OptionsQuit(); // ...So now this is used here. - } - else if (optionsmenu.profile == NULL) // Not currently editing a profile (otherwise we're using these variables for other purposes....) - { - // I don't like this, it looks like shit but it needs to be done.......... - if (optionsmenu.profilemenu) - { - optionsmenu.toptx = 420; - optionsmenu.topty = 70+1; - } - else if (currentMenu == &OPTIONS_GameplayItemsDef) - { - optionsmenu.toptx = -160; // off the side of the screen - optionsmenu.topty = 50; - } - else - { - optionsmenu.toptx = 160; - optionsmenu.topty = 50; - } - } - - // Handle the background stuff: - if (optionsmenu.fade) - optionsmenu.fade--; - - // change the colour if we aren't matching the current menu colour - if (optionsmenu.currcolour != currentMenu->extra1) - M_OptionsChangeBGColour(currentMenu->extra1); - - // And one last giggle... - if (shitsfree) - shitsfree--; -} - -boolean M_OptionsInputs(INT32 ch) -{ - - const UINT8 pid = 0; - (void)ch; - - if (menucmd[pid].dpad_ud > 0) - { - M_SetMenuDelay(pid); - optionsmenu.offset += 48; - M_NextOpt(); - S_StartSound(NULL, sfx_s3k5b); - - if (itemOn == 0) - optionsmenu.offset -= currentMenu->numitems*48; - - - return true; - } - else if (menucmd[pid].dpad_ud < 0) - { - M_SetMenuDelay(pid); - optionsmenu.offset -= 48; - M_PrevOpt(); - S_StartSound(NULL, sfx_s3k5b); - - if (itemOn == currentMenu->numitems-1) - optionsmenu.offset += currentMenu->numitems*48; - - - return true; - } - else if (M_MenuConfirmPressed(pid)) - { - - if (currentMenu->menuitems[itemOn].status & IT_TRANSTEXT) - return true; // No. - - optionsmenu.optx = 140; - optionsmenu.opty = 70; // Default position for the currently selected option. - return false; // Don't eat. - } - return false; -} - -void M_ProfileSelectInit(INT32 choice) -{ - (void)choice; - optionsmenu.profilemenu = true; - - M_SetupNextMenu(&OPTIONS_ProfilesDef, false); -} - -// setup video mode menu -void M_VideoModeMenu(INT32 choice) -{ - INT32 i, j, vdup, nummodes; - UINT32 width, height; - const char *desc; - - (void)choice; - - memset(optionsmenu.modedescs, 0, sizeof(optionsmenu.modedescs)); - -#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) - VID_PrepareModeList(); // FIXME: hack -#endif - optionsmenu.vidm_nummodes = 0; - optionsmenu.vidm_selected = 0; - nummodes = VID_NumModes(); - - // DOS does not skip mode 0, because mode 0 is ALWAYS present - i = 0; - for (; i < nummodes && optionsmenu.vidm_nummodes < MAXMODEDESCS; i++) - { - desc = VID_GetModeName(i); - if (desc) - { - vdup = 0; - - // when a resolution exists both under VGA and VESA, keep the - // VESA mode, which is always a higher modenum - for (j = 0; j < optionsmenu.vidm_nummodes; j++) - { - if (!strcmp(optionsmenu.modedescs[j].desc, desc)) - { - // mode(0): 320x200 is always standard VGA, not vesa - if (optionsmenu.modedescs[j].modenum) - { - optionsmenu.modedescs[j].modenum = i; - vdup = 1; - - if (i == vid.modenum) - optionsmenu.vidm_selected = j; - } - else - vdup = 1; - - break; - } - } - - if (!vdup) - { - optionsmenu.modedescs[optionsmenu.vidm_nummodes].modenum = i; - optionsmenu.modedescs[optionsmenu.vidm_nummodes].desc = desc; - - if (i == vid.modenum) - optionsmenu.vidm_selected = optionsmenu.vidm_nummodes; - - // Pull out the width and height - sscanf(desc, "%u%*c%u", &width, &height); - - // Show multiples of 320x200 as green. - if (SCR_IsAspectCorrect(width, height)) - optionsmenu.modedescs[optionsmenu.vidm_nummodes].goodratio = 1; - - optionsmenu.vidm_nummodes++; - } - } - } - - optionsmenu.vidm_column_size = (optionsmenu.vidm_nummodes+2) / 3; - - M_SetupNextMenu(&OPTIONS_VideoModesDef, false); -} - -// Select the current profile for menu use and go to maindef. -static void M_FirstPickProfile(INT32 c) -{ - if (c == MA_YES) - { - M_ResetOptions(); // Reset all options variables otherwise things are gonna go reaaal bad lol. - optionsmenu.profile = NULL; // Make sure to get rid of that, too. - - PR_ApplyProfile(optionsmenu.profilen, 0); - M_SetupNextMenu(M_InterruptMenuWithChallenges(&MainDef), false); - - // Tell the game this is the last profile we picked. - CV_StealthSetValue(&cv_ttlprofilen, optionsmenu.profilen); - - // Save em! - PR_SaveProfiles(); - return; - } -} - -// Start menu edition. Call this with MA_YES if not used with a textbox. -static void M_StartEditProfile(INT32 c) -{ - - const INT32 maxp = PR_GetNumProfiles(); - - if (c == MA_YES) - { - if (optionsmenu.profilen == maxp) - PR_InitNewProfile(); // initialize the new profile. - - optionsmenu.profile = PR_GetProfile(optionsmenu.profilen); - // copy this profile's controls into optionsmenu so that we can edit controls without changing them directly. - // we do this so that we don't edit a profile's controls in real-time and end up doing really weird shit. - memcpy(&optionsmenu.tempcontrols, optionsmenu.profile->controls, sizeof(gamecontroldefault)); - - // This is now used to move the card we've selected. - optionsmenu.optx = 160; - optionsmenu.opty = 35; - optionsmenu.toptx = 130/2; - optionsmenu.topty = 0; - - // setup cvars - if (optionsmenu.profile->version) - { - CV_StealthSet(&cv_dummyprofilename, optionsmenu.profile->profilename); - CV_StealthSet(&cv_dummyprofileplayername, optionsmenu.profile->playername); - CV_StealthSetValue(&cv_dummyprofilekickstart, optionsmenu.profile->kickstartaccel); - } - else - { - CV_StealthSet(&cv_dummyprofilename, ""); - CV_StealthSet(&cv_dummyprofileplayername, ""); - CV_StealthSetValue(&cv_dummyprofilekickstart, 0); // off - } - - // Setup greyout and stuff. - OPTIONS_EditProfile[popt_profilename].status = IT_STRING | IT_CVAR | IT_CV_STRING; - OPTIONS_EditProfile[popt_profilepname].status = IT_STRING | IT_CVAR | IT_CV_STRING; - OPTIONS_EditProfile[popt_char].status = IT_STRING | IT_CALL; - - if (gamestate != GS_MENU) // If we're modifying things mid game, transtext some of those! - { - OPTIONS_EditProfile[popt_profilename].status |= IT_TRANSTEXT; - OPTIONS_EditProfile[popt_profilepname].status |= IT_TRANSTEXT; - OPTIONS_EditProfile[popt_char].status |= IT_TRANSTEXT; - } - - M_SetupNextMenu(&OPTIONS_EditProfileDef, false); - return; - } -} - -void M_HandleProfileSelect(INT32 ch) -{ - const UINT8 pid = 0; - INT32 maxp = PR_GetNumProfiles(); - boolean creatable = (maxp < MAXPROFILES); - (void) ch; - - if (!creatable) - { - maxp = MAXPROFILES; - } - - if (menucmd[pid].dpad_lr > 0) - { - optionsmenu.profilen++; - optionsmenu.offset += (128 + 128/8); - - if (optionsmenu.profilen > maxp) - { - optionsmenu.profilen = 0; - optionsmenu.offset -= (128 + 128/8)*(maxp+1); - } - - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - - } - else if (menucmd[pid].dpad_lr < 0) - { - optionsmenu.profilen--; - optionsmenu.offset -= (128 + 128/8); - - if (optionsmenu.profilen < 0) - { - optionsmenu.profilen = maxp; - optionsmenu.offset += (128 + 128/8)*(maxp+1); - } - - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - - else if (M_MenuConfirmPressed(pid)) - { - - // Boot profile setup has already been done. - if (cv_currprofile.value > -1) - { - - if (optionsmenu.profilen == 0) // Guest profile, you can't edit that one! - { - S_StartSound(NULL, sfx_s3k7b); - M_StartMessage(M_GetText("The Guest profile cannot be edited.\nCreate a new profile instead."), NULL, MM_NOTHING); - M_SetMenuDelay(pid); - return; - } - else if (creatable && optionsmenu.profilen == maxp && gamestate != GS_MENU) - { - S_StartSound(NULL, sfx_s3k7b); - M_StartMessage(M_GetText("Cannot create a new profile\nmid-game. Return to the\ntitle screen first."), NULL, MM_NOTHING); - M_SetMenuDelay(pid); - return; - } - - S_StartSound(NULL, sfx_s3k5b); - M_StartEditProfile(MA_YES); - } - else - { - // We're on the profile selection screen. - if (creatable && optionsmenu.profilen == maxp) - { - M_StartEditProfile(MA_YES); - M_SetMenuDelay(pid); - return; - } - else - { -#if 0 - if (optionsmenu.profilen == 0) - { - M_StartMessage(M_GetText("Are you sure you wish\nto use the Guest Profile?\nThis profile cannot be customised.\nIt is recommended to create\na new Profile instead.\n\nPress (A) to confirm or (B) to cancel"), FUNCPTRCAST(M_FirstPickProfile), MM_YESNO); - return; - } -#endif - - M_FirstPickProfile(MA_YES); - M_SetMenuDelay(pid); - return; - } - } - } - - else if (M_MenuBackPressed(pid)) - { - optionsmenu.resetprofilemenu = true; - M_GoBack(0); - M_SetMenuDelay(pid); - } - - if (menutransition.tics == 0 && optionsmenu.resetprofile) - { - optionsmenu.profile = NULL; // Make sure to reset that when transitions are done.' - optionsmenu.resetprofile = false; - } -} - -// Returns true if the profile can be saved, false otherwise. Also starts messages if necessary. -static boolean M_ProfileEditEnd(const UINT8 pid) -{ - UINT8 i; - - // Guest profile, you can't edit that one! - if (optionsmenu.profilen == 0) - { - S_StartSound(NULL, sfx_s3k7b); - M_StartMessage(M_GetText("Guest profile cannot be edited.\nCreate a new profile instead."), NULL, MM_NOTHING); - M_SetMenuDelay(pid); - return false; - } - - // check if some profiles have the same name - for (i = 0; i < PR_GetNumProfiles(); i++) - { - profile_t *check = PR_GetProfile(i); - - // For obvious reasons don't check if our name is the same as our name.... - if (check != optionsmenu.profile) - { - if (!(strcmp(optionsmenu.profile->profilename, check->profilename))) - { - S_StartSound(NULL, sfx_s3k7b); - M_StartMessage(M_GetText("Another profile uses the same name.\nThis must be changed to be able to save."), NULL, MM_NOTHING); - M_SetMenuDelay(pid); - return false; - } - } - } - - return true; -} - -static void M_ProfileEditExit(void) -{ - optionsmenu.toptx = 160; - optionsmenu.topty = 35; - optionsmenu.resetprofile = true; // Reset profile after the transition is done. - - PR_SaveProfiles(); // save profiles after we do that. -} - -// For profile edit, just make sure going back resets the card to its position, the rest is taken care of automatically. -boolean M_ProfileEditInputs(INT32 ch) -{ - - (void) ch; - const UINT8 pid = 0; - - if (M_MenuBackPressed(pid)) - { - if (M_ProfileEditEnd(pid)) - { - M_ProfileEditExit(); - if (cv_currprofile.value == -1) - M_SetupNextMenu(&MAIN_ProfilesDef, false); - else - M_GoBack(0); - M_SetMenuDelay(pid); - } - return true; - } - else if (M_MenuConfirmPressed(pid)) - { - if (currentMenu->menuitems[itemOn].status & IT_TRANSTEXT) - return true; // No. - } - - return false; -} - -// Handle some actions in profile editing -void M_HandleProfileEdit(void) -{ - // Always copy the profile name and player name in the profile. - if (optionsmenu.profile) - { - // Copy the first 6 chars for profile name - if (strlen(cv_dummyprofilename.string)) - { - char *s; - // convert dummyprofilename to uppercase - strncpy(optionsmenu.profile->profilename, cv_dummyprofilename.string, PROFILENAMELEN); - s = optionsmenu.profile->profilename; - while (*s) - { - *s = toupper(*s); - s++; - } - } - - if (strlen(cv_dummyprofileplayername.string)) - strncpy(optionsmenu.profile->playername, cv_dummyprofileplayername.string, MAXPLAYERNAME); - } - - M_OptionsTick(); // Has to be afterwards because this can unset optionsmenu.profile -} - -// Confirm Profile edi via button. -void M_ConfirmProfile(INT32 choice) -{ - const UINT8 pid = 0; - (void) choice; - - if (M_ProfileEditEnd(pid)) - { - if (cv_currprofile.value > -1) - { - M_ProfileEditExit(); - M_GoBack(0); - M_SetMenuDelay(pid); - } - else - { - M_StartMessage(M_GetText("Are you sure you wish to\nselect this profile?\n\nPress (A) to confirm or (B) to cancel"), FUNCPTRCAST(M_FirstPickProfile), MM_YESNO); - M_SetMenuDelay(pid); - } - } - return; -} - -// special menuitem key handler for video mode list -void M_HandleVideoModes(INT32 ch) -{ - - const UINT8 pid = 0; - (void)ch; - - if (optionsmenu.vidm_testingmode > 0) - { - // change back to the previous mode quickly - if (M_MenuBackPressed(pid)) - { - setmodeneeded = optionsmenu.vidm_previousmode + 1; - optionsmenu.vidm_testingmode = 0; - } - else if (M_MenuConfirmPressed(pid)) - { - S_StartSound(NULL, sfx_s3k5b); - optionsmenu.vidm_testingmode = 0; // stop testing - } - } - - else - { - if (menucmd[pid].dpad_ud > 0) - { - S_StartSound(NULL, sfx_s3k5b); - if (++optionsmenu.vidm_selected >= optionsmenu.vidm_nummodes) - optionsmenu.vidm_selected = 0; - - M_SetMenuDelay(pid); - } - - else if (menucmd[pid].dpad_ud < 0) - { - S_StartSound(NULL, sfx_s3k5b); - if (--optionsmenu.vidm_selected < 0) - optionsmenu.vidm_selected = optionsmenu.vidm_nummodes - 1; - - M_SetMenuDelay(pid); - } - - else if (menucmd[pid].dpad_lr < 0) - { - S_StartSound(NULL, sfx_s3k5b); - optionsmenu.vidm_selected -= optionsmenu.vidm_column_size; - if (optionsmenu.vidm_selected < 0) - optionsmenu.vidm_selected = (optionsmenu.vidm_column_size*3) + optionsmenu.vidm_selected; - if (optionsmenu.vidm_selected >= optionsmenu.vidm_nummodes) - optionsmenu.vidm_selected = optionsmenu.vidm_nummodes - 1; - - M_SetMenuDelay(pid); - } - - else if (menucmd[pid].dpad_lr > 0) - { - S_StartSound(NULL, sfx_s3k5b); - optionsmenu.vidm_selected += optionsmenu.vidm_column_size; - if (optionsmenu.vidm_selected >= (optionsmenu.vidm_column_size*3)) - optionsmenu.vidm_selected %= optionsmenu.vidm_column_size; - if (optionsmenu.vidm_selected >= optionsmenu.vidm_nummodes) - optionsmenu.vidm_selected = optionsmenu.vidm_nummodes - 1; - - M_SetMenuDelay(pid); - } - - else if (M_MenuConfirmPressed(pid)) - { - M_SetMenuDelay(pid); - S_StartSound(NULL, sfx_s3k5b); - if (vid.modenum == optionsmenu.modedescs[optionsmenu.vidm_selected].modenum) - SCR_SetDefaultMode(); - else - { - optionsmenu.vidm_testingmode = 15*TICRATE; - optionsmenu.vidm_previousmode = vid.modenum; - if (!setmodeneeded) // in case the previous setmode was not finished - setmodeneeded = optionsmenu.modedescs[optionsmenu.vidm_selected].modenum + 1; - } - } - - else if (M_MenuBackPressed(pid)) - { - M_SetMenuDelay(pid); - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu, false); - else - M_ClearMenus(true); - } - } -} - -// sets whatever device has had its key pressed to the active device. -// 20/05/22: Commented out for now but not deleted as it might still find some use in the future? -/* -static void SetDeviceOnPress(void) -{ - UINT8 i; - - for (i=0; i < MAXDEVICES; i++) - { - if (deviceResponding[i]) - { - CV_SetValue(&cv_usejoystick[0], i); // Force-set this joystick as the current joystick we're using for P1 (which is the only one controlling menus) - CONS_Printf("SetDeviceOnPress: Device for %d set to %d\n", 0, i); - return; - } - } -} -*/ - - -// Prompt a device selection window (just tap any button on the device you want) -void M_ProfileDeviceSelect(INT32 choice) -{ - (void)choice; - - // While we're here, setup the incoming controls menu to reset the scroll & bind status: - optionsmenu.controlscroll = 0; - optionsmenu.bindcontrol = 0; - optionsmenu.bindtimer = 0; - - optionsmenu.lastkey = 0; - optionsmenu.keyheldfor = 0; - - optionsmenu.contx = optionsmenu.tcontx = controlleroffsets[gc_a][0]; - optionsmenu.conty = optionsmenu.tconty = controlleroffsets[gc_a][1]; - - M_SetupNextMenu(&OPTIONS_ProfileControlsDef, false); // Don't set device here anymore. -} - -void M_HandleProfileControls(void) -{ - UINT8 maxscroll = currentMenu->numitems - 5; - M_OptionsTick(); - - optionsmenu.contx += (optionsmenu.tcontx - optionsmenu.contx)/2; - optionsmenu.conty += (optionsmenu.tconty - optionsmenu.conty)/2; - - if (abs(optionsmenu.contx - optionsmenu.tcontx) < 2 && abs(optionsmenu.conty - optionsmenu.tconty) < 2) - { - optionsmenu.contx = optionsmenu.tcontx; - optionsmenu.conty = optionsmenu.tconty; // Avoid awkward 1 px errors. - } - - optionsmenu.controlscroll = itemOn - 3; // very barebones scrolling, but it works just fine for our purpose. - if (optionsmenu.controlscroll > maxscroll) - optionsmenu.controlscroll = maxscroll; - - if (optionsmenu.controlscroll < 0) - optionsmenu.controlscroll = 0; - - // bindings, cancel if timer is depleted. - if (optionsmenu.bindcontrol) - { - optionsmenu.bindtimer--; - if (!optionsmenu.bindtimer) - { - optionsmenu.bindcontrol = 0; // we've gone past the max, just stop. - } - - } -} - -void M_ProfileTryController(INT32 choice) -{ - (void)choice; - - optionsmenu.trycontroller = TICRATE*5; - - // Apply these controls right now on P1's end. - memcpy(&gamecontrol[0], optionsmenu.tempcontrols, sizeof(gamecontroldefault)); -} - -static void M_ProfileControlSaveResponse(INT32 choice) -{ - if (choice == MA_YES) - { - SINT8 belongsto = PR_ProfileUsedBy(optionsmenu.profile); - // Save the profile - optionsmenu.profile->kickstartaccel = cv_dummyprofilekickstart.value; - memcpy(&optionsmenu.profile->controls, optionsmenu.tempcontrols, sizeof(gamecontroldefault)); - - // If this profile is in-use by anyone, apply the changes immediately upon exiting. - // Don't apply the profile itself as that would lead to issues mid-game. - if (belongsto > -1 && belongsto < MAXSPLITSCREENPLAYERS) - { - memcpy(&gamecontrol[belongsto], optionsmenu.tempcontrols, sizeof(gamecontroldefault)); - CV_StealthSetValue(&cv_kickstartaccel[belongsto], cv_dummyprofilekickstart.value); - } - - M_GoBack(0); - } -} - -void M_ProfileControlsConfirm(INT32 choice) -{ - (void)choice; - - //M_StartMessage(M_GetText("Exiting will save the control changes\nfor this Profile.\nIs this okay?\n\nPress (A) to confirm or (B) to cancel"), FUNCPTRCAST(M_ProfileControlSaveResponse), MM_YESNO); - // TODO: Add a graphic for controls saving, instead of obnoxious prompt. - - M_ProfileControlSaveResponse(MA_YES); - - optionsmenu.profile->kickstartaccel = cv_dummyprofilekickstart.value; // Make sure to save kickstart accel. - - // Reapply player 1's real profile. - if (cv_currprofile.value > -1) - { - PR_ApplyProfile(cv_lastprofile[0].value, 0); - } -} - -boolean M_ProfileControlsInputs(INT32 ch) -{ - const UINT8 pid = 0; - (void)ch; - - // By default, accept all inputs. - if (optionsmenu.trycontroller) - { - if (menucmd[pid].dpad_ud || menucmd[pid].dpad_lr || menucmd[pid].buttons) - { - optionsmenu.trycontroller = 5*TICRATE; - } - else - { - optionsmenu.trycontroller--; - } - - if (optionsmenu.trycontroller == 0) - { - // Reset controls to that of the current profile. - profile_t *cpr = PR_GetProfile(cv_currprofile.value); - if (cpr == NULL) - cpr = PR_GetProfile(0); // Creating a profile at boot, revert to guest profile - memcpy(&gamecontrol[0], cpr->controls, sizeof(gamecontroldefault)); - } - - return true; - } - - if (optionsmenu.bindcontrol) - return true; // Eat all inputs there. We'll use a stupid hack in M_Responder instead. - - //SetDeviceOnPress(); // Update device constantly so that we don't stay stuck with otpions saying a device is unavailable just because we're mapping multiple devices... - - if (M_MenuExtraPressed(pid)) - { - // check if we're on a valid menu option... - if (currentMenu->menuitems[itemOn].mvar1) - { - // clear controls for that key - INT32 i; - - for (i = 0; i < MAXINPUTMAPPING; i++) - optionsmenu.tempcontrols[currentMenu->menuitems[itemOn].mvar1][i] = KEY_NULL; - - S_StartSound(NULL, sfx_s3k66); - } - M_SetMenuDelay(pid); - return true; - } - else if (M_MenuBackPressed(pid)) - { - M_ProfileControlsConfirm(0); - M_SetMenuDelay(pid); - return true; - } - - return false; -} - -void M_ProfileSetControl(INT32 ch) -{ - INT32 controln = currentMenu->menuitems[itemOn].mvar1; - UINT8 i; - (void) ch; - - optionsmenu.bindcontrol = 1; // Default to control #1 - - for (i = 0; i < MAXINPUTMAPPING; i++) - { - if (optionsmenu.tempcontrols[controln][i] == KEY_NULL) - { - optionsmenu.bindcontrol = i+1; - break; - } - } - - // If we could find a null key to map into, map there. - // Otherwise, this will stay at 1 which means we'll overwrite the first bound control. - - optionsmenu.bindtimer = TICRATE*5; -} - -// Map the event to the profile. - -#define KEYHOLDFOR 1 -void M_MapProfileControl(event_t *ev) -{ - INT32 c = 0; - UINT8 n = optionsmenu.bindcontrol-1; // # of input to bind - INT32 controln = currentMenu->menuitems[itemOn].mvar1; // gc_ - UINT8 where = n; // By default, we'll save the bind where we're supposed to map. - INT32 i; - - //SetDeviceOnPress(); // Update cv_usejoystick - - // Only consider keydown and joystick events to make sure we ignore ev_mouse and other events - // See also G_MapEventsToControls - switch (ev->type) - { - case ev_keydown: - if (ev->data1 < NUMINPUTS) - { - c = ev->data1; - } -#ifdef PARANOIA - else - { - CONS_Debug(DBG_GAMELOGIC, "Bad downkey input %d\n", ev->data1); - } -#endif - break; - case ev_joystick: - if (ev->data1 >= JOYAXES) - { -#ifdef PARANOIA - CONS_Debug(DBG_GAMELOGIC, "Bad joystick axis event %d\n", ev->data1); -#endif - return; - } - else - { - INT32 deadzone = deadzone = (JOYAXISRANGE * cv_deadzone[0].value) / FRACUNIT; // TODO how properly account for different deadzone cvars for different devices - boolean responsivelr = ((ev->data2 != INT32_MAX) && (abs(ev->data2) >= deadzone)); - boolean responsiveud = ((ev->data3 != INT32_MAX) && (abs(ev->data3) >= deadzone)); - - i = ev->data1; - - if (i >= JOYANALOGS) - { - // The trigger axes are handled specially. - i -= JOYANALOGS; - - if (responsivelr) - { - c = KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2); - } - else if (responsiveud) - { - c = KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2) + 1; - } - } - else - { - // Actual analog sticks - - // Only consider unambiguous assignment. - if (responsivelr == responsiveud) - return; - - if (responsivelr) - { - if (ev->data2 < 0) - { - // Left - c = KEY_AXIS1 + (i * 4); - } - else - { - // Right - c = KEY_AXIS1 + (i * 4) + 1; - } - } - else //if (responsiveud) - { - if (ev->data3 < 0) - { - // Up - c = KEY_AXIS1 + (i * 4) + 2; - } - else - { - // Down - c = KEY_AXIS1 + (i * 4) + 3; - } - } - } - } - break; - default: - return; - } - - // safety result - if (!c) - return; - - // Set menu delay regardless of what we're doing to avoid stupid stuff. - M_SetMenuDelay(0); - - // Check if this particular key (c) is already bound in any slot. - // If that's the case, simply do nothing. - for (i = 0; i < MAXINPUTMAPPING; i++) - { - if (optionsmenu.tempcontrols[controln][i] == c) - { - optionsmenu.bindcontrol = 0; - return; - } - } - - // With the way we do things, there cannot be instances of 'gaps' within the controls, so we don't need to pretend like we need to handle that. - // Unless of course you tamper with the cfg file, but then it's *your* fault, not mine. - - optionsmenu.tempcontrols[controln][where] = c; - optionsmenu.bindcontrol = 0; // not binding anymore - - // If possible, reapply the profile... - // 19/05/22: Actually, no, don't do that, it just fucks everything up in too many cases. - - /* - if (gamestate == GS_MENU) // In menu? Apply this to P1, no questions asked. - { - // Apply the profile's properties to player 1 but keep the last profile cv to p1's ACTUAL profile to revert once we exit. - UINT8 lastp = cv_lastprofile[0].value; - PR_ApplyProfile(PR_GetProfileNum(optionsmenu.profile), 0); - CV_StealthSetValue(&cv_lastprofile[0], lastp); - } - else // != GS_MENU - { - // ONLY apply the profile if it's in use by anything currently. - UINT8 pnum = PR_GetProfileNum(optionsmenu.profile); - for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) - { - if (cv_lastprofile[i].value == pnum) - { - PR_ApplyProfile(pnum, i); - break; - } - } - } - */ -} -#undef KEYHOLDFOR - -void M_HandleItemToggles(INT32 choice) -{ - const INT32 width = 8, height = 4; - INT32 column = itemOn/height, row = itemOn%height; - INT16 next; - UINT8 i; - boolean exitmenu = false; - const UINT8 pid = 0; - - (void) choice; - - if (menucmd[pid].dpad_lr > 0) - { - S_StartSound(NULL, sfx_s3k5b); - column++; - if (((column*height)+row) >= currentMenu->numitems) - column = 0; - next = min(((column*height)+row), currentMenu->numitems-1); - itemOn = next; - - M_SetMenuDelay(pid); - } - - else if (menucmd[pid].dpad_lr < 0) - { - S_StartSound(NULL, sfx_s3k5b); - column--; - if (column < 0) - column = width-1; - if (((column*height)+row) >= currentMenu->numitems) - column--; - next = max(((column*height)+row), 0); - if (next >= currentMenu->numitems) - next = currentMenu->numitems-1; - itemOn = next; - - M_SetMenuDelay(pid); - } - - else if (menucmd[pid].dpad_ud > 0) - { - S_StartSound(NULL, sfx_s3k5b); - row = (row+1) % height; - if (((column*height)+row) >= currentMenu->numitems) - row = 0; - next = min(((column*height)+row), currentMenu->numitems-1); - itemOn = next; - - M_SetMenuDelay(pid); - } - - else if (menucmd[pid].dpad_ud < 0) - { - S_StartSound(NULL, sfx_s3k5b); - row = (row-1) % height; - if (row < 0) - row = height-1; - if (((column*height)+row) >= currentMenu->numitems) - row--; - next = max(((column*height)+row), 0); - if (next >= currentMenu->numitems) - next = currentMenu->numitems-1; - itemOn = next; - - M_SetMenuDelay(pid); - } - - else if (M_MenuConfirmPressed(pid)) - { - M_SetMenuDelay(pid); - if (currentMenu->menuitems[itemOn].mvar1 == 255) - { - //S_StartSound(NULL, sfx_s26d); - if (!shitsfree) - { - shitsfree = TICRATE; - S_StartSound(NULL, sfx_itfree); - } - } - else - if (currentMenu->menuitems[itemOn].mvar1 == 0) - { - INT32 v = cv_items[0].value; - S_StartSound(NULL, sfx_s1b4); - for (i = 0; i < NUMKARTRESULTS-1; i++) - { - if (cv_items[i].value == v) - CV_AddValue(&cv_items[i], 1); - } - } - else - { - if (currentMenu->menuitems[itemOn].mvar2) - { - S_StartSound(NULL, currentMenu->menuitems[itemOn].mvar2); - } - else - { - S_StartSound(NULL, sfx_s1ba); - } - CV_AddValue(&cv_items[currentMenu->menuitems[itemOn].mvar1-1], 1); - } - } - - else if (M_MenuBackPressed(pid)) - { - M_SetMenuDelay(pid); - exitmenu = true; - } - - if (exitmenu) - { - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu, false); - else - M_ClearMenus(true); - } -} - -// Check if we have any profile loaded. -void M_CheckProfileData(INT32 choice) -{ - UINT8 np = PR_GetNumProfiles(); - (void) choice; - - if (np < 2) - { - S_StartSound(NULL, sfx_s3k7b); - M_StartMessage("There are no custom profiles.\n\nPress (B)", NULL, MM_NOTHING); - return; - } - - optionsmenu.eraseprofilen = 1; - M_SetupNextMenu(&OPTIONS_DataProfileEraseDef, false); -} - -static void M_EraseProfileResponse(INT32 choice) -{ - if (choice == MA_YES) - { - S_StartSound(NULL, sfx_itrole); // bweh heh heh - - PR_DeleteProfile(optionsmenu.eraseprofilen); - - // Did we bust our current profile..!? - if (cv_currprofile.value == -1) - { - F_StartIntro(); - M_ClearMenus(true); - } - else if (optionsmenu.eraseprofilen > PR_GetNumProfiles()-1) - { - optionsmenu.eraseprofilen--; - } - } -} - -void M_HandleProfileErase(INT32 choice) -{ - const UINT8 pid = 0; - const UINT8 np = PR_GetNumProfiles()-1; - (void) choice; - - if (menucmd[pid].dpad_ud > 0) - { - S_StartSound(NULL, sfx_s3k5b); - optionsmenu.eraseprofilen++; - - if (optionsmenu.eraseprofilen > np) - optionsmenu.eraseprofilen = 1; - - M_SetMenuDelay(pid); - } - else if (menucmd[pid].dpad_ud < 0) - { - S_StartSound(NULL, sfx_s3k5b); - - if (optionsmenu.eraseprofilen == 1) - optionsmenu.eraseprofilen = np; - else - optionsmenu.eraseprofilen--; - - M_SetMenuDelay(pid); - } - else if (M_MenuBackPressed(pid)) - { - M_GoBack(0); - M_SetMenuDelay(pid); - } - else if (M_MenuConfirmPressed(pid)) - { - if (optionsmenu.eraseprofilen == cv_currprofile.value) - M_StartMessage("Your ""\x85""current profile""\x80"" will be erased.\nAre you sure you want to proceed?\nDeleting this profile will also\nreturn you to the title screen.\n\nPress (A) to confirm or (B) to cancel", FUNCPTRCAST(M_EraseProfileResponse), MM_YESNO); - else - M_StartMessage("This profile will be erased.\nAre you sure you want to proceed?\n\nPress (A) to confirm or (B) to cancel", FUNCPTRCAST(M_EraseProfileResponse), MM_YESNO); - - M_SetMenuDelay(pid); - } -} - -// Extras menu; -// this is copypasted from the options menu but all of these are different functions in case we ever want it to look more unique - -struct extrasmenu_s extrasmenu; - -void M_InitExtras(INT32 choice) -{ - (void)choice; - - extrasmenu.ticker = 0; - extrasmenu.offset = 0; - - extrasmenu.extx = 0; - extrasmenu.exty = 0; - extrasmenu.textx = 0; - extrasmenu.texty = 0; - - M_SetupNextMenu(&EXTRAS_MainDef, false); -} - -// For statistics, will maybe remain unused for a while -boolean M_ExtrasQuit(void) -{ - extrasmenu.textx = 140-1; - extrasmenu.texty = 70+1; - - return true; // Always allow quitting, duh. -} - -void M_ExtrasTick(void) -{ - extrasmenu.offset /= 2; - extrasmenu.ticker++; - - extrasmenu.extx += (extrasmenu.textx - extrasmenu.extx)/2; - extrasmenu.exty += (extrasmenu.texty - extrasmenu.exty)/2; - - if (abs(extrasmenu.extx - extrasmenu.exty) < 2) - { - extrasmenu.extx = extrasmenu.textx; - extrasmenu.exty = extrasmenu.texty; // Avoid awkward 1 px errors. - } - - // Move the button for cool animations - if (currentMenu == &EXTRAS_MainDef) - { - M_ExtrasQuit(); // reset the options button. - } - else - { - extrasmenu.textx = 160; - extrasmenu.texty = 50; - } -} - -boolean M_ExtrasInputs(INT32 ch) -{ - - const UINT8 pid = 0; - (void) ch; - - if (menucmd[pid].dpad_ud > 0) - { - extrasmenu.offset += 48; - M_NextOpt(); - S_StartSound(NULL, sfx_s3k5b); - - if (itemOn == 0) - extrasmenu.offset -= currentMenu->numitems*48; - - M_SetMenuDelay(pid); - return true; - } - - else if (menucmd[pid].dpad_ud < 0) - { - extrasmenu.offset -= 48; - M_PrevOpt(); - S_StartSound(NULL, sfx_s3k5b); - - if (itemOn == currentMenu->numitems-1) - extrasmenu.offset += currentMenu->numitems*48; - - M_SetMenuDelay(pid); - return true; - } - - else if (M_MenuConfirmPressed(pid)) - { - - if (currentMenu->menuitems[itemOn].status & IT_TRANSTEXT) - return true; // No. - - extrasmenu.extx = 140; - extrasmenu.exty = 70; // Default position for the currently selected option. - - M_SetMenuDelay(pid); - return false; // Don't eat. - } - return false; -} - -// ===================== -// PAUSE / IN-GAME MENUS -// ===================== -void M_EndModeAttackRun(void) -{ - G_CheckDemoStatus(); // Cancel recording - - if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) - Command_ExitGame_f(); - - M_StartControlPanel(); - - currentMenu = &PLAY_TimeAttackDef; - itemOn = currentMenu->lastOn; - - G_SetGamestate(GS_MENU); - S_ChangeMusicInternal("menu", true); - - modeattacking = ATTACKING_NONE; -} - -struct pausemenu_s pausemenu; - -// Pause menu! -void M_OpenPauseMenu(void) -{ - INT32 i = 0; - - currentMenu = &PAUSE_MainDef; - - // Ready the variables - pausemenu.ticker = 0; - - pausemenu.offset = 0; - pausemenu.openoffset = 256; - pausemenu.closing = false; - - currentMenu->lastOn = mpause_continue; // Make sure we select "RESUME GAME" by default - - // Now the hilarious balancing act of deciding what options should be enabled and which ones shouldn't be! - // By default, disable anything sensitive: - - PAUSE_Main[mpause_addons].status = IT_DISABLED; - PAUSE_Main[mpause_changegametype].status = IT_DISABLED; - PAUSE_Main[mpause_switchmap].status = IT_DISABLED; - PAUSE_Main[mpause_restartmap].status = IT_DISABLED; - PAUSE_Main[mpause_tryagain].status = IT_DISABLED; -#ifdef HAVE_DISCORDRPC - PAUSE_Main[mpause_discordrequests].status = IT_DISABLED; -#endif - - PAUSE_Main[mpause_spectate].status = IT_DISABLED; - PAUSE_Main[mpause_entergame].status = IT_DISABLED; - PAUSE_Main[mpause_canceljoin].status = IT_DISABLED; - PAUSE_Main[mpause_spectatemenu].status = IT_DISABLED; - PAUSE_Main[mpause_psetup].status = IT_DISABLED; - - Dummymenuplayer_OnChange(); // Make sure the consvar is within bounds of the amount of splitscreen players we have. - - if (K_CanChangeRules(false)) - { - PAUSE_Main[mpause_psetup].status = IT_STRING | IT_CALL; - - if (server || IsPlayerAdmin(consoleplayer)) - { - PAUSE_Main[mpause_changegametype].status = IT_STRING | IT_KEYHANDLER; - menugametype = gametype; - - PAUSE_Main[mpause_switchmap].status = IT_STRING | IT_CALL; - PAUSE_Main[mpause_restartmap].status = IT_STRING | IT_CALL; - PAUSE_Main[mpause_addons].status = IT_STRING | IT_CALL; - } - } - else if (!netgame && !demo.playback) - { - boolean retryallowed = (modeattacking != ATTACKING_NONE); - if (G_GametypeUsesLives()) - { - for (i = 0; i <= splitscreen; i++) - { - if (players[g_localplayers[i]].lives <= 1) - continue; - retryallowed = true; - break; - } - } - - if (retryallowed) - { - PAUSE_Main[mpause_tryagain].status = IT_STRING | IT_CALL; - } - } - - if (G_GametypeHasSpectators()) - { - if (splitscreen) - PAUSE_Main[mpause_spectatemenu].status = IT_STRING|IT_SUBMENU; - else - { - if (!players[consoleplayer].spectator) - PAUSE_Main[mpause_spectate].status = IT_STRING | IT_CALL; - else if (players[consoleplayer].pflags & PF_WANTSTOJOIN) - PAUSE_Main[mpause_canceljoin].status = IT_STRING | IT_CALL; - else - PAUSE_Main[mpause_entergame].status = IT_STRING | IT_CALL; - } - } -} - -void M_QuitPauseMenu(INT32 choice) -{ - (void)choice; - // M_PauseTick actually handles the quitting when it's been long enough. - pausemenu.closing = true; - pausemenu.openoffset = 4; -} - -void M_PauseTick(void) -{ - pausemenu.offset /= 2; - pausemenu.ticker++; - - if (pausemenu.closing) - { - pausemenu.openoffset *= 2; - if (pausemenu.openoffset > 255) - M_ClearMenus(true); - - } - else - pausemenu.openoffset /= 2; -} - -boolean M_PauseInputs(INT32 ch) -{ - - const UINT8 pid = 0; - (void) ch; - - if (pausemenu.closing) - return true; // Don't allow inputs. - - if (menucmd[pid].dpad_ud < 0) - { - M_SetMenuDelay(pid); - pausemenu.offset -= 50; // Each item is spaced by 50 px - S_StartSound(NULL, sfx_s3k5b); - M_PrevOpt(); - return true; - } - - else if (menucmd[pid].dpad_ud > 0) - { - pausemenu.offset += 50; // Each item is spaced by 50 px - S_StartSound(NULL, sfx_s3k5b); - M_NextOpt(); - M_SetMenuDelay(pid); - return true; - } - - else if (M_MenuBackPressed(pid) || M_MenuButtonPressed(pid, MBT_START)) - { - M_QuitPauseMenu(-1); - M_SetMenuDelay(pid); - return true; - } - return false; -} - -// Change gametype -void M_HandlePauseMenuGametype(INT32 choice) -{ - const UINT8 pid = 0; - const UINT32 forbidden = GTR_FORBIDMP; - - (void)choice; - - if (M_MenuConfirmPressed(pid)) - { - if (menugametype != gametype) - { - M_ClearMenus(true); - COM_ImmedExecute(va("randommap -gt %s", gametypes[menugametype]->name)); - return; - } - - M_SetMenuDelay(pid); - S_StartSound(NULL, sfx_s3k7b); - } - else if (M_MenuExtraPressed(pid)) - { - menugametype = gametype; - M_SetMenuDelay(pid); - S_StartSound(NULL, sfx_s3k7b); - } - else if (menucmd[pid].dpad_lr > 0) - { - M_NextMenuGametype(forbidden); - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - else if (menucmd[pid].dpad_lr < 0) - { - M_PrevMenuGametype(forbidden); - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } -} - -// Restart map -void M_RestartMap(INT32 choice) -{ - (void)choice; - M_ClearMenus(false); - COM_ImmedExecute("restartlevel"); -} - -// Try again -void M_TryAgain(INT32 choice) -{ - (void)choice; - if (demo.playback) - return; - - if (netgame || !Playing()) // Should never happen! - return; - - M_ClearMenus(false); - - if (modeattacking != ATTACKING_NONE) - { - G_CheckDemoStatus(); // Cancel recording - M_StartTimeAttack(-1); - } - else - { - G_SetRetryFlag(); - } -} - -// Pause spectate / join functions -void M_ConfirmSpectate(INT32 choice) -{ - (void)choice; - // We allow switching to spectator even if team changing is not allowed - M_QuitPauseMenu(-1); - COM_ImmedExecute("changeteam spectator"); -} - -void M_ConfirmEnterGame(INT32 choice) -{ - (void)choice; - if (!cv_allowteamchange.value) - { - M_StartMessage(M_GetText("The server is not allowing\nteam changes at this time.\n\nPress (B)\n"), NULL, MM_NOTHING); - return; - } - M_QuitPauseMenu(-1); - COM_ImmedExecute("changeteam playing"); -} - -static void M_ExitGameResponse(INT32 ch) -{ - if (ch != MA_YES) - return; - - if (modeattacking) - { - M_EndModeAttackRun(); - } - else - { - G_SetExitGameFlag(); - M_ClearMenus(true); - } -} - -void M_EndGame(INT32 choice) -{ - (void)choice; - if (demo.playback) - return; - - if (!Playing()) - return; - - M_StartMessage(M_GetText("Are you sure you want to\nreturn to the menu?\nPress (A) to confirm or (B) to cancel\n"), FUNCPTRCAST(M_ExitGameResponse), MM_YESNO); -} - - -// Replay Playback Menu -void M_SetPlaybackMenuPointer(void) -{ - itemOn = playback_pause; -} - -void M_PlaybackRewind(INT32 choice) -{ - static tic_t lastconfirmtime; - - (void)choice; - - if (!demo.rewinding) - { - if (paused) - { - G_ConfirmRewind(leveltime-1); - paused = true; - S_PauseAudio(); - } - else - demo.rewinding = paused = true; - } - else if (lastconfirmtime + TICRATE/2 < I_GetTime()) - { - lastconfirmtime = I_GetTime(); - G_ConfirmRewind(leveltime); - } - - CV_SetValue(&cv_playbackspeed, 1); -} - -void M_PlaybackPause(INT32 choice) -{ - (void)choice; - - paused = !paused; - - if (demo.rewinding) - { - G_ConfirmRewind(leveltime); - paused = true; - S_PauseAudio(); - } - else if (paused) - S_PauseAudio(); - else - S_ResumeAudio(); - - CV_SetValue(&cv_playbackspeed, 1); -} - -void M_PlaybackFastForward(INT32 choice) -{ - (void)choice; - - if (demo.rewinding) - { - G_ConfirmRewind(leveltime); - paused = false; - S_ResumeAudio(); - } - CV_SetValue(&cv_playbackspeed, cv_playbackspeed.value == 1 ? 4 : 1); -} - -void M_PlaybackAdvance(INT32 choice) -{ - (void)choice; - - paused = false; - TryRunTics(1); - paused = true; -} - -void M_PlaybackSetViews(INT32 choice) -{ - if (choice > 0) - { - if (splitscreen < 3) - G_AdjustView(splitscreen + 2, 0, true); - } - else if (splitscreen) - { - splitscreen--; - R_ExecuteSetViewSize(); - } -} - -void M_PlaybackAdjustView(INT32 choice) -{ - G_AdjustView(itemOn - playback_viewcount, (choice > 0) ? 1 : -1, true); -} - -// this one's rather tricky -void M_PlaybackToggleFreecam(INT32 choice) -{ - (void)choice; - M_ClearMenus(true); - - // remove splitscreen: - splitscreen = 0; - R_ExecuteSetViewSize(); - - P_InitCameraCmd(); // init camera controls - if (!demo.freecam) // toggle on - { - demo.freecam = true; - democam.cam = &camera[0]; // this is rather useful - } - else // toggle off - { - demo.freecam = false; - // reset democam vars: - democam.cam = NULL; - //democam.turnheld = false; - democam.keyboardlook = false; // reset only these. localangle / aiming gets set before the cam does anything anyway - } -} - -void M_PlaybackQuit(INT32 choice) -{ - (void)choice; - G_StopDemo(); - - if (demo.inreplayhut) - M_ReplayHut(choice); - else if (modeattacking) - M_EndModeAttackRun(); - else - D_StartTitle(); -} - -void M_PrepReplayList(void) -{ - size_t i; - - if (extrasmenu.demolist) - Z_Free(extrasmenu.demolist); - - extrasmenu.demolist = Z_Calloc(sizeof(menudemo_t) * sizedirmenu, PU_STATIC, NULL); - - for (i = 0; i < sizedirmenu; i++) - { - if (dirmenu[i][DIR_TYPE] == EXT_UP) - { - extrasmenu.demolist[i].type = MD_SUBDIR; - sprintf(extrasmenu.demolist[i].title, "UP"); - } - else if (dirmenu[i][DIR_TYPE] == EXT_FOLDER) - { - extrasmenu.demolist[i].type = MD_SUBDIR; - strncpy(extrasmenu.demolist[i].title, dirmenu[i] + DIR_STRING, 64); - } - else - { - extrasmenu.demolist[i].type = MD_NOTLOADED; - snprintf(extrasmenu.demolist[i].filepath, sizeof extrasmenu.demolist[i].filepath, - // 255 = UINT8 limit. dirmenu entries are restricted to this length (see DIR_LEN). - "%s%.255s", menupath, dirmenu[i] + DIR_STRING); - sprintf(extrasmenu.demolist[i].title, "....."); - } - } -} - - -void M_ReplayHut(INT32 choice) -{ - (void)choice; - - extrasmenu.replayScrollTitle = 0; - extrasmenu.replayScrollDelay = TICRATE; - extrasmenu.replayScrollDir = 1; - - if (!demo.inreplayhut) - { - snprintf(menupath, 1024, "%s"PATHSEP"media"PATHSEP"replay"PATHSEP"online"PATHSEP, srb2home); - menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath); - } - if (!preparefilemenu(false, true)) - { - M_StartMessage("No replays found.\n\nPress (B)\n", NULL, MM_NOTHING); - return; - } - else if (!demo.inreplayhut) - dir_on[menudepthleft] = 0; - demo.inreplayhut = true; - - extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; - - M_PrepReplayList(); - - menuactive = true; - M_SetupNextMenu(&EXTRAS_ReplayHutDef, false); - //G_SetGamestate(GS_TIMEATTACK); - //titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please - - demo.rewinding = false; - CL_ClearRewinds(); - - //S_ChangeMusicInternal("replst", true); -} - -// key handler -void M_HandleReplayHutList(INT32 choice) -{ - - const UINT8 pid = 0; - (void) choice; - - if (menucmd[pid].dpad_ud < 0) - { - if (dir_on[menudepthleft]) - dir_on[menudepthleft]--; - else - return; - //M_PrevOpt(); - - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; - } - - else if (menucmd[pid].dpad_ud > 0) - { - if (dir_on[menudepthleft] < sizedirmenu-1) - dir_on[menudepthleft]++; - else - return; - //itemOn = 0; // Not M_NextOpt because that would take us to the extra dummy item - - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; - } - - else if (M_MenuBackPressed(pid)) - { - M_SetMenuDelay(pid); - M_QuitReplayHut(); - } - - else if (M_MenuConfirmPressed(pid)) - { - M_SetMenuDelay(pid); - switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE]) - { - case EXT_FOLDER: - strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING); - if (menudepthleft) - { - menupathindex[--menudepthleft] = strlen(menupath); - menupath[menupathindex[menudepthleft]] = 0; - - if (!preparefilemenu(false, true)) - { - S_StartSound(NULL, sfx_s224); - M_StartMessage(va("%c%s\x80\nThis folder is empty.\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); - menupath[menupathindex[++menudepthleft]] = 0; - - if (!preparefilemenu(true, true)) - { - M_QuitReplayHut(); - return; - } - } - else - { - S_StartSound(NULL, sfx_s3k5b); - dir_on[menudepthleft] = 1; - M_PrepReplayList(); - } - } - else - { - S_StartSound(NULL, sfx_s26d); - M_StartMessage(va("%c%s\x80\nThis folder is too deep to navigate to!\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); - menupath[menupathindex[menudepthleft]] = 0; - } - break; - case EXT_UP: - S_StartSound(NULL, sfx_s3k5b); - menupath[menupathindex[++menudepthleft]] = 0; - if (!preparefilemenu(false, true)) - { - M_QuitReplayHut(); - return; - } - M_PrepReplayList(); - break; - default: - // We can't just use M_SetupNextMenu because that'll run ReplayDef's quitroutine and boot us back to the title screen! - currentMenu->lastOn = itemOn; - currentMenu = &EXTRAS_ReplayStartDef; - - extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; - - switch (extrasmenu.demolist[dir_on[menudepthleft]].addonstatus) - { - case DFILE_ERROR_CANNOTLOAD: - // Only show "Watch Replay Without Addons" - EXTRAS_ReplayStart[0].status = IT_DISABLED; - EXTRAS_ReplayStart[1].status = IT_CALL|IT_STRING; - //EXTRAS_ReplayStart[1].alphaKey = 0; - EXTRAS_ReplayStart[2].status = IT_DISABLED; - itemOn = 1; - break; - - case DFILE_ERROR_NOTLOADED: - case DFILE_ERROR_INCOMPLETEOUTOFORDER: - // Show "Load Addons and Watch Replay" and "Watch Replay Without Addons" - EXTRAS_ReplayStart[0].status = IT_CALL|IT_STRING; - EXTRAS_ReplayStart[1].status = IT_CALL|IT_STRING; - //EXTRAS_ReplayStart[1].alphaKey = 10; - EXTRAS_ReplayStart[2].status = IT_DISABLED; - itemOn = 0; - break; - - case DFILE_ERROR_EXTRAFILES: - case DFILE_ERROR_OUTOFORDER: - default: - // Show "Watch Replay" - EXTRAS_ReplayStart[0].status = IT_DISABLED; - EXTRAS_ReplayStart[1].status = IT_DISABLED; - EXTRAS_ReplayStart[2].status = IT_CALL|IT_STRING; - //EXTRAS_ReplayStart[2].alphaKey = 0; - itemOn = 2; - break; - } - } - } -} - -boolean M_QuitReplayHut(void) -{ - // D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate. - menuactive = false; - D_StartTitle(); - - if (extrasmenu.demolist) - Z_Free(extrasmenu.demolist); - extrasmenu.demolist = NULL; - - demo.inreplayhut = false; - - return true; -} - -void M_HutStartReplay(INT32 choice) -{ - (void)choice; - - M_ClearMenus(false); - demo.loadfiles = (itemOn == 0); - demo.ignorefiles = (itemOn != 0); - - G_DoPlayDemo(extrasmenu.demolist[dir_on[menudepthleft]].filepath); -} - - -static void Splitplayers_OnChange(void) -{ -#if 0 - if (cv_splitplayers.value < setupm_pselect) - setupm_pselect = 1; -#endif -} - -// Misc menus - -// Addons menu: (Merely copypasted, original code by toaster) - -void M_Addons(INT32 choice) -{ - const char *pathname = "."; - - (void)choice; - -#if 1 - if (cv_addons_option.value == 0) - pathname = addonsdir; - else if (cv_addons_option.value == 1) - pathname = srb2home; - else if (cv_addons_option.value == 2) - pathname = srb2path; - else -#endif - if (cv_addons_option.value == 3 && *cv_addons_folder.string != '\0') - pathname = cv_addons_folder.string; - - strlcpy(menupath, pathname, 1024); - menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath) + 1; - - if (menupath[menupathindex[menudepthleft]-2] != PATHSEP[0]) - { - menupath[menupathindex[menudepthleft]-1] = PATHSEP[0]; - menupath[menupathindex[menudepthleft]] = 0; - } - else - --menupathindex[menudepthleft]; - - if (!preparefilemenu(false, false)) - { - M_StartMessage(va("No files/folders found.\n\n%s\n\nPress (B)\n", LOCATIONSTRING1),NULL,MM_NOTHING); - return; - } - else - dir_on[menudepthleft] = 0; - - MISC_AddonsDef.lastOn = 0; // Always start on search - - MISC_AddonsDef.prevMenu = currentMenu; - M_SetupNextMenu(&MISC_AddonsDef, false); -} - - -char *M_AddonsHeaderPath(void) -{ - UINT32 len; - static char header[1024]; - - strlcpy(header, va("%s folder%s", cv_addons_option.string, menupath+menupathindex[menudepth-1]-1), 1024); - len = strlen(header); - if (len > 34) - { - len = len-34; - header[len] = header[len+1] = header[len+2] = '.'; - } - else - len = 0; - - return header+len; -} - -#define UNEXIST S_StartSound(NULL, sfx_s26d);\ - M_SetupNextMenu(MISC_AddonsDef.prevMenu, false);\ - M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\nPress (B)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING) - -#define CLEARNAME Z_Free(refreshdirname);\ - refreshdirname = NULL - -static boolean prevmajormods = false; - -static void M_AddonsClearName(INT32 choice) -{ - if (!majormods || prevmajormods) - { - CLEARNAME; - } - M_StopMessage(choice); -} - -// Handles messages for addon errors. -void M_AddonsRefresh(void) -{ - if ((refreshdirmenu & REFRESHDIR_NORMAL) && !preparefilemenu(true, false)) - { - UNEXIST; - if (refreshdirname) - { - CLEARNAME; - } - return;// true; - } - -#ifdef DEVELOP - prevmajormods = majormods; -#else - if (!majormods && prevmajormods) - prevmajormods = false; -#endif - - if ((refreshdirmenu & REFRESHDIR_ADDFILE) || (majormods && !prevmajormods)) - { - char *message = NULL; - - if (refreshdirmenu & REFRESHDIR_NOTLOADED) - { - S_StartSound(NULL, sfx_s26d); - if (refreshdirmenu & REFRESHDIR_MAX) - message = va("%c%s\x80\nMaximum number of addons reached.\nA file could not be loaded.\nIf you wish to play with this addon, restart the game to clear existing ones.\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); - else - message = va("%c%s\x80\nA file was not loaded.\nCheck the console log for more info.\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); - } - else if (refreshdirmenu & (REFRESHDIR_WARNING|REFRESHDIR_ERROR)) - { - S_StartSound(NULL, sfx_s224); - message = va("%c%s\x80\nA file was loaded with %s.\nCheck the console log for more info.\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname, ((refreshdirmenu & REFRESHDIR_ERROR) ? "errors" : "warnings")); - } - else if (majormods && !prevmajormods) - { - S_StartSound(NULL, sfx_s221); - message = va("%c%s\x80\nYou've loaded a gameplay-modifying addon.\n\nRecord Attack has been disabled, but you\ncan still play alone in local Multiplayer.\n\nIf you wish to play Record Attack mode, restart the game to disable loaded addons.\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); - prevmajormods = majormods; - } - - if (message) - { - M_StartMessage(message,FUNCPTRCAST(M_AddonsClearName),MM_YESNO); - return;// true; - } - - S_StartSound(NULL, sfx_s221); - CLEARNAME; - } - - return;// false; -} - -static void M_AddonExec(INT32 ch) -{ - if (ch == MA_YES) - { - S_StartSound(NULL, sfx_zoom); - COM_BufAddText(va("exec \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); - } -} - -static void M_UpdateAddonsSearch(void) -{ - menusearch[0] = strlen(cv_dummyaddonsearch.string); - strlcpy(menusearch+1, cv_dummyaddonsearch.string, MAXSTRINGLENGTH); - if (!cv_addons_search_case.value) - strupr(menusearch+1); - -#if 0 // much slower - if (!preparefilemenu(true, false)) - { - UNEXIST; - return; - } -#else // streamlined - searchfilemenu(NULL); -#endif -} - -void M_HandleAddons(INT32 choice) -{ - const UINT8 pid = 0; - boolean exitmenu = false; // exit to previous menu - - (void) choice; - - if (menucmd[pid].dpad_ud > 0) - { - if (dir_on[menudepthleft] < sizedirmenu-1) - { - dir_on[menudepthleft]++; - S_StartSound(NULL, sfx_s3k5b); - } - else if (M_NextOpt()) - { - S_StartSound(NULL, sfx_s3k5b); - } - M_SetMenuDelay(pid); - } - else if (menucmd[pid].dpad_ud < 0) - { - if (dir_on[menudepthleft]) - { - dir_on[menudepthleft]--; - S_StartSound(NULL, sfx_s3k5b); - } - else if (M_PrevOpt()) - { - S_StartSound(NULL, sfx_s3k5b); - } - M_SetMenuDelay(pid); - } - - else if (M_MenuButtonPressed(pid, MBT_L)) - { - UINT8 i; - for (i = numaddonsshown; i && (dir_on[menudepthleft] < sizedirmenu-1); i--) - dir_on[menudepthleft]++; - - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - - else if (M_MenuButtonPressed(pid, MBT_R)) - { - UINT8 i; - for (i = numaddonsshown; i && (dir_on[menudepthleft]); i--) - dir_on[menudepthleft]--; - - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - - else if (M_MenuConfirmPressed(pid)) - { - boolean refresh = true; - M_SetMenuDelay(pid); - - if (!dirmenu[dir_on[menudepthleft]]) - S_StartSound(NULL, sfx_s26d); - else - { - switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE]) - { - case EXT_FOLDER: - strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING); - if (menudepthleft) - { - menupathindex[--menudepthleft] = strlen(menupath); - menupath[menupathindex[menudepthleft]] = 0; - - if (!preparefilemenu(false, false)) - { - S_StartSound(NULL, sfx_s224); - M_StartMessage(va("%c%s\x80\nThis folder is empty.\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); - menupath[menupathindex[++menudepthleft]] = 0; - - if (!preparefilemenu(true, false)) - { - UNEXIST; - return; - } - } - else - { - S_StartSound(NULL, sfx_s3k5b); - dir_on[menudepthleft] = 1; - } - refresh = false; - } - else - { - S_StartSound(NULL, sfx_s26d); - M_StartMessage(va("%c%s\x80\nThis folder is too deep to navigate to!\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); - menupath[menupathindex[menudepthleft]] = 0; - } - break; - - case EXT_UP: - S_StartSound(NULL, sfx_s3k5b); - menupath[menupathindex[++menudepthleft]] = 0; - if (!preparefilemenu(false, false)) - { - UNEXIST; - return; - } - break; - - case EXT_TXT: - M_StartMessage(va("%c%s\x80\nThis file may not be a console script.\nAttempt to run anyways? \n\nPress (A) to confirm or (B) to cancel\n\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),FUNCPTRCAST(M_AddonExec),MM_YESNO); - break; - - case EXT_CFG: - M_StartMessage(va("%c%s\x80\nThis file may modify your settings.\nAttempt to run anyways? \n\nPress (A) to confirm or (B) to cancel\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),FUNCPTRCAST(M_AddonExec),MM_YESNO); - break; - - case EXT_LUA: - case EXT_SOC: - case EXT_WAD: -#ifdef USE_KART - case EXT_KART: -#endif - case EXT_PK3: - COM_BufAddText(va("addfile \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); - break; - - default: - S_StartSound(NULL, sfx_s26d); - } - - if (refresh) - refreshdirmenu |= REFRESHDIR_NORMAL; - } - } - else if (M_MenuBackPressed(pid)) - { - exitmenu = true; - M_SetMenuDelay(pid); - } - - - if (exitmenu) - { - closefilemenu(true); - - // Secret menu! - //MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED); - - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu, false); - else - M_ClearMenus(true); - - M_SetMenuDelay(pid); - } -} - -// Opening manual -void M_Manual(INT32 choice) -{ - (void)choice; - - MISC_ManualDef.prevMenu = (choice == INT32_MAX ? NULL : currentMenu); - M_SetupNextMenu(&MISC_ManualDef, true); -} - -// Challenges menu - -struct challengesmenu_s challengesmenu; - -menu_t *M_InterruptMenuWithChallenges(menu_t *desiredmenu) -{ - UINT8 i; - - M_UpdateUnlockablesAndExtraEmblems(false); - - if ((challengesmenu.pending = challengesmenu.requestnew = (M_GetNextAchievedUnlock() < MAXUNLOCKABLES))) - { - MISC_ChallengesDef.prevMenu = desiredmenu; - } - - if (challengesmenu.pending || desiredmenu == NULL) - { - challengesmenu.currentunlock = MAXUNLOCKABLES; - challengesmenu.unlockcondition = NULL; - - M_PopulateChallengeGrid(); - if (gamedata->challengegrid) - challengesmenu.extradata = M_ChallengeGridExtraData(); - - memset(setup_explosions, 0, sizeof(setup_explosions)); - memset(&challengesmenu.unlockcount, 0, sizeof(challengesmenu.unlockcount)); - for (i = 0; i < MAXUNLOCKABLES; i++) - { - if (!unlockables[i].conditionset) - { - continue; - } - - challengesmenu.unlockcount[CC_TOTAL]++; - - if (!gamedata->unlocked[i]) - { - continue; - } - - challengesmenu.unlockcount[CC_UNLOCKED]++; - } - - return &MISC_ChallengesDef; - } - - return desiredmenu; -} - -static void M_ChallengesAutoFocus(UINT8 unlockid, boolean fresh) -{ - UINT8 i; - SINT8 work; - - if (unlockid >= MAXUNLOCKABLES) - return; - - challengesmenu.currentunlock = unlockid; - challengesmenu.unlockcondition = M_BuildConditionSetString(challengesmenu.currentunlock); - challengesmenu.unlockanim = 0; - - if (gamedata->challengegrid == NULL || challengesmenu.extradata == NULL) - return; - - for (i = 0; i < (CHALLENGEGRIDHEIGHT * gamedata->challengegridwidth); i++) - { - if (gamedata->challengegrid[i] != unlockid) - { - // Not what we're looking for. - continue; - } - - if (challengesmenu.extradata[i] & CHE_CONNECTEDLEFT) - { - // no need to check for CHE_CONNECTEDUP in linear iteration - continue; - } - - // Helper calculation for non-fresh scrolling. - work = (challengesmenu.col + challengesmenu.focusx); - - challengesmenu.col = challengesmenu.hilix = i/CHALLENGEGRIDHEIGHT; - challengesmenu.row = challengesmenu.hiliy = i%CHALLENGEGRIDHEIGHT; - - if (fresh) - { - // We're just entering the menu. Immediately jump to the desired position... - challengesmenu.focusx = 0; - // ...and since the menu is even-width, randomly select whether it's left or right of center. - if (!unlockables[unlockid].majorunlock - && M_RandomChance(FRACUNIT/2)) - challengesmenu.focusx--; - } - else - { - // We're jumping between multiple unlocks in sequence. Get the difference (looped from -range/2 < work <= range/2). - work -= challengesmenu.col; - if (work <= -gamedata->challengegridwidth/2) - work += gamedata->challengegridwidth; - else if (work >= gamedata->challengegridwidth/2) - work -= gamedata->challengegridwidth; - - if (work > 0) - { - // We only need to scroll as far as the rightward edge. - if (unlockables[unlockid].majorunlock) - { - work--; - challengesmenu.col++; - if (challengesmenu.col >= gamedata->challengegridwidth) - challengesmenu.col = 0; - } - - // Offset right, scroll left? - if (work > LEFTUNLOCKSCROLL) - { - work -= LEFTUNLOCKSCROLL; - challengesmenu.focusx = LEFTUNLOCKSCROLL; - } - else - { - challengesmenu.focusx = work; - work = 0; - } - } - else if (work < 0) - { - // Offset left, scroll right? - if (work < -RIGHTUNLOCKSCROLL) - { - challengesmenu.focusx = -RIGHTUNLOCKSCROLL; - work += RIGHTUNLOCKSCROLL; - } - else - { - challengesmenu.focusx = work; - work = 0; - } - } - else - { - // We're right where we want to be. - challengesmenu.focusx = 0; - } - - // And put the pixel-based scrolling in play, too. - challengesmenu.offset = -work*16; - } - - break; - } -} - -void M_Challenges(INT32 choice) -{ - UINT8 i; - (void)choice; - - M_InterruptMenuWithChallenges(NULL); - MISC_ChallengesDef.prevMenu = currentMenu; - - if (gamedata->challengegrid != NULL && !challengesmenu.pending) - { - UINT8 selection[MAXUNLOCKABLES]; - UINT8 numunlocks = 0; - - // Get a random available unlockable. - for (i = 0; i < MAXUNLOCKABLES; i++) - { - if (!unlockables[i].conditionset) - { - continue; - } - - if (!gamedata->unlocked[i]) - { - continue; - } - - selection[numunlocks++] = i; - } - - if (!numunlocks) - { - // ...OK, get a random unlockable. - for (i = 0; i < MAXUNLOCKABLES; i++) - { - if (!unlockables[i].conditionset) - { - continue; - } - - selection[numunlocks++] = i; - } - } - - M_ChallengesAutoFocus(selection[M_RandomKey(numunlocks)], true); - } - - M_SetupNextMenu(&MISC_ChallengesDef, false); -} - -void M_ChallengesTick(void) -{ - const UINT8 pid = 0; - UINT8 i, newunlock = MAXUNLOCKABLES; - boolean fresh = (challengesmenu.currentunlock >= MAXUNLOCKABLES); - - // Ticking - challengesmenu.ticker++; - challengesmenu.offset /= 2; - for (i = 0; i < CSEXPLOSIONS; i++) - { - if (setup_explosions[i].tics > 0) - setup_explosions[i].tics--; - } - if (challengesmenu.unlockcount[CC_ANIM] > 0) - challengesmenu.unlockcount[CC_ANIM]--; - M_CupSelectTick(); - - if (challengesmenu.pending) - { - // Pending mode. - - if (challengesmenu.requestnew) - { - // The menu apparatus is requesting a new unlock. - challengesmenu.requestnew = false; - if ((newunlock = M_GetNextAchievedUnlock()) < MAXUNLOCKABLES) - { - // We got one! - M_ChallengesAutoFocus(newunlock, fresh); - } - else - { - // All done! Let's save the unlocks we've busted open. - challengesmenu.pending = false; - G_SaveGameData(); - } - } - else if (challengesmenu.fade < 5) - { - // Fade increase. - challengesmenu.fade++; - } - else - { - // Unlock sequence. - tic_t nexttime = M_MenuExtraHeld(pid) ? (UNLOCKTIME*2) : MAXUNLOCKTIME; - - if (++challengesmenu.unlockanim >= nexttime) - { - challengesmenu.requestnew = true; - } - - if (challengesmenu.currentunlock < MAXUNLOCKABLES - && challengesmenu.unlockanim == UNLOCKTIME) - { - // Unlock animation... also tied directly to the actual unlock! - gamedata->unlocked[challengesmenu.currentunlock] = true; - M_UpdateUnlockablesAndExtraEmblems(true); - - // Update shown description just in case..? - challengesmenu.unlockcondition = M_BuildConditionSetString(challengesmenu.currentunlock); - - challengesmenu.unlockcount[CC_TALLY]++; - challengesmenu.unlockcount[CC_ANIM]++; - - Z_Free(challengesmenu.extradata); - if ((challengesmenu.extradata = M_ChallengeGridExtraData())) - { - unlockable_t *ref = &unlockables[challengesmenu.currentunlock]; - UINT16 bombcolor = SKINCOLOR_NONE; - - if (ref->color != SKINCOLOR_NONE && ref->color < numskincolors) - { - bombcolor = ref->color; - } - else switch (ref->type) - { - case SECRET_SKIN: - { - INT32 skin = M_UnlockableSkinNum(ref); - if (skin != -1) - { - bombcolor = skins[skin].prefcolor; - } - break; - } - case SECRET_FOLLOWER: - { - INT32 skin = M_UnlockableFollowerNum(ref); - if (skin != -1) - { - bombcolor = K_GetEffectiveFollowerColor(followers[skin].defaultcolor, cv_playercolor[0].value); - } - break; - } - default: - break; - } - - if (bombcolor == SKINCOLOR_NONE) - { - bombcolor = cv_playercolor[0].value; - } - - i = (ref->majorunlock && M_RandomChance(FRACUNIT/2)) ? 1 : 0; - M_SetupReadyExplosions(false, challengesmenu.hilix, challengesmenu.hiliy+i, bombcolor); - if (ref->majorunlock) - { - M_SetupReadyExplosions(false, challengesmenu.hilix+1, challengesmenu.hiliy+(1-i), bombcolor); - } - - S_StartSound(NULL, sfx_s3k4e); - } - } - } - } - else - { - - // Tick down the tally. (currently not visible) - /*if ((challengesmenu.ticker & 1) - && challengesmenu.unlockcount[CC_TALLY] > 0) - { - challengesmenu.unlockcount[CC_TALLY]--; - challengesmenu.unlockcount[CC_UNLOCKED]++; - }*/ - - if (challengesmenu.fade > 0) - { - // Fade decrease. - challengesmenu.fade--; - } - } -} - -boolean M_ChallengesInputs(INT32 ch) -{ - const UINT8 pid = 0; - UINT8 i; - const boolean start = M_MenuButtonPressed(pid, MBT_START); - const boolean move = (menucmd[pid].dpad_ud != 0 || menucmd[pid].dpad_lr != 0); - (void) ch; - - if (challengesmenu.fade) - { - ; - } -#ifdef DEVELOP - else if (M_MenuExtraPressed(pid) && challengesmenu.extradata) // debugging - { - if (challengesmenu.currentunlock < MAXUNLOCKABLES) - { - Z_Free(gamedata->challengegrid); - gamedata->challengegrid = NULL; - gamedata->challengegridwidth = 0; - M_PopulateChallengeGrid(); - Z_Free(challengesmenu.extradata); - challengesmenu.extradata = M_ChallengeGridExtraData(); - - M_ChallengesAutoFocus(challengesmenu.currentunlock, true); - - challengesmenu.pending = true; - } - return true; - } -#endif - else - { - if (M_MenuBackPressed(pid) || start) - { - M_GoBack(0); - M_SetMenuDelay(pid); - - Z_Free(challengesmenu.extradata); - challengesmenu.extradata = NULL; - - challengesmenu.unlockcondition = NULL; - - return true; - } - - if (challengesmenu.extradata != NULL && move) - { - // Determine movement around the grid - // For right/down movement, we can pre-determine the number of steps based on extradata. - // For left/up movement, we can't - we have to be ready to iterate twice, and break early if we don't run into a large tile. - - if (menucmd[pid].dpad_ud > 0) - { - i = 2; - while (i > 0) - { - if (challengesmenu.row < CHALLENGEGRIDHEIGHT-1) - { - challengesmenu.row++; - } - else - { - challengesmenu.row = 0; - } - if (!(challengesmenu.extradata[ - (challengesmenu.col * CHALLENGEGRIDHEIGHT) - + challengesmenu.row] - & CHE_CONNECTEDUP)) - { - break; - } - i--; - } - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - else if (menucmd[pid].dpad_ud < 0) - { - i = (challengesmenu.extradata[ - (challengesmenu.col * CHALLENGEGRIDHEIGHT) - + challengesmenu.row] - & CHE_CONNECTEDUP) ? 2 : 1; - while (i > 0) - { - if (challengesmenu.row > 0) - { - challengesmenu.row--; - } - else - { - challengesmenu.row = CHALLENGEGRIDHEIGHT-1; - } - i--; - } - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - - if (menucmd[pid].dpad_lr > 0) - { - i = 2; - while (i > 0) - { - // Slide the focus counter to movement, if we can. - if (challengesmenu.focusx > -RIGHTUNLOCKSCROLL) - { - challengesmenu.focusx--; - } - - // Step the actual column right. - if (challengesmenu.col < gamedata->challengegridwidth-1) - { - challengesmenu.col++; - } - else - { - challengesmenu.col = 0; - } - - if (!(challengesmenu.extradata[ - (challengesmenu.col * CHALLENGEGRIDHEIGHT) - + challengesmenu.row] - & CHE_CONNECTEDLEFT)) - { - break; - } - - i--; - } - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - else if (menucmd[pid].dpad_lr < 0) - { - i = (challengesmenu.extradata[ - (challengesmenu.col * CHALLENGEGRIDHEIGHT) - + challengesmenu.row] - & CHE_CONNECTEDLEFT) ? 2 : 1; - while (i > 0) - { - // Slide the focus counter to movement, if we can. - if (challengesmenu.focusx < LEFTUNLOCKSCROLL) - { - challengesmenu.focusx++; - } - - // Step the actual column left. - if (challengesmenu.col > 0) - { - challengesmenu.col--; - } - else - { - challengesmenu.col = gamedata->challengegridwidth-1; - } - - i--; - } - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - - // After movement has been determined, figure out the current selection. - i = (challengesmenu.col * CHALLENGEGRIDHEIGHT) + challengesmenu.row; - challengesmenu.currentunlock = (gamedata->challengegrid[i]); - challengesmenu.unlockcondition = M_BuildConditionSetString(challengesmenu.currentunlock); - - challengesmenu.hilix = challengesmenu.col; - challengesmenu.hiliy = challengesmenu.row; - - if (challengesmenu.currentunlock < MAXUNLOCKABLES - && unlockables[challengesmenu.currentunlock].majorunlock) - { - // Adjust highlight coordinates up/to the left for large tiles. - - if (challengesmenu.hiliy > 0 && (challengesmenu.extradata[i] & CHE_CONNECTEDUP)) - { - challengesmenu.hiliy--; - } - - if ((challengesmenu.extradata[i] & CHE_CONNECTEDLEFT)) - { - if (challengesmenu.hilix > 0) - { - challengesmenu.hilix--; - } - else - { - challengesmenu.hilix = gamedata->challengegridwidth-1; - } - } - } - - return true; - } - - if (M_MenuConfirmPressed(pid) - && challengesmenu.currentunlock < MAXUNLOCKABLES - && gamedata->unlocked[challengesmenu.currentunlock]) - { - switch (unlockables[challengesmenu.currentunlock].type) - { - case SECRET_ALTTITLE: - CV_AddValue(&cv_alttitle, 1); - S_StartSound(NULL, sfx_s3kc3s); - M_SetMenuDelay(pid); - break; - default: - break; - } - - return true; - } - } - - return true; -} - -// Statistics menu - -struct statisticsmenu_s statisticsmenu; - -void M_Statistics(INT32 choice) -{ - UINT16 i = 0; - - (void)choice; - - statisticsmenu.maplist = Z_Malloc(sizeof(UINT16) * nummapheaders, PU_STATIC, NULL); - statisticsmenu.nummaps = 0; - - for (i = 0; i < nummapheaders; i++) - { - if (!mapheaderinfo[i]) - continue; - - // Check for no visibility + legacy box - if (mapheaderinfo[i]->menuflags & (LF2_NOTIMEATTACK|LF2_HIDEINSTATS|LF2_HIDEINMENU)) - continue; - - // Check for completion - if ((mapheaderinfo[i]->menuflags & LF2_FINISHNEEDED) - && !(mapheaderinfo[i]->mapvisited & MV_BEATEN)) - continue; - - // Check for unlock - if (M_MapLocked(i+1)) - continue; - - statisticsmenu.maplist[statisticsmenu.nummaps++] = i; - } - statisticsmenu.maplist[statisticsmenu.nummaps] = NEXTMAP_INVALID; - statisticsmenu.maxscroll = (statisticsmenu.nummaps + M_CountMedals(true, true) + 2) - 10; - statisticsmenu.location = 0; - - if (statisticsmenu.maxscroll < 0) - { - statisticsmenu.maxscroll = 0; - } - - MISC_StatisticsDef.prevMenu = currentMenu; - M_SetupNextMenu(&MISC_StatisticsDef, false); -} - -boolean M_StatisticsInputs(INT32 ch) -{ - const UINT8 pid = 0; - - (void)ch; - - if (M_MenuBackPressed(pid)) - { - M_GoBack(0); - M_SetMenuDelay(pid); - - Z_Free(statisticsmenu.maplist); - statisticsmenu.maplist = NULL; - - return true; - } - - if (M_MenuExtraPressed(pid)) - { - if (statisticsmenu.location > 0) - { - statisticsmenu.location = 0; - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - } - else if (menucmd[pid].dpad_ud > 0) - { - if (statisticsmenu.location < statisticsmenu.maxscroll) - { - statisticsmenu.location++; - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - } - else if (menucmd[pid].dpad_ud < 0) - { - if (statisticsmenu.location > 0) - { - statisticsmenu.location--; - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - } - } - - return true; -} diff --git a/src/menus/CMakeLists.txt b/src/menus/CMakeLists.txt index 43bc71147..cb350244d 100644 --- a/src/menus/CMakeLists.txt +++ b/src/menus/CMakeLists.txt @@ -3,6 +3,7 @@ target_sources(SRB2SDL2 PRIVATE extras-addons.c extras-challenges.c extras-replay-hut.c + extras-statistics.c main-1.c main-profile-select.c options-1.c @@ -35,6 +36,7 @@ target_sources(SRB2SDL2 PRIVATE play-online-1.c play-online-host.c play-online-join-ip.c + play-online-room-select.c play-online-server-browser.c ) diff --git a/src/menus/extras-1.c b/src/menus/extras-1.c index e6af1edf3..457ca348d 100644 --- a/src/menus/extras-1.c +++ b/src/menus/extras-1.c @@ -2,6 +2,7 @@ /// \brief Extras Menu #include "../k_menu.h" +#include "../s_sound.h" menuitem_t EXTRAS_Main[] = { @@ -35,3 +36,104 @@ menu_t EXTRAS_MainDef = { M_ExtrasInputs }; +// Extras menu; +// this is copypasted from the options menu but all of these are different functions in case we ever want it to look more unique + +struct extrasmenu_s extrasmenu; + +void M_InitExtras(INT32 choice) +{ + (void)choice; + + extrasmenu.ticker = 0; + extrasmenu.offset = 0; + + extrasmenu.extx = 0; + extrasmenu.exty = 0; + extrasmenu.textx = 0; + extrasmenu.texty = 0; + + M_SetupNextMenu(&EXTRAS_MainDef, false); +} + +// For statistics, will maybe remain unused for a while +boolean M_ExtrasQuit(void) +{ + extrasmenu.textx = 140-1; + extrasmenu.texty = 70+1; + + return true; // Always allow quitting, duh. +} + +void M_ExtrasTick(void) +{ + extrasmenu.offset /= 2; + extrasmenu.ticker++; + + extrasmenu.extx += (extrasmenu.textx - extrasmenu.extx)/2; + extrasmenu.exty += (extrasmenu.texty - extrasmenu.exty)/2; + + if (abs(extrasmenu.extx - extrasmenu.exty) < 2) + { + extrasmenu.extx = extrasmenu.textx; + extrasmenu.exty = extrasmenu.texty; // Avoid awkward 1 px errors. + } + + // Move the button for cool animations + if (currentMenu == &EXTRAS_MainDef) + { + M_ExtrasQuit(); // reset the options button. + } + else + { + extrasmenu.textx = 160; + extrasmenu.texty = 50; + } +} + +boolean M_ExtrasInputs(INT32 ch) +{ + + const UINT8 pid = 0; + (void) ch; + + if (menucmd[pid].dpad_ud > 0) + { + extrasmenu.offset += 48; + M_NextOpt(); + S_StartSound(NULL, sfx_s3k5b); + + if (itemOn == 0) + extrasmenu.offset -= currentMenu->numitems*48; + + M_SetMenuDelay(pid); + return true; + } + + else if (menucmd[pid].dpad_ud < 0) + { + extrasmenu.offset -= 48; + M_PrevOpt(); + S_StartSound(NULL, sfx_s3k5b); + + if (itemOn == currentMenu->numitems-1) + extrasmenu.offset += currentMenu->numitems*48; + + M_SetMenuDelay(pid); + return true; + } + + else if (M_MenuConfirmPressed(pid)) + { + + if (currentMenu->menuitems[itemOn].status & IT_TRANSTEXT) + return true; // No. + + extrasmenu.extx = 140; + extrasmenu.exty = 70; // Default position for the currently selected option. + + M_SetMenuDelay(pid); + return false; // Don't eat. + } + return false; +} diff --git a/src/menus/extras-addons.c b/src/menus/extras-addons.c index b010861d3..e980d131d 100644 --- a/src/menus/extras-addons.c +++ b/src/menus/extras-addons.c @@ -2,6 +2,11 @@ /// \brief Addons menu! #include "../k_menu.h" +#include "../filesrch.h" // Addfile +#include "../d_main.h" +#include "../z_zone.h" +#include "../s_sound.h" +#include "../v_video.h" menuitem_t MISC_AddonsMenu[] = { @@ -25,3 +30,330 @@ menu_t MISC_AddonsDef = { NULL, NULL }; + +// Addons menu: (Merely copypasted, original code by toaster) + +static void M_UpdateAddonsSearch(void); +consvar_t cv_dummyaddonsearch = CVAR_INIT ("dummyaddonsearch", "", CV_HIDDEN|CV_CALL|CV_NOINIT, NULL, M_UpdateAddonsSearch); + +void M_Addons(INT32 choice) +{ + const char *pathname = "."; + + (void)choice; + +#if 1 + if (cv_addons_option.value == 0) + pathname = addonsdir; + else if (cv_addons_option.value == 1) + pathname = srb2home; + else if (cv_addons_option.value == 2) + pathname = srb2path; + else +#endif + if (cv_addons_option.value == 3 && *cv_addons_folder.string != '\0') + pathname = cv_addons_folder.string; + + strlcpy(menupath, pathname, 1024); + menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath) + 1; + + if (menupath[menupathindex[menudepthleft]-2] != PATHSEP[0]) + { + menupath[menupathindex[menudepthleft]-1] = PATHSEP[0]; + menupath[menupathindex[menudepthleft]] = 0; + } + else + --menupathindex[menudepthleft]; + + if (!preparefilemenu(false, false)) + { + M_StartMessage(va("No files/folders found.\n\n%s\n\nPress (B)\n", LOCATIONSTRING1),NULL,MM_NOTHING); + return; + } + else + dir_on[menudepthleft] = 0; + + MISC_AddonsDef.lastOn = 0; // Always start on search + + MISC_AddonsDef.prevMenu = currentMenu; + M_SetupNextMenu(&MISC_AddonsDef, false); +} + + +char *M_AddonsHeaderPath(void) +{ + UINT32 len; + static char header[1024]; + + strlcpy(header, va("%s folder%s", cv_addons_option.string, menupath+menupathindex[menudepth-1]-1), 1024); + len = strlen(header); + if (len > 34) + { + len = len-34; + header[len] = header[len+1] = header[len+2] = '.'; + } + else + len = 0; + + return header+len; +} + +#define UNEXIST S_StartSound(NULL, sfx_s26d);\ + M_SetupNextMenu(MISC_AddonsDef.prevMenu, false);\ + M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\nPress (B)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING) + +#define CLEARNAME Z_Free(refreshdirname);\ + refreshdirname = NULL + +static boolean prevmajormods = false; + +static void M_AddonsClearName(INT32 choice) +{ + if (!majormods || prevmajormods) + { + CLEARNAME; + } + M_StopMessage(choice); +} + +// Handles messages for addon errors. +void M_AddonsRefresh(void) +{ + if ((refreshdirmenu & REFRESHDIR_NORMAL) && !preparefilemenu(true, false)) + { + UNEXIST; + if (refreshdirname) + { + CLEARNAME; + } + return;// true; + } + +#ifdef DEVELOP + prevmajormods = majormods; +#else + if (!majormods && prevmajormods) + prevmajormods = false; +#endif + + if ((refreshdirmenu & REFRESHDIR_ADDFILE) || (majormods && !prevmajormods)) + { + char *message = NULL; + + if (refreshdirmenu & REFRESHDIR_NOTLOADED) + { + S_StartSound(NULL, sfx_s26d); + if (refreshdirmenu & REFRESHDIR_MAX) + message = va("%c%s\x80\nMaximum number of addons reached.\nA file could not be loaded.\nIf you wish to play with this addon, restart the game to clear existing ones.\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); + else + message = va("%c%s\x80\nA file was not loaded.\nCheck the console log for more info.\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); + } + else if (refreshdirmenu & (REFRESHDIR_WARNING|REFRESHDIR_ERROR)) + { + S_StartSound(NULL, sfx_s224); + message = va("%c%s\x80\nA file was loaded with %s.\nCheck the console log for more info.\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname, ((refreshdirmenu & REFRESHDIR_ERROR) ? "errors" : "warnings")); + } + else if (majormods && !prevmajormods) + { + S_StartSound(NULL, sfx_s221); + message = va("%c%s\x80\nYou've loaded a gameplay-modifying addon.\n\nRecord Attack has been disabled, but you\ncan still play alone in local Multiplayer.\n\nIf you wish to play Record Attack mode, restart the game to disable loaded addons.\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); + prevmajormods = majormods; + } + + if (message) + { + M_StartMessage(message,FUNCPTRCAST(M_AddonsClearName),MM_YESNO); + return;// true; + } + + S_StartSound(NULL, sfx_s221); + CLEARNAME; + } + + return;// false; +} + +static void M_AddonExec(INT32 ch) +{ + if (ch == MA_YES) + { + S_StartSound(NULL, sfx_zoom); + COM_BufAddText(va("exec \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); + } +} + +static void M_UpdateAddonsSearch(void) +{ + menusearch[0] = strlen(cv_dummyaddonsearch.string); + strlcpy(menusearch+1, cv_dummyaddonsearch.string, MAXSTRINGLENGTH); + if (!cv_addons_search_case.value) + strupr(menusearch+1); + +#if 0 // much slower + if (!preparefilemenu(true, false)) + { + UNEXIST; + return; + } +#else // streamlined + searchfilemenu(NULL); +#endif +} + +void M_HandleAddons(INT32 choice) +{ + const UINT8 pid = 0; + boolean exitmenu = false; // exit to previous menu + + (void) choice; + + if (menucmd[pid].dpad_ud > 0) + { + if (dir_on[menudepthleft] < sizedirmenu-1) + { + dir_on[menudepthleft]++; + S_StartSound(NULL, sfx_s3k5b); + } + else if (M_NextOpt()) + { + S_StartSound(NULL, sfx_s3k5b); + } + M_SetMenuDelay(pid); + } + else if (menucmd[pid].dpad_ud < 0) + { + if (dir_on[menudepthleft]) + { + dir_on[menudepthleft]--; + S_StartSound(NULL, sfx_s3k5b); + } + else if (M_PrevOpt()) + { + S_StartSound(NULL, sfx_s3k5b); + } + M_SetMenuDelay(pid); + } + + else if (M_MenuButtonPressed(pid, MBT_L)) + { + UINT8 i; + for (i = numaddonsshown; i && (dir_on[menudepthleft] < sizedirmenu-1); i--) + dir_on[menudepthleft]++; + + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + + else if (M_MenuButtonPressed(pid, MBT_R)) + { + UINT8 i; + for (i = numaddonsshown; i && (dir_on[menudepthleft]); i--) + dir_on[menudepthleft]--; + + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + + else if (M_MenuConfirmPressed(pid)) + { + boolean refresh = true; + M_SetMenuDelay(pid); + + if (!dirmenu[dir_on[menudepthleft]]) + S_StartSound(NULL, sfx_s26d); + else + { + switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE]) + { + case EXT_FOLDER: + strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING); + if (menudepthleft) + { + menupathindex[--menudepthleft] = strlen(menupath); + menupath[menupathindex[menudepthleft]] = 0; + + if (!preparefilemenu(false, false)) + { + S_StartSound(NULL, sfx_s224); + M_StartMessage(va("%c%s\x80\nThis folder is empty.\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); + menupath[menupathindex[++menudepthleft]] = 0; + + if (!preparefilemenu(true, false)) + { + UNEXIST; + return; + } + } + else + { + S_StartSound(NULL, sfx_s3k5b); + dir_on[menudepthleft] = 1; + } + refresh = false; + } + else + { + S_StartSound(NULL, sfx_s26d); + M_StartMessage(va("%c%s\x80\nThis folder is too deep to navigate to!\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); + menupath[menupathindex[menudepthleft]] = 0; + } + break; + + case EXT_UP: + S_StartSound(NULL, sfx_s3k5b); + menupath[menupathindex[++menudepthleft]] = 0; + if (!preparefilemenu(false, false)) + { + UNEXIST; + return; + } + break; + + case EXT_TXT: + M_StartMessage(va("%c%s\x80\nThis file may not be a console script.\nAttempt to run anyways? \n\nPress (A) to confirm or (B) to cancel\n\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),FUNCPTRCAST(M_AddonExec),MM_YESNO); + break; + + case EXT_CFG: + M_StartMessage(va("%c%s\x80\nThis file may modify your settings.\nAttempt to run anyways? \n\nPress (A) to confirm or (B) to cancel\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),FUNCPTRCAST(M_AddonExec),MM_YESNO); + break; + + case EXT_LUA: + case EXT_SOC: + case EXT_WAD: +#ifdef USE_KART + case EXT_KART: +#endif + case EXT_PK3: + COM_BufAddText(va("addfile \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); + break; + + default: + S_StartSound(NULL, sfx_s26d); + } + + if (refresh) + refreshdirmenu |= REFRESHDIR_NORMAL; + } + } + else if (M_MenuBackPressed(pid)) + { + exitmenu = true; + M_SetMenuDelay(pid); + } + + + if (exitmenu) + { + closefilemenu(true); + + // Secret menu! + //MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + + if (currentMenu->prevMenu) + M_SetupNextMenu(currentMenu->prevMenu, false); + else + M_ClearMenus(true); + + M_SetMenuDelay(pid); + } +} diff --git a/src/menus/extras-challenges.c b/src/menus/extras-challenges.c index 15c955d0e..ca4c1268e 100644 --- a/src/menus/extras-challenges.c +++ b/src/menus/extras-challenges.c @@ -2,6 +2,11 @@ /// \brief Challenges. #include "../k_menu.h" +#include "../m_cond.h" // Condition Sets +#include "../m_random.h" // And just some randomness for the exits. +#include "../z_zone.h" +#include "../r_skins.h" +#include "../s_sound.h" menuitem_t MISC_ChallengesStatsDummyMenu[] = { @@ -23,6 +28,8 @@ menu_t MISC_ChallengesDef = { M_ChallengesInputs, }; +// This must be defined here so it can take sizeof +// MISC_ChallengesStatsDummyMenu :V menu_t MISC_StatisticsDef = { sizeof (MISC_ChallengesStatsDummyMenu)/sizeof (menuitem_t), &MainDef, @@ -37,3 +44,558 @@ menu_t MISC_StatisticsDef = { NULL, M_StatisticsInputs, }; + +struct challengesmenu_s challengesmenu; + +menu_t *M_InterruptMenuWithChallenges(menu_t *desiredmenu) +{ + UINT8 i; + + M_UpdateUnlockablesAndExtraEmblems(false); + + if ((challengesmenu.pending = challengesmenu.requestnew = (M_GetNextAchievedUnlock() < MAXUNLOCKABLES))) + { + MISC_ChallengesDef.prevMenu = desiredmenu; + } + + if (challengesmenu.pending || desiredmenu == NULL) + { + challengesmenu.currentunlock = MAXUNLOCKABLES; + challengesmenu.unlockcondition = NULL; + + M_PopulateChallengeGrid(); + if (gamedata->challengegrid) + challengesmenu.extradata = M_ChallengeGridExtraData(); + + memset(setup_explosions, 0, sizeof(setup_explosions)); + memset(&challengesmenu.unlockcount, 0, sizeof(challengesmenu.unlockcount)); + for (i = 0; i < MAXUNLOCKABLES; i++) + { + if (!unlockables[i].conditionset) + { + continue; + } + + challengesmenu.unlockcount[CC_TOTAL]++; + + if (!gamedata->unlocked[i]) + { + continue; + } + + challengesmenu.unlockcount[CC_UNLOCKED]++; + } + + return &MISC_ChallengesDef; + } + + return desiredmenu; +} + +static void M_ChallengesAutoFocus(UINT8 unlockid, boolean fresh) +{ + UINT8 i; + SINT8 work; + + if (unlockid >= MAXUNLOCKABLES) + return; + + challengesmenu.currentunlock = unlockid; + challengesmenu.unlockcondition = M_BuildConditionSetString(challengesmenu.currentunlock); + challengesmenu.unlockanim = 0; + + if (gamedata->challengegrid == NULL || challengesmenu.extradata == NULL) + return; + + for (i = 0; i < (CHALLENGEGRIDHEIGHT * gamedata->challengegridwidth); i++) + { + if (gamedata->challengegrid[i] != unlockid) + { + // Not what we're looking for. + continue; + } + + if (challengesmenu.extradata[i] & CHE_CONNECTEDLEFT) + { + // no need to check for CHE_CONNECTEDUP in linear iteration + continue; + } + + // Helper calculation for non-fresh scrolling. + work = (challengesmenu.col + challengesmenu.focusx); + + challengesmenu.col = challengesmenu.hilix = i/CHALLENGEGRIDHEIGHT; + challengesmenu.row = challengesmenu.hiliy = i%CHALLENGEGRIDHEIGHT; + + if (fresh) + { + // We're just entering the menu. Immediately jump to the desired position... + challengesmenu.focusx = 0; + // ...and since the menu is even-width, randomly select whether it's left or right of center. + if (!unlockables[unlockid].majorunlock + && M_RandomChance(FRACUNIT/2)) + challengesmenu.focusx--; + } + else + { + // We're jumping between multiple unlocks in sequence. Get the difference (looped from -range/2 < work <= range/2). + work -= challengesmenu.col; + if (work <= -gamedata->challengegridwidth/2) + work += gamedata->challengegridwidth; + else if (work >= gamedata->challengegridwidth/2) + work -= gamedata->challengegridwidth; + + if (work > 0) + { + // We only need to scroll as far as the rightward edge. + if (unlockables[unlockid].majorunlock) + { + work--; + challengesmenu.col++; + if (challengesmenu.col >= gamedata->challengegridwidth) + challengesmenu.col = 0; + } + + // Offset right, scroll left? + if (work > LEFTUNLOCKSCROLL) + { + work -= LEFTUNLOCKSCROLL; + challengesmenu.focusx = LEFTUNLOCKSCROLL; + } + else + { + challengesmenu.focusx = work; + work = 0; + } + } + else if (work < 0) + { + // Offset left, scroll right? + if (work < -RIGHTUNLOCKSCROLL) + { + challengesmenu.focusx = -RIGHTUNLOCKSCROLL; + work += RIGHTUNLOCKSCROLL; + } + else + { + challengesmenu.focusx = work; + work = 0; + } + } + else + { + // We're right where we want to be. + challengesmenu.focusx = 0; + } + + // And put the pixel-based scrolling in play, too. + challengesmenu.offset = -work*16; + } + + break; + } +} + +void M_Challenges(INT32 choice) +{ + UINT8 i; + (void)choice; + + M_InterruptMenuWithChallenges(NULL); + MISC_ChallengesDef.prevMenu = currentMenu; + + if (gamedata->challengegrid != NULL && !challengesmenu.pending) + { + UINT8 selection[MAXUNLOCKABLES]; + UINT8 numunlocks = 0; + + // Get a random available unlockable. + for (i = 0; i < MAXUNLOCKABLES; i++) + { + if (!unlockables[i].conditionset) + { + continue; + } + + if (!gamedata->unlocked[i]) + { + continue; + } + + selection[numunlocks++] = i; + } + + if (!numunlocks) + { + // ...OK, get a random unlockable. + for (i = 0; i < MAXUNLOCKABLES; i++) + { + if (!unlockables[i].conditionset) + { + continue; + } + + selection[numunlocks++] = i; + } + } + + M_ChallengesAutoFocus(selection[M_RandomKey(numunlocks)], true); + } + + M_SetupNextMenu(&MISC_ChallengesDef, false); +} + +void M_ChallengesTick(void) +{ + const UINT8 pid = 0; + UINT8 i, newunlock = MAXUNLOCKABLES; + boolean fresh = (challengesmenu.currentunlock >= MAXUNLOCKABLES); + + // Ticking + challengesmenu.ticker++; + challengesmenu.offset /= 2; + for (i = 0; i < CSEXPLOSIONS; i++) + { + if (setup_explosions[i].tics > 0) + setup_explosions[i].tics--; + } + if (challengesmenu.unlockcount[CC_ANIM] > 0) + challengesmenu.unlockcount[CC_ANIM]--; + M_CupSelectTick(); + + if (challengesmenu.pending) + { + // Pending mode. + + if (challengesmenu.requestnew) + { + // The menu apparatus is requesting a new unlock. + challengesmenu.requestnew = false; + if ((newunlock = M_GetNextAchievedUnlock()) < MAXUNLOCKABLES) + { + // We got one! + M_ChallengesAutoFocus(newunlock, fresh); + } + else + { + // All done! Let's save the unlocks we've busted open. + challengesmenu.pending = false; + G_SaveGameData(); + } + } + else if (challengesmenu.fade < 5) + { + // Fade increase. + challengesmenu.fade++; + } + else + { + // Unlock sequence. + tic_t nexttime = M_MenuExtraHeld(pid) ? (UNLOCKTIME*2) : MAXUNLOCKTIME; + + if (++challengesmenu.unlockanim >= nexttime) + { + challengesmenu.requestnew = true; + } + + if (challengesmenu.currentunlock < MAXUNLOCKABLES + && challengesmenu.unlockanim == UNLOCKTIME) + { + // Unlock animation... also tied directly to the actual unlock! + gamedata->unlocked[challengesmenu.currentunlock] = true; + M_UpdateUnlockablesAndExtraEmblems(true); + + // Update shown description just in case..? + challengesmenu.unlockcondition = M_BuildConditionSetString(challengesmenu.currentunlock); + + challengesmenu.unlockcount[CC_TALLY]++; + challengesmenu.unlockcount[CC_ANIM]++; + + Z_Free(challengesmenu.extradata); + if ((challengesmenu.extradata = M_ChallengeGridExtraData())) + { + unlockable_t *ref = &unlockables[challengesmenu.currentunlock]; + UINT16 bombcolor = SKINCOLOR_NONE; + + if (ref->color != SKINCOLOR_NONE && ref->color < numskincolors) + { + bombcolor = ref->color; + } + else switch (ref->type) + { + case SECRET_SKIN: + { + INT32 skin = M_UnlockableSkinNum(ref); + if (skin != -1) + { + bombcolor = skins[skin].prefcolor; + } + break; + } + case SECRET_FOLLOWER: + { + INT32 skin = M_UnlockableFollowerNum(ref); + if (skin != -1) + { + bombcolor = K_GetEffectiveFollowerColor(followers[skin].defaultcolor, cv_playercolor[0].value); + } + break; + } + default: + break; + } + + if (bombcolor == SKINCOLOR_NONE) + { + bombcolor = cv_playercolor[0].value; + } + + i = (ref->majorunlock && M_RandomChance(FRACUNIT/2)) ? 1 : 0; + M_SetupReadyExplosions(false, challengesmenu.hilix, challengesmenu.hiliy+i, bombcolor); + if (ref->majorunlock) + { + M_SetupReadyExplosions(false, challengesmenu.hilix+1, challengesmenu.hiliy+(1-i), bombcolor); + } + + S_StartSound(NULL, sfx_s3k4e); + } + } + } + } + else + { + + // Tick down the tally. (currently not visible) + /*if ((challengesmenu.ticker & 1) + && challengesmenu.unlockcount[CC_TALLY] > 0) + { + challengesmenu.unlockcount[CC_TALLY]--; + challengesmenu.unlockcount[CC_UNLOCKED]++; + }*/ + + if (challengesmenu.fade > 0) + { + // Fade decrease. + challengesmenu.fade--; + } + } +} + +boolean M_ChallengesInputs(INT32 ch) +{ + const UINT8 pid = 0; + UINT8 i; + const boolean start = M_MenuButtonPressed(pid, MBT_START); + const boolean move = (menucmd[pid].dpad_ud != 0 || menucmd[pid].dpad_lr != 0); + (void) ch; + + if (challengesmenu.fade) + { + ; + } +#ifdef DEVELOP + else if (M_MenuExtraPressed(pid) && challengesmenu.extradata) // debugging + { + if (challengesmenu.currentunlock < MAXUNLOCKABLES) + { + Z_Free(gamedata->challengegrid); + gamedata->challengegrid = NULL; + gamedata->challengegridwidth = 0; + M_PopulateChallengeGrid(); + Z_Free(challengesmenu.extradata); + challengesmenu.extradata = M_ChallengeGridExtraData(); + + M_ChallengesAutoFocus(challengesmenu.currentunlock, true); + + challengesmenu.pending = true; + } + return true; + } +#endif + else + { + if (M_MenuBackPressed(pid) || start) + { + M_GoBack(0); + M_SetMenuDelay(pid); + + Z_Free(challengesmenu.extradata); + challengesmenu.extradata = NULL; + + challengesmenu.unlockcondition = NULL; + + return true; + } + + if (challengesmenu.extradata != NULL && move) + { + // Determine movement around the grid + // For right/down movement, we can pre-determine the number of steps based on extradata. + // For left/up movement, we can't - we have to be ready to iterate twice, and break early if we don't run into a large tile. + + if (menucmd[pid].dpad_ud > 0) + { + i = 2; + while (i > 0) + { + if (challengesmenu.row < CHALLENGEGRIDHEIGHT-1) + { + challengesmenu.row++; + } + else + { + challengesmenu.row = 0; + } + if (!(challengesmenu.extradata[ + (challengesmenu.col * CHALLENGEGRIDHEIGHT) + + challengesmenu.row] + & CHE_CONNECTEDUP)) + { + break; + } + i--; + } + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + else if (menucmd[pid].dpad_ud < 0) + { + i = (challengesmenu.extradata[ + (challengesmenu.col * CHALLENGEGRIDHEIGHT) + + challengesmenu.row] + & CHE_CONNECTEDUP) ? 2 : 1; + while (i > 0) + { + if (challengesmenu.row > 0) + { + challengesmenu.row--; + } + else + { + challengesmenu.row = CHALLENGEGRIDHEIGHT-1; + } + i--; + } + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + + if (menucmd[pid].dpad_lr > 0) + { + i = 2; + while (i > 0) + { + // Slide the focus counter to movement, if we can. + if (challengesmenu.focusx > -RIGHTUNLOCKSCROLL) + { + challengesmenu.focusx--; + } + + // Step the actual column right. + if (challengesmenu.col < gamedata->challengegridwidth-1) + { + challengesmenu.col++; + } + else + { + challengesmenu.col = 0; + } + + if (!(challengesmenu.extradata[ + (challengesmenu.col * CHALLENGEGRIDHEIGHT) + + challengesmenu.row] + & CHE_CONNECTEDLEFT)) + { + break; + } + + i--; + } + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + else if (menucmd[pid].dpad_lr < 0) + { + i = (challengesmenu.extradata[ + (challengesmenu.col * CHALLENGEGRIDHEIGHT) + + challengesmenu.row] + & CHE_CONNECTEDLEFT) ? 2 : 1; + while (i > 0) + { + // Slide the focus counter to movement, if we can. + if (challengesmenu.focusx < LEFTUNLOCKSCROLL) + { + challengesmenu.focusx++; + } + + // Step the actual column left. + if (challengesmenu.col > 0) + { + challengesmenu.col--; + } + else + { + challengesmenu.col = gamedata->challengegridwidth-1; + } + + i--; + } + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + + // After movement has been determined, figure out the current selection. + i = (challengesmenu.col * CHALLENGEGRIDHEIGHT) + challengesmenu.row; + challengesmenu.currentunlock = (gamedata->challengegrid[i]); + challengesmenu.unlockcondition = M_BuildConditionSetString(challengesmenu.currentunlock); + + challengesmenu.hilix = challengesmenu.col; + challengesmenu.hiliy = challengesmenu.row; + + if (challengesmenu.currentunlock < MAXUNLOCKABLES + && unlockables[challengesmenu.currentunlock].majorunlock) + { + // Adjust highlight coordinates up/to the left for large tiles. + + if (challengesmenu.hiliy > 0 && (challengesmenu.extradata[i] & CHE_CONNECTEDUP)) + { + challengesmenu.hiliy--; + } + + if ((challengesmenu.extradata[i] & CHE_CONNECTEDLEFT)) + { + if (challengesmenu.hilix > 0) + { + challengesmenu.hilix--; + } + else + { + challengesmenu.hilix = gamedata->challengegridwidth-1; + } + } + } + + return true; + } + + if (M_MenuConfirmPressed(pid) + && challengesmenu.currentunlock < MAXUNLOCKABLES + && gamedata->unlocked[challengesmenu.currentunlock]) + { + switch (unlockables[challengesmenu.currentunlock].type) + { + case SECRET_ALTTITLE: + CV_AddValue(&cv_alttitle, 1); + S_StartSound(NULL, sfx_s3kc3s); + M_SetMenuDelay(pid); + break; + default: + break; + } + + return true; + } + } + + return true; +} diff --git a/src/menus/extras-replay-hut.c b/src/menus/extras-replay-hut.c index 3ba3f7e20..db9e3b0dd 100644 --- a/src/menus/extras-replay-hut.c +++ b/src/menus/extras-replay-hut.c @@ -2,6 +2,11 @@ /// \brief Extras Menu: Replay Hut #include "../k_menu.h" +#include "../filesrch.h" // Addfile +#include "../d_main.h" +#include "../s_sound.h" +#include "../v_video.h" +#include "../z_zone.h" // extras menu: replay hut menuitem_t EXTRAS_ReplayHut[] = @@ -60,3 +65,228 @@ menu_t EXTRAS_ReplayStartDef = NULL, NULL }; + +void M_PrepReplayList(void) +{ + size_t i; + + if (extrasmenu.demolist) + Z_Free(extrasmenu.demolist); + + extrasmenu.demolist = Z_Calloc(sizeof(menudemo_t) * sizedirmenu, PU_STATIC, NULL); + + for (i = 0; i < sizedirmenu; i++) + { + if (dirmenu[i][DIR_TYPE] == EXT_UP) + { + extrasmenu.demolist[i].type = MD_SUBDIR; + sprintf(extrasmenu.demolist[i].title, "UP"); + } + else if (dirmenu[i][DIR_TYPE] == EXT_FOLDER) + { + extrasmenu.demolist[i].type = MD_SUBDIR; + strncpy(extrasmenu.demolist[i].title, dirmenu[i] + DIR_STRING, 64); + } + else + { + extrasmenu.demolist[i].type = MD_NOTLOADED; + snprintf(extrasmenu.demolist[i].filepath, sizeof extrasmenu.demolist[i].filepath, + // 255 = UINT8 limit. dirmenu entries are restricted to this length (see DIR_LEN). + "%s%.255s", menupath, dirmenu[i] + DIR_STRING); + sprintf(extrasmenu.demolist[i].title, "....."); + } + } +} + +void M_ReplayHut(INT32 choice) +{ + (void)choice; + + extrasmenu.replayScrollTitle = 0; + extrasmenu.replayScrollDelay = TICRATE; + extrasmenu.replayScrollDir = 1; + + if (!demo.inreplayhut) + { + snprintf(menupath, 1024, "%s"PATHSEP"media"PATHSEP"replay"PATHSEP"online"PATHSEP, srb2home); + menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath); + } + if (!preparefilemenu(false, true)) + { + M_StartMessage("No replays found.\n\nPress (B)\n", NULL, MM_NOTHING); + return; + } + else if (!demo.inreplayhut) + dir_on[menudepthleft] = 0; + demo.inreplayhut = true; + + extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; + + M_PrepReplayList(); + + menuactive = true; + M_SetupNextMenu(&EXTRAS_ReplayHutDef, false); + //G_SetGamestate(GS_TIMEATTACK); + //titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please + + demo.rewinding = false; + CL_ClearRewinds(); + + //S_ChangeMusicInternal("replst", true); +} + +// key handler +void M_HandleReplayHutList(INT32 choice) +{ + + const UINT8 pid = 0; + (void) choice; + + if (menucmd[pid].dpad_ud < 0) + { + if (dir_on[menudepthleft]) + dir_on[menudepthleft]--; + else + return; + //M_PrevOpt(); + + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; + } + + else if (menucmd[pid].dpad_ud > 0) + { + if (dir_on[menudepthleft] < sizedirmenu-1) + dir_on[menudepthleft]++; + else + return; + //itemOn = 0; // Not M_NextOpt because that would take us to the extra dummy item + + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; + } + + else if (M_MenuBackPressed(pid)) + { + M_SetMenuDelay(pid); + M_QuitReplayHut(); + } + + else if (M_MenuConfirmPressed(pid)) + { + M_SetMenuDelay(pid); + switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE]) + { + case EXT_FOLDER: + strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING); + if (menudepthleft) + { + menupathindex[--menudepthleft] = strlen(menupath); + menupath[menupathindex[menudepthleft]] = 0; + + if (!preparefilemenu(false, true)) + { + S_StartSound(NULL, sfx_s224); + M_StartMessage(va("%c%s\x80\nThis folder is empty.\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); + menupath[menupathindex[++menudepthleft]] = 0; + + if (!preparefilemenu(true, true)) + { + M_QuitReplayHut(); + return; + } + } + else + { + S_StartSound(NULL, sfx_s3k5b); + dir_on[menudepthleft] = 1; + M_PrepReplayList(); + } + } + else + { + S_StartSound(NULL, sfx_s26d); + M_StartMessage(va("%c%s\x80\nThis folder is too deep to navigate to!\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); + menupath[menupathindex[menudepthleft]] = 0; + } + break; + case EXT_UP: + S_StartSound(NULL, sfx_s3k5b); + menupath[menupathindex[++menudepthleft]] = 0; + if (!preparefilemenu(false, true)) + { + M_QuitReplayHut(); + return; + } + M_PrepReplayList(); + break; + default: + // We can't just use M_SetupNextMenu because that'll run ReplayDef's quitroutine and boot us back to the title screen! + currentMenu->lastOn = itemOn; + currentMenu = &EXTRAS_ReplayStartDef; + + extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; + + switch (extrasmenu.demolist[dir_on[menudepthleft]].addonstatus) + { + case DFILE_ERROR_CANNOTLOAD: + // Only show "Watch Replay Without Addons" + EXTRAS_ReplayStart[0].status = IT_DISABLED; + EXTRAS_ReplayStart[1].status = IT_CALL|IT_STRING; + //EXTRAS_ReplayStart[1].alphaKey = 0; + EXTRAS_ReplayStart[2].status = IT_DISABLED; + itemOn = 1; + break; + + case DFILE_ERROR_NOTLOADED: + case DFILE_ERROR_INCOMPLETEOUTOFORDER: + // Show "Load Addons and Watch Replay" and "Watch Replay Without Addons" + EXTRAS_ReplayStart[0].status = IT_CALL|IT_STRING; + EXTRAS_ReplayStart[1].status = IT_CALL|IT_STRING; + //EXTRAS_ReplayStart[1].alphaKey = 10; + EXTRAS_ReplayStart[2].status = IT_DISABLED; + itemOn = 0; + break; + + case DFILE_ERROR_EXTRAFILES: + case DFILE_ERROR_OUTOFORDER: + default: + // Show "Watch Replay" + EXTRAS_ReplayStart[0].status = IT_DISABLED; + EXTRAS_ReplayStart[1].status = IT_DISABLED; + EXTRAS_ReplayStart[2].status = IT_CALL|IT_STRING; + //EXTRAS_ReplayStart[2].alphaKey = 0; + itemOn = 2; + break; + } + } + } +} + +boolean M_QuitReplayHut(void) +{ + // D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate. + menuactive = false; + D_StartTitle(); + + if (extrasmenu.demolist) + Z_Free(extrasmenu.demolist); + extrasmenu.demolist = NULL; + + demo.inreplayhut = false; + + return true; +} + +void M_HutStartReplay(INT32 choice) +{ + (void)choice; + + M_ClearMenus(false); + demo.loadfiles = (itemOn == 0); + demo.ignorefiles = (itemOn != 0); + + G_DoPlayDemo(extrasmenu.demolist[dir_on[menudepthleft]].filepath); +} diff --git a/src/menus/extras-statistics.c b/src/menus/extras-statistics.c new file mode 100644 index 000000000..97f4b3192 --- /dev/null +++ b/src/menus/extras-statistics.c @@ -0,0 +1,99 @@ +/// \file menus/extras-challenges.c +/// \brief Statistics menu + +#include "../k_menu.h" +#include "../z_zone.h" +#include "../m_cond.h" // Condition Sets +#include "../s_sound.h" + +struct statisticsmenu_s statisticsmenu; + +void M_Statistics(INT32 choice) +{ + UINT16 i = 0; + + (void)choice; + + statisticsmenu.maplist = Z_Malloc(sizeof(UINT16) * nummapheaders, PU_STATIC, NULL); + statisticsmenu.nummaps = 0; + + for (i = 0; i < nummapheaders; i++) + { + if (!mapheaderinfo[i]) + continue; + + // Check for no visibility + legacy box + if (mapheaderinfo[i]->menuflags & (LF2_NOTIMEATTACK|LF2_HIDEINSTATS|LF2_HIDEINMENU)) + continue; + + // Check for completion + if ((mapheaderinfo[i]->menuflags & LF2_FINISHNEEDED) + && !(mapheaderinfo[i]->mapvisited & MV_BEATEN)) + continue; + + // Check for unlock + if (M_MapLocked(i+1)) + continue; + + statisticsmenu.maplist[statisticsmenu.nummaps++] = i; + } + statisticsmenu.maplist[statisticsmenu.nummaps] = NEXTMAP_INVALID; + statisticsmenu.maxscroll = (statisticsmenu.nummaps + M_CountMedals(true, true) + 2) - 10; + statisticsmenu.location = 0; + + if (statisticsmenu.maxscroll < 0) + { + statisticsmenu.maxscroll = 0; + } + + MISC_StatisticsDef.prevMenu = currentMenu; + M_SetupNextMenu(&MISC_StatisticsDef, false); +} + +boolean M_StatisticsInputs(INT32 ch) +{ + const UINT8 pid = 0; + + (void)ch; + + if (M_MenuBackPressed(pid)) + { + M_GoBack(0); + M_SetMenuDelay(pid); + + Z_Free(statisticsmenu.maplist); + statisticsmenu.maplist = NULL; + + return true; + } + + if (M_MenuExtraPressed(pid)) + { + if (statisticsmenu.location > 0) + { + statisticsmenu.location = 0; + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + } + else if (menucmd[pid].dpad_ud > 0) + { + if (statisticsmenu.location < statisticsmenu.maxscroll) + { + statisticsmenu.location++; + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + } + else if (menucmd[pid].dpad_ud < 0) + { + if (statisticsmenu.location > 0) + { + statisticsmenu.location--; + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + } + + return true; +} diff --git a/src/menus/main-1.c b/src/menus/main-1.c index ea337e3f3..aa441b572 100644 --- a/src/menus/main-1.c +++ b/src/menus/main-1.c @@ -11,6 +11,13 @@ // point to submenus. #include "../k_menu.h" +#include "../m_random.h" +#include "../s_sound.h" +#include "../i_time.h" +#include "../v_video.h" +#include "../z_zone.h" +#include "../i_video.h" // I_FinishUpdate +#include "../i_system.h" // I_Sleep menuitem_t MainMenu[] = { @@ -32,3 +39,74 @@ menuitem_t MainMenu[] = }; menu_t MainDef = KARTGAMEMODEMENU(MainMenu, NULL); + +// Quit Game +static INT32 quitsounds[] = +{ + // holy shit we're changing things up! + // srb2kart: you ain't seen nothing yet + sfx_kc2e, + sfx_kc2f, + sfx_cdfm01, + sfx_ddash, + sfx_s3ka2, + sfx_s3k49, + sfx_slip, + sfx_tossed, + sfx_s3k7b, + sfx_itrolf, + sfx_itrole, + sfx_cdpcm9, + sfx_s3k4e, + sfx_s259, + sfx_3db06, + sfx_s3k3a, + sfx_peel, + sfx_cdfm28, + sfx_s3k96, + sfx_s3kc0s, + sfx_cdfm39, + sfx_hogbom, + sfx_kc5a, + sfx_kc46, + sfx_s3k92, + sfx_s3k42, + sfx_kpogos, + sfx_screec +}; + +void M_QuitSRB2(INT32 choice) +{ + // We pick index 0 which is language sensitive, or one at random, + // between 1 and maximum number. + (void)choice; + M_StartMessage("Are you sure you want to quit playing?\n\nPress (A) to confirm or (B) to cancel", FUNCPTRCAST(M_QuitResponse), MM_YESNO); +} + +void M_QuitResponse(INT32 ch) +{ + tic_t ptime; + INT32 mrand; + + if (ch == MA_YES) + { + if (!(netgame || cht_debug)) + { + mrand = M_RandomKey(sizeof(quitsounds) / sizeof(INT32)); + if (quitsounds[mrand]) + S_StartSound(NULL, quitsounds[mrand]); + + //added : 12-02-98: do that instead of I_WaitVbl which does not work + ptime = I_GetTime() + NEWTICRATE*2; // Shortened the quit time, used to be 2 seconds Tails 03-26-2001 + while (ptime > I_GetTime()) + { + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + V_DrawSmallScaledPatch(0, 0, 0, W_CachePatchName("GAMEQUIT", PU_CACHE)); // Demo 3 Quit Screen Tails 06-16-2001 + I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001 + I_Sleep(cv_sleep.value); + I_UpdateTime(cv_timescale.value); + } + } + I_Quit(); + } +} diff --git a/src/menus/options-1.c b/src/menus/options-1.c index 6c6d12374..fd35da23d 100644 --- a/src/menus/options-1.c +++ b/src/menus/options-1.c @@ -2,6 +2,9 @@ /// \brief Options Menu #include "../k_menu.h" +#include "../k_grandprix.h" // K_CanChangeRules +#include "../m_cond.h" // Condition Sets +#include "../s_sound.h" // options menu -- see mopt_e menuitem_t OPTIONS_Main[] = @@ -47,3 +50,181 @@ menu_t OPTIONS_MainDef = { NULL, M_OptionsInputs }; + +struct optionsmenu_s optionsmenu; + +void M_ResetOptions(void) +{ + optionsmenu.ticker = 0; + optionsmenu.offset = 0; + + optionsmenu.optx = 0; + optionsmenu.opty = 0; + optionsmenu.toptx = 0; + optionsmenu.topty = 0; + + // BG setup: + optionsmenu.currcolour = OPTIONS_MainDef.extra1; + optionsmenu.lastcolour = 0; + optionsmenu.fade = 0; + + // For profiles: + memset(setup_player, 0, sizeof(setup_player)); + optionsmenu.profile = NULL; +} + +void M_InitOptions(INT32 choice) +{ + (void)choice; + + OPTIONS_MainDef.menuitems[mopt_gameplay].status = IT_STRING | IT_TRANSTEXT; + OPTIONS_MainDef.menuitems[mopt_server].status = IT_STRING | IT_TRANSTEXT; + + // enable gameplay & server options under the right circumstances. + if (gamestate == GS_MENU + || ((server || IsPlayerAdmin(consoleplayer)) && K_CanChangeRules(false))) + { + OPTIONS_MainDef.menuitems[mopt_gameplay].status = IT_STRING | IT_SUBMENU; + OPTIONS_MainDef.menuitems[mopt_server].status = IT_STRING | IT_SUBMENU; + OPTIONS_GameplayDef.menuitems[gopt_encore].status = + (M_SecretUnlocked(SECRET_ENCORE, false) ? (IT_STRING | IT_CVAR) : IT_DISABLED); + } + + OPTIONS_DataDef.menuitems[dopt_erase].status = (gamestate == GS_MENU + ? (IT_STRING | IT_SUBMENU) + : (IT_TRANSTEXT2 | IT_SPACE)); + + M_ResetOptions(); + + // So that pause doesn't go to the main menu... + OPTIONS_MainDef.prevMenu = currentMenu; + + // This will disable or enable the textboxes of the affected menus before we get to them. + Screenshot_option_Onchange(); + Moviemode_mode_Onchange(); + Moviemode_option_Onchange(); + Addons_option_Onchange(); + + M_SetupNextMenu(&OPTIONS_MainDef, false); +} + +// Prepares changing the colour of the background +void M_OptionsChangeBGColour(INT16 newcolour) +{ + optionsmenu.fade = 10; + optionsmenu.lastcolour = optionsmenu.currcolour; + optionsmenu.currcolour = newcolour; +} + +boolean M_OptionsQuit(void) +{ + optionsmenu.toptx = 140-1; + optionsmenu.topty = 70+1; + + // Reset button behaviour because profile menu is different, since of course it is. + if (optionsmenu.resetprofilemenu) + { + optionsmenu.profilemenu = false; + optionsmenu.profile = NULL; + optionsmenu.resetprofilemenu = false; + } + + return true; // Always allow quitting, duh. +} + +void M_OptionsTick(void) +{ + optionsmenu.offset /= 2; + optionsmenu.ticker++; + + optionsmenu.optx += (optionsmenu.toptx - optionsmenu.optx)/2; + optionsmenu.opty += (optionsmenu.topty - optionsmenu.opty)/2; + + if (abs(optionsmenu.optx - optionsmenu.opty) < 2) + { + optionsmenu.optx = optionsmenu.toptx; + optionsmenu.opty = optionsmenu.topty; // Avoid awkward 1 px errors. + } + + // Move the button for cool animations + if (currentMenu == &OPTIONS_MainDef) + { + M_OptionsQuit(); // ...So now this is used here. + } + else if (optionsmenu.profile == NULL) // Not currently editing a profile (otherwise we're using these variables for other purposes....) + { + // I don't like this, it looks like shit but it needs to be done.......... + if (optionsmenu.profilemenu) + { + optionsmenu.toptx = 420; + optionsmenu.topty = 70+1; + } + else if (currentMenu == &OPTIONS_GameplayItemsDef) + { + optionsmenu.toptx = -160; // off the side of the screen + optionsmenu.topty = 50; + } + else + { + optionsmenu.toptx = 160; + optionsmenu.topty = 50; + } + } + + // Handle the background stuff: + if (optionsmenu.fade) + optionsmenu.fade--; + + // change the colour if we aren't matching the current menu colour + if (optionsmenu.currcolour != currentMenu->extra1) + M_OptionsChangeBGColour(currentMenu->extra1); + + // And one last giggle... + if (shitsfree) + shitsfree--; +} + +boolean M_OptionsInputs(INT32 ch) +{ + + const UINT8 pid = 0; + (void)ch; + + if (menucmd[pid].dpad_ud > 0) + { + M_SetMenuDelay(pid); + optionsmenu.offset += 48; + M_NextOpt(); + S_StartSound(NULL, sfx_s3k5b); + + if (itemOn == 0) + optionsmenu.offset -= currentMenu->numitems*48; + + + return true; + } + else if (menucmd[pid].dpad_ud < 0) + { + M_SetMenuDelay(pid); + optionsmenu.offset -= 48; + M_PrevOpt(); + S_StartSound(NULL, sfx_s3k5b); + + if (itemOn == currentMenu->numitems-1) + optionsmenu.offset += currentMenu->numitems*48; + + + return true; + } + else if (M_MenuConfirmPressed(pid)) + { + + if (currentMenu->menuitems[itemOn].status & IT_TRANSTEXT) + return true; // No. + + optionsmenu.optx = 140; + optionsmenu.opty = 70; // Default position for the currently selected option. + return false; // Don't eat. + } + return false; +} diff --git a/src/menus/options-data-addons.c b/src/menus/options-data-addons.c index 8b6cce96a..1af384e97 100644 --- a/src/menus/options-data-addons.c +++ b/src/menus/options-data-addons.c @@ -51,3 +51,10 @@ menu_t OPTIONS_DataAddonDef = { NULL, }; +void Addons_option_Onchange(void) +{ + // Option 2 will always be the textbar. + // (keep in mind this is a 0 indexed array and the first element is a header...) + OPTIONS_DataAddon[2].status = + (cv_addons_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED); +} diff --git a/src/menus/options-data-erase-1.c b/src/menus/options-data-erase-1.c index 8be6deff0..a27e1f559 100644 --- a/src/menus/options-data-erase-1.c +++ b/src/menus/options-data-erase-1.c @@ -2,6 +2,9 @@ /// \brief Erase Data Menu #include "../k_menu.h" +#include "../s_sound.h" +#include "../m_cond.h" // Condition Sets +#include "../f_finale.h" menuitem_t OPTIONS_DataErase[] = { @@ -40,3 +43,42 @@ menu_t OPTIONS_DataEraseDef = { NULL, NULL, }; + +static void M_EraseDataResponse(INT32 ch) +{ + if (ch == MA_NO) + return; + + S_StartSound(NULL, sfx_itrole); // bweh heh heh + + // Delete the data + if (optionsmenu.erasecontext == 2) + { + // SRB2Kart: This actually needs to be done FIRST, so that you don't immediately regain playtime/matches secrets + gamedata->totalplaytime = 0; + gamedata->matchesplayed = 0; + } + if (optionsmenu.erasecontext != 1) + G_ClearRecords(); + if (optionsmenu.erasecontext != 0) + M_ClearSecrets(); + + F_StartIntro(); + M_ClearMenus(true); +} + +void M_EraseData(INT32 choice) +{ + const char *eschoice, *esstr = M_GetText("Are you sure you want to erase\n%s?\n\nPress (A) to confirm or (B) to cancel\n"); + + optionsmenu.erasecontext = (UINT8)choice; + + if (choice == 0) + eschoice = M_GetText("Time Attack data"); + else if (choice == 1) + eschoice = M_GetText("Secrets data"); + else + eschoice = M_GetText("ALL game data"); + + M_StartMessage(va(esstr, eschoice), FUNCPTRCAST(M_EraseDataResponse), MM_YESNO); +} diff --git a/src/menus/options-data-erase-profile.c b/src/menus/options-data-erase-profile.c index 87e4e95cc..69afc1d20 100644 --- a/src/menus/options-data-erase-profile.c +++ b/src/menus/options-data-erase-profile.c @@ -2,6 +2,8 @@ /// \brief Erase Profile Menu #include "../k_menu.h" +#include "../s_sound.h" +#include "../f_finale.h" menuitem_t OPTIONS_DataProfileErase[] = { @@ -22,3 +24,84 @@ menu_t OPTIONS_DataProfileEraseDef = { NULL, NULL }; + +// Check if we have any profile loaded. +void M_CheckProfileData(INT32 choice) +{ + UINT8 np = PR_GetNumProfiles(); + (void) choice; + + if (np < 2) + { + S_StartSound(NULL, sfx_s3k7b); + M_StartMessage("There are no custom profiles.\n\nPress (B)", NULL, MM_NOTHING); + return; + } + + optionsmenu.eraseprofilen = 1; + M_SetupNextMenu(&OPTIONS_DataProfileEraseDef, false); +} + +static void M_EraseProfileResponse(INT32 choice) +{ + if (choice == MA_YES) + { + S_StartSound(NULL, sfx_itrole); // bweh heh heh + + PR_DeleteProfile(optionsmenu.eraseprofilen); + + // Did we bust our current profile..!? + if (cv_currprofile.value == -1) + { + F_StartIntro(); + M_ClearMenus(true); + } + else if (optionsmenu.eraseprofilen > PR_GetNumProfiles()-1) + { + optionsmenu.eraseprofilen--; + } + } +} + +void M_HandleProfileErase(INT32 choice) +{ + const UINT8 pid = 0; + const UINT8 np = PR_GetNumProfiles()-1; + (void) choice; + + if (menucmd[pid].dpad_ud > 0) + { + S_StartSound(NULL, sfx_s3k5b); + optionsmenu.eraseprofilen++; + + if (optionsmenu.eraseprofilen > np) + optionsmenu.eraseprofilen = 1; + + M_SetMenuDelay(pid); + } + else if (menucmd[pid].dpad_ud < 0) + { + S_StartSound(NULL, sfx_s3k5b); + + if (optionsmenu.eraseprofilen == 1) + optionsmenu.eraseprofilen = np; + else + optionsmenu.eraseprofilen--; + + M_SetMenuDelay(pid); + } + else if (M_MenuBackPressed(pid)) + { + M_GoBack(0); + M_SetMenuDelay(pid); + } + else if (M_MenuConfirmPressed(pid)) + { + if (optionsmenu.eraseprofilen == cv_currprofile.value) + M_StartMessage("Your ""\x85""current profile""\x80"" will be erased.\nAre you sure you want to proceed?\nDeleting this profile will also\nreturn you to the title screen.\n\nPress (A) to confirm or (B) to cancel", FUNCPTRCAST(M_EraseProfileResponse), MM_YESNO); + else + M_StartMessage("This profile will be erased.\nAre you sure you want to proceed?\n\nPress (A) to confirm or (B) to cancel", FUNCPTRCAST(M_EraseProfileResponse), MM_YESNO); + + M_SetMenuDelay(pid); + } +} diff --git a/src/menus/options-data-screenshots.c b/src/menus/options-data-screenshots.c index a24dea49c..dcd50f99d 100644 --- a/src/menus/options-data-screenshots.c +++ b/src/menus/options-data-screenshots.c @@ -44,3 +44,43 @@ menu_t OPTIONS_DataScreenshotDef = { NULL, NULL, }; + +void Screenshot_option_Onchange(void) +{ + // Screenshot opt is at #3, 0 based array obv. + OPTIONS_DataScreenshot[2].status = + (cv_screenshot_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED); + +} + +void Moviemode_mode_Onchange(void) +{ +#if 0 + INT32 i, cstart, cend; + for (i = op_screenshot_gif_start; i <= op_screenshot_apng_end; ++i) + OP_ScreenshotOptionsMenu[i].status = IT_DISABLED; + + switch (cv_moviemode.value) + { + case MM_GIF: + cstart = op_screenshot_gif_start; + cend = op_screenshot_gif_end; + break; + case MM_APNG: + cstart = op_screenshot_apng_start; + cend = op_screenshot_apng_end; + break; + default: + return; + } + for (i = cstart; i <= cend; ++i) + OP_ScreenshotOptionsMenu[i].status = IT_STRING|IT_CVAR; +#endif +} + +void Moviemode_option_Onchange(void) +{ + // opt 7 in a 0 based array, you get the idea... + OPTIONS_DataScreenshot[6].status = + (cv_movie_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED); +} diff --git a/src/menus/options-gameplay-item-toggles.c b/src/menus/options-gameplay-item-toggles.c index 3479d5998..4c6e76080 100644 --- a/src/menus/options-gameplay-item-toggles.c +++ b/src/menus/options-gameplay-item-toggles.c @@ -2,6 +2,7 @@ /// \brief Random Item Toggles #include "../k_menu.h" +#include "../s_sound.h" menuitem_t OPTIONS_GameplayItems[] = { @@ -60,3 +61,122 @@ menu_t OPTIONS_GameplayItemsDef = { NULL, NULL, }; + +void M_HandleItemToggles(INT32 choice) +{ + const INT32 width = 8, height = 4; + INT32 column = itemOn/height, row = itemOn%height; + INT16 next; + UINT8 i; + boolean exitmenu = false; + const UINT8 pid = 0; + + (void) choice; + + if (menucmd[pid].dpad_lr > 0) + { + S_StartSound(NULL, sfx_s3k5b); + column++; + if (((column*height)+row) >= currentMenu->numitems) + column = 0; + next = min(((column*height)+row), currentMenu->numitems-1); + itemOn = next; + + M_SetMenuDelay(pid); + } + + else if (menucmd[pid].dpad_lr < 0) + { + S_StartSound(NULL, sfx_s3k5b); + column--; + if (column < 0) + column = width-1; + if (((column*height)+row) >= currentMenu->numitems) + column--; + next = max(((column*height)+row), 0); + if (next >= currentMenu->numitems) + next = currentMenu->numitems-1; + itemOn = next; + + M_SetMenuDelay(pid); + } + + else if (menucmd[pid].dpad_ud > 0) + { + S_StartSound(NULL, sfx_s3k5b); + row = (row+1) % height; + if (((column*height)+row) >= currentMenu->numitems) + row = 0; + next = min(((column*height)+row), currentMenu->numitems-1); + itemOn = next; + + M_SetMenuDelay(pid); + } + + else if (menucmd[pid].dpad_ud < 0) + { + S_StartSound(NULL, sfx_s3k5b); + row = (row-1) % height; + if (row < 0) + row = height-1; + if (((column*height)+row) >= currentMenu->numitems) + row--; + next = max(((column*height)+row), 0); + if (next >= currentMenu->numitems) + next = currentMenu->numitems-1; + itemOn = next; + + M_SetMenuDelay(pid); + } + + else if (M_MenuConfirmPressed(pid)) + { + M_SetMenuDelay(pid); + if (currentMenu->menuitems[itemOn].mvar1 == 255) + { + //S_StartSound(NULL, sfx_s26d); + if (!shitsfree) + { + shitsfree = TICRATE; + S_StartSound(NULL, sfx_itfree); + } + } + else + if (currentMenu->menuitems[itemOn].mvar1 == 0) + { + INT32 v = cv_items[0].value; + S_StartSound(NULL, sfx_s1b4); + for (i = 0; i < NUMKARTRESULTS-1; i++) + { + if (cv_items[i].value == v) + CV_AddValue(&cv_items[i], 1); + } + } + else + { + if (currentMenu->menuitems[itemOn].mvar2) + { + S_StartSound(NULL, currentMenu->menuitems[itemOn].mvar2); + } + else + { + S_StartSound(NULL, sfx_s1ba); + } + CV_AddValue(&cv_items[currentMenu->menuitems[itemOn].mvar1-1], 1); + } + } + + else if (M_MenuBackPressed(pid)) + { + M_SetMenuDelay(pid); + exitmenu = true; + } + + if (exitmenu) + { + if (currentMenu->prevMenu) + M_SetupNextMenu(currentMenu->prevMenu, false); + else + M_ClearMenus(true); + } +} diff --git a/src/menus/options-profiles-1.c b/src/menus/options-profiles-1.c index a61eb1ef5..bc0fc280c 100644 --- a/src/menus/options-profiles-1.c +++ b/src/menus/options-profiles-1.c @@ -2,6 +2,7 @@ /// \brief Profiles Menu #include "../k_menu.h" +#include "../s_sound.h" // profile select menuitem_t OPTIONS_Profiles[] = { @@ -23,3 +24,195 @@ menu_t OPTIONS_ProfilesDef = { NULL, NULL, }; + +consvar_t cv_dummyprofilename = CVAR_INIT ("dummyprofilename", "", CV_HIDDEN, NULL, NULL); +consvar_t cv_dummyprofileplayername = CVAR_INIT ("dummyprofileplayername", "", CV_HIDDEN, NULL, NULL); +consvar_t cv_dummyprofilekickstart = CVAR_INIT ("dummyprofilekickstart", "Off", CV_HIDDEN, CV_OnOff, NULL); + +void M_ProfileSelectInit(INT32 choice) +{ + (void)choice; + optionsmenu.profilemenu = true; + + M_SetupNextMenu(&OPTIONS_ProfilesDef, false); +} + +// Select the current profile for menu use and go to maindef. +void M_FirstPickProfile(INT32 c) +{ + if (c == MA_YES) + { + M_ResetOptions(); // Reset all options variables otherwise things are gonna go reaaal bad lol. + optionsmenu.profile = NULL; // Make sure to get rid of that, too. + + PR_ApplyProfile(optionsmenu.profilen, 0); + M_SetupNextMenu(M_InterruptMenuWithChallenges(&MainDef), false); + + // Tell the game this is the last profile we picked. + CV_StealthSetValue(&cv_ttlprofilen, optionsmenu.profilen); + + // Save em! + PR_SaveProfiles(); + return; + } +} + +// Start menu edition. Call this with MA_YES if not used with a textbox. +static void M_StartEditProfile(INT32 c) +{ + + const INT32 maxp = PR_GetNumProfiles(); + + if (c == MA_YES) + { + if (optionsmenu.profilen == maxp) + PR_InitNewProfile(); // initialize the new profile. + + optionsmenu.profile = PR_GetProfile(optionsmenu.profilen); + // copy this profile's controls into optionsmenu so that we can edit controls without changing them directly. + // we do this so that we don't edit a profile's controls in real-time and end up doing really weird shit. + memcpy(&optionsmenu.tempcontrols, optionsmenu.profile->controls, sizeof(gamecontroldefault)); + + // This is now used to move the card we've selected. + optionsmenu.optx = 160; + optionsmenu.opty = 35; + optionsmenu.toptx = 130/2; + optionsmenu.topty = 0; + + // setup cvars + if (optionsmenu.profile->version) + { + CV_StealthSet(&cv_dummyprofilename, optionsmenu.profile->profilename); + CV_StealthSet(&cv_dummyprofileplayername, optionsmenu.profile->playername); + CV_StealthSetValue(&cv_dummyprofilekickstart, optionsmenu.profile->kickstartaccel); + } + else + { + CV_StealthSet(&cv_dummyprofilename, ""); + CV_StealthSet(&cv_dummyprofileplayername, ""); + CV_StealthSetValue(&cv_dummyprofilekickstart, 0); // off + } + + // Setup greyout and stuff. + OPTIONS_EditProfile[popt_profilename].status = IT_STRING | IT_CVAR | IT_CV_STRING; + OPTIONS_EditProfile[popt_profilepname].status = IT_STRING | IT_CVAR | IT_CV_STRING; + OPTIONS_EditProfile[popt_char].status = IT_STRING | IT_CALL; + + if (gamestate != GS_MENU) // If we're modifying things mid game, transtext some of those! + { + OPTIONS_EditProfile[popt_profilename].status |= IT_TRANSTEXT; + OPTIONS_EditProfile[popt_profilepname].status |= IT_TRANSTEXT; + OPTIONS_EditProfile[popt_char].status |= IT_TRANSTEXT; + } + + M_SetupNextMenu(&OPTIONS_EditProfileDef, false); + return; + } +} + +void M_HandleProfileSelect(INT32 ch) +{ + const UINT8 pid = 0; + INT32 maxp = PR_GetNumProfiles(); + boolean creatable = (maxp < MAXPROFILES); + (void) ch; + + if (!creatable) + { + maxp = MAXPROFILES; + } + + if (menucmd[pid].dpad_lr > 0) + { + optionsmenu.profilen++; + optionsmenu.offset += (128 + 128/8); + + if (optionsmenu.profilen > maxp) + { + optionsmenu.profilen = 0; + optionsmenu.offset -= (128 + 128/8)*(maxp+1); + } + + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + + } + else if (menucmd[pid].dpad_lr < 0) + { + optionsmenu.profilen--; + optionsmenu.offset -= (128 + 128/8); + + if (optionsmenu.profilen < 0) + { + optionsmenu.profilen = maxp; + optionsmenu.offset += (128 + 128/8)*(maxp+1); + } + + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + + else if (M_MenuConfirmPressed(pid)) + { + + // Boot profile setup has already been done. + if (cv_currprofile.value > -1) + { + + if (optionsmenu.profilen == 0) // Guest profile, you can't edit that one! + { + S_StartSound(NULL, sfx_s3k7b); + M_StartMessage(M_GetText("The Guest profile cannot be edited.\nCreate a new profile instead."), NULL, MM_NOTHING); + M_SetMenuDelay(pid); + return; + } + else if (creatable && optionsmenu.profilen == maxp && gamestate != GS_MENU) + { + S_StartSound(NULL, sfx_s3k7b); + M_StartMessage(M_GetText("Cannot create a new profile\nmid-game. Return to the\ntitle screen first."), NULL, MM_NOTHING); + M_SetMenuDelay(pid); + return; + } + + S_StartSound(NULL, sfx_s3k5b); + M_StartEditProfile(MA_YES); + } + else + { + // We're on the profile selection screen. + if (creatable && optionsmenu.profilen == maxp) + { + M_StartEditProfile(MA_YES); + M_SetMenuDelay(pid); + return; + } + else + { +#if 0 + if (optionsmenu.profilen == 0) + { + M_StartMessage(M_GetText("Are you sure you wish\nto use the Guest Profile?\nThis profile cannot be customised.\nIt is recommended to create\na new Profile instead.\n\nPress (A) to confirm or (B) to cancel"), FUNCPTRCAST(M_FirstPickProfile), MM_YESNO); + return; + } +#endif + + M_FirstPickProfile(MA_YES); + M_SetMenuDelay(pid); + return; + } + } + } + + else if (M_MenuBackPressed(pid)) + { + optionsmenu.resetprofilemenu = true; + M_GoBack(0); + M_SetMenuDelay(pid); + } + + if (menutransition.tics == 0 && optionsmenu.resetprofile) + { + optionsmenu.profile = NULL; // Make sure to reset that when transitions are done.' + optionsmenu.resetprofile = false; + } +} diff --git a/src/menus/options-profiles-edit-1.c b/src/menus/options-profiles-edit-1.c index 2e9f91c17..061acbf6a 100644 --- a/src/menus/options-profiles-edit-1.c +++ b/src/menus/options-profiles-edit-1.c @@ -2,6 +2,7 @@ /// \brief Profile Editor #include "../k_menu.h" +#include "../s_sound.h" menuitem_t OPTIONS_EditProfile[] = { {IT_STRING | IT_CVAR | IT_CV_STRING, "Profile Name", "6-character long name to identify this Profile.", @@ -35,3 +36,145 @@ menu_t OPTIONS_EditProfileDef = { NULL, M_ProfileEditInputs, }; + +// Returns true if the profile can be saved, false otherwise. Also starts messages if necessary. +static boolean M_ProfileEditEnd(const UINT8 pid) +{ + UINT8 i; + + // Guest profile, you can't edit that one! + if (optionsmenu.profilen == 0) + { + S_StartSound(NULL, sfx_s3k7b); + M_StartMessage(M_GetText("Guest profile cannot be edited.\nCreate a new profile instead."), NULL, MM_NOTHING); + M_SetMenuDelay(pid); + return false; + } + + // check if some profiles have the same name + for (i = 0; i < PR_GetNumProfiles(); i++) + { + profile_t *check = PR_GetProfile(i); + + // For obvious reasons don't check if our name is the same as our name.... + if (check != optionsmenu.profile) + { + if (!(strcmp(optionsmenu.profile->profilename, check->profilename))) + { + S_StartSound(NULL, sfx_s3k7b); + M_StartMessage(M_GetText("Another profile uses the same name.\nThis must be changed to be able to save."), NULL, MM_NOTHING); + M_SetMenuDelay(pid); + return false; + } + } + } + + return true; +} + +static void M_ProfileEditExit(void) +{ + optionsmenu.toptx = 160; + optionsmenu.topty = 35; + optionsmenu.resetprofile = true; // Reset profile after the transition is done. + + PR_SaveProfiles(); // save profiles after we do that. +} + +// For profile edit, just make sure going back resets the card to its position, the rest is taken care of automatically. +boolean M_ProfileEditInputs(INT32 ch) +{ + + (void) ch; + const UINT8 pid = 0; + + if (M_MenuBackPressed(pid)) + { + if (M_ProfileEditEnd(pid)) + { + M_ProfileEditExit(); + if (cv_currprofile.value == -1) + M_SetupNextMenu(&MAIN_ProfilesDef, false); + else + M_GoBack(0); + M_SetMenuDelay(pid); + } + return true; + } + else if (M_MenuConfirmPressed(pid)) + { + if (currentMenu->menuitems[itemOn].status & IT_TRANSTEXT) + return true; // No. + } + + return false; +} + +// Handle some actions in profile editing +void M_HandleProfileEdit(void) +{ + // Always copy the profile name and player name in the profile. + if (optionsmenu.profile) + { + // Copy the first 6 chars for profile name + if (strlen(cv_dummyprofilename.string)) + { + char *s; + // convert dummyprofilename to uppercase + strncpy(optionsmenu.profile->profilename, cv_dummyprofilename.string, PROFILENAMELEN); + s = optionsmenu.profile->profilename; + while (*s) + { + *s = toupper(*s); + s++; + } + } + + if (strlen(cv_dummyprofileplayername.string)) + strncpy(optionsmenu.profile->playername, cv_dummyprofileplayername.string, MAXPLAYERNAME); + } + + M_OptionsTick(); // Has to be afterwards because this can unset optionsmenu.profile +} + +// Confirm Profile edi via button. +void M_ConfirmProfile(INT32 choice) +{ + const UINT8 pid = 0; + (void) choice; + + if (M_ProfileEditEnd(pid)) + { + if (cv_currprofile.value > -1) + { + M_ProfileEditExit(); + M_GoBack(0); + M_SetMenuDelay(pid); + } + else + { + M_StartMessage(M_GetText("Are you sure you wish to\nselect this profile?\n\nPress (A) to confirm or (B) to cancel"), FUNCPTRCAST(M_FirstPickProfile), MM_YESNO); + M_SetMenuDelay(pid); + } + } + return; +} + +// Prompt a device selection window (just tap any button on the device you want) +void M_ProfileDeviceSelect(INT32 choice) +{ + (void)choice; + + // While we're here, setup the incoming controls menu to reset the scroll & bind status: + optionsmenu.controlscroll = 0; + optionsmenu.bindcontrol = 0; + optionsmenu.bindtimer = 0; + + optionsmenu.lastkey = 0; + optionsmenu.keyheldfor = 0; + + optionsmenu.contx = optionsmenu.tcontx = controlleroffsets[gc_a][0]; + optionsmenu.conty = optionsmenu.tconty = controlleroffsets[gc_a][1]; + + M_SetupNextMenu(&OPTIONS_ProfileControlsDef, false); // Don't set device here anymore. +} diff --git a/src/menus/options-profiles-edit-controls.c b/src/menus/options-profiles-edit-controls.c index 774bcdfa4..d1ac713f2 100644 --- a/src/menus/options-profiles-edit-controls.c +++ b/src/menus/options-profiles-edit-controls.c @@ -2,6 +2,8 @@ /// \brief Profile Controls Editor #include "../k_menu.h" +#include "../s_sound.h" +#include "../i_joy.h" // for joystick menu controls menuitem_t OPTIONS_ProfileControls[] = { @@ -108,3 +110,339 @@ menu_t OPTIONS_ProfileControlsDef = { NULL, M_ProfileControlsInputs, }; + +// sets whatever device has had its key pressed to the active device. +// 20/05/22: Commented out for now but not deleted as it might still find some use in the future? +/* +static void SetDeviceOnPress(void) +{ + UINT8 i; + + for (i=0; i < MAXDEVICES; i++) + { + if (deviceResponding[i]) + { + CV_SetValue(&cv_usejoystick[0], i); // Force-set this joystick as the current joystick we're using for P1 (which is the only one controlling menus) + CONS_Printf("SetDeviceOnPress: Device for %d set to %d\n", 0, i); + return; + } + } +} +*/ + +void M_HandleProfileControls(void) +{ + UINT8 maxscroll = currentMenu->numitems - 5; + M_OptionsTick(); + + optionsmenu.contx += (optionsmenu.tcontx - optionsmenu.contx)/2; + optionsmenu.conty += (optionsmenu.tconty - optionsmenu.conty)/2; + + if (abs(optionsmenu.contx - optionsmenu.tcontx) < 2 && abs(optionsmenu.conty - optionsmenu.tconty) < 2) + { + optionsmenu.contx = optionsmenu.tcontx; + optionsmenu.conty = optionsmenu.tconty; // Avoid awkward 1 px errors. + } + + optionsmenu.controlscroll = itemOn - 3; // very barebones scrolling, but it works just fine for our purpose. + if (optionsmenu.controlscroll > maxscroll) + optionsmenu.controlscroll = maxscroll; + + if (optionsmenu.controlscroll < 0) + optionsmenu.controlscroll = 0; + + // bindings, cancel if timer is depleted. + if (optionsmenu.bindcontrol) + { + optionsmenu.bindtimer--; + if (!optionsmenu.bindtimer) + { + optionsmenu.bindcontrol = 0; // we've gone past the max, just stop. + } + + } +} + +void M_ProfileTryController(INT32 choice) +{ + (void)choice; + + optionsmenu.trycontroller = TICRATE*5; + + // Apply these controls right now on P1's end. + memcpy(&gamecontrol[0], optionsmenu.tempcontrols, sizeof(gamecontroldefault)); +} + +static void M_ProfileControlSaveResponse(INT32 choice) +{ + if (choice == MA_YES) + { + SINT8 belongsto = PR_ProfileUsedBy(optionsmenu.profile); + // Save the profile + optionsmenu.profile->kickstartaccel = cv_dummyprofilekickstart.value; + memcpy(&optionsmenu.profile->controls, optionsmenu.tempcontrols, sizeof(gamecontroldefault)); + + // If this profile is in-use by anyone, apply the changes immediately upon exiting. + // Don't apply the profile itself as that would lead to issues mid-game. + if (belongsto > -1 && belongsto < MAXSPLITSCREENPLAYERS) + { + memcpy(&gamecontrol[belongsto], optionsmenu.tempcontrols, sizeof(gamecontroldefault)); + CV_StealthSetValue(&cv_kickstartaccel[belongsto], cv_dummyprofilekickstart.value); + } + + M_GoBack(0); + } +} + +void M_ProfileControlsConfirm(INT32 choice) +{ + (void)choice; + + //M_StartMessage(M_GetText("Exiting will save the control changes\nfor this Profile.\nIs this okay?\n\nPress (A) to confirm or (B) to cancel"), FUNCPTRCAST(M_ProfileControlSaveResponse), MM_YESNO); + // TODO: Add a graphic for controls saving, instead of obnoxious prompt. + + M_ProfileControlSaveResponse(MA_YES); + + optionsmenu.profile->kickstartaccel = cv_dummyprofilekickstart.value; // Make sure to save kickstart accel. + + // Reapply player 1's real profile. + if (cv_currprofile.value > -1) + { + PR_ApplyProfile(cv_lastprofile[0].value, 0); + } +} + +boolean M_ProfileControlsInputs(INT32 ch) +{ + const UINT8 pid = 0; + (void)ch; + + // By default, accept all inputs. + if (optionsmenu.trycontroller) + { + if (menucmd[pid].dpad_ud || menucmd[pid].dpad_lr || menucmd[pid].buttons) + { + optionsmenu.trycontroller = 5*TICRATE; + } + else + { + optionsmenu.trycontroller--; + } + + if (optionsmenu.trycontroller == 0) + { + // Reset controls to that of the current profile. + profile_t *cpr = PR_GetProfile(cv_currprofile.value); + if (cpr == NULL) + cpr = PR_GetProfile(0); // Creating a profile at boot, revert to guest profile + memcpy(&gamecontrol[0], cpr->controls, sizeof(gamecontroldefault)); + } + + return true; + } + + if (optionsmenu.bindcontrol) + return true; // Eat all inputs there. We'll use a stupid hack in M_Responder instead. + + //SetDeviceOnPress(); // Update device constantly so that we don't stay stuck with otpions saying a device is unavailable just because we're mapping multiple devices... + + if (M_MenuExtraPressed(pid)) + { + // check if we're on a valid menu option... + if (currentMenu->menuitems[itemOn].mvar1) + { + // clear controls for that key + INT32 i; + + for (i = 0; i < MAXINPUTMAPPING; i++) + optionsmenu.tempcontrols[currentMenu->menuitems[itemOn].mvar1][i] = KEY_NULL; + + S_StartSound(NULL, sfx_s3k66); + } + M_SetMenuDelay(pid); + return true; + } + else if (M_MenuBackPressed(pid)) + { + M_ProfileControlsConfirm(0); + M_SetMenuDelay(pid); + return true; + } + + return false; +} + +void M_ProfileSetControl(INT32 ch) +{ + INT32 controln = currentMenu->menuitems[itemOn].mvar1; + UINT8 i; + (void) ch; + + optionsmenu.bindcontrol = 1; // Default to control #1 + + for (i = 0; i < MAXINPUTMAPPING; i++) + { + if (optionsmenu.tempcontrols[controln][i] == KEY_NULL) + { + optionsmenu.bindcontrol = i+1; + break; + } + } + + // If we could find a null key to map into, map there. + // Otherwise, this will stay at 1 which means we'll overwrite the first bound control. + + optionsmenu.bindtimer = TICRATE*5; +} + +// Map the event to the profile. + +#define KEYHOLDFOR 1 +void M_MapProfileControl(event_t *ev) +{ + INT32 c = 0; + UINT8 n = optionsmenu.bindcontrol-1; // # of input to bind + INT32 controln = currentMenu->menuitems[itemOn].mvar1; // gc_ + UINT8 where = n; // By default, we'll save the bind where we're supposed to map. + INT32 i; + + //SetDeviceOnPress(); // Update cv_usejoystick + + // Only consider keydown and joystick events to make sure we ignore ev_mouse and other events + // See also G_MapEventsToControls + switch (ev->type) + { + case ev_keydown: + if (ev->data1 < NUMINPUTS) + { + c = ev->data1; + } +#ifdef PARANOIA + else + { + CONS_Debug(DBG_GAMELOGIC, "Bad downkey input %d\n", ev->data1); + } +#endif + break; + case ev_joystick: + if (ev->data1 >= JOYAXES) + { +#ifdef PARANOIA + CONS_Debug(DBG_GAMELOGIC, "Bad joystick axis event %d\n", ev->data1); +#endif + return; + } + else + { + INT32 deadzone = deadzone = (JOYAXISRANGE * cv_deadzone[0].value) / FRACUNIT; // TODO how properly account for different deadzone cvars for different devices + boolean responsivelr = ((ev->data2 != INT32_MAX) && (abs(ev->data2) >= deadzone)); + boolean responsiveud = ((ev->data3 != INT32_MAX) && (abs(ev->data3) >= deadzone)); + + i = ev->data1; + + if (i >= JOYANALOGS) + { + // The trigger axes are handled specially. + i -= JOYANALOGS; + + if (responsivelr) + { + c = KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2); + } + else if (responsiveud) + { + c = KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2) + 1; + } + } + else + { + // Actual analog sticks + + // Only consider unambiguous assignment. + if (responsivelr == responsiveud) + return; + + if (responsivelr) + { + if (ev->data2 < 0) + { + // Left + c = KEY_AXIS1 + (i * 4); + } + else + { + // Right + c = KEY_AXIS1 + (i * 4) + 1; + } + } + else //if (responsiveud) + { + if (ev->data3 < 0) + { + // Up + c = KEY_AXIS1 + (i * 4) + 2; + } + else + { + // Down + c = KEY_AXIS1 + (i * 4) + 3; + } + } + } + } + break; + default: + return; + } + + // safety result + if (!c) + return; + + // Set menu delay regardless of what we're doing to avoid stupid stuff. + M_SetMenuDelay(0); + + // Check if this particular key (c) is already bound in any slot. + // If that's the case, simply do nothing. + for (i = 0; i < MAXINPUTMAPPING; i++) + { + if (optionsmenu.tempcontrols[controln][i] == c) + { + optionsmenu.bindcontrol = 0; + return; + } + } + + // With the way we do things, there cannot be instances of 'gaps' within the controls, so we don't need to pretend like we need to handle that. + // Unless of course you tamper with the cfg file, but then it's *your* fault, not mine. + + optionsmenu.tempcontrols[controln][where] = c; + optionsmenu.bindcontrol = 0; // not binding anymore + + // If possible, reapply the profile... + // 19/05/22: Actually, no, don't do that, it just fucks everything up in too many cases. + + /* + if (gamestate == GS_MENU) // In menu? Apply this to P1, no questions asked. + { + // Apply the profile's properties to player 1 but keep the last profile cv to p1's ACTUAL profile to revert once we exit. + UINT8 lastp = cv_lastprofile[0].value; + PR_ApplyProfile(PR_GetProfileNum(optionsmenu.profile), 0); + CV_StealthSetValue(&cv_lastprofile[0], lastp); + } + else // != GS_MENU + { + // ONLY apply the profile if it's in use by anything currently. + UINT8 pnum = PR_GetProfileNum(optionsmenu.profile); + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + if (cv_lastprofile[i].value == pnum) + { + PR_ApplyProfile(pnum, i); + break; + } + } + } + */ +} +#undef KEYHOLDFOR diff --git a/src/menus/options-video-modes.c b/src/menus/options-video-modes.c index 160820abf..85f2cd70b 100644 --- a/src/menus/options-video-modes.c +++ b/src/menus/options-video-modes.c @@ -2,6 +2,8 @@ /// \brief Video modes (resolutions) #include "../k_menu.h" +#include "../i_video.h" +#include "../s_sound.h" menuitem_t OPTIONS_VideoModes[] = { @@ -24,3 +26,169 @@ menu_t OPTIONS_VideoModesDef = { NULL, NULL, }; + +// setup video mode menu +void M_VideoModeMenu(INT32 choice) +{ + INT32 i, j, vdup, nummodes; + UINT32 width, height; + const char *desc; + + (void)choice; + + memset(optionsmenu.modedescs, 0, sizeof(optionsmenu.modedescs)); + +#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) + VID_PrepareModeList(); // FIXME: hack +#endif + optionsmenu.vidm_nummodes = 0; + optionsmenu.vidm_selected = 0; + nummodes = VID_NumModes(); + + // DOS does not skip mode 0, because mode 0 is ALWAYS present + i = 0; + for (; i < nummodes && optionsmenu.vidm_nummodes < MAXMODEDESCS; i++) + { + desc = VID_GetModeName(i); + if (desc) + { + vdup = 0; + + // when a resolution exists both under VGA and VESA, keep the + // VESA mode, which is always a higher modenum + for (j = 0; j < optionsmenu.vidm_nummodes; j++) + { + if (!strcmp(optionsmenu.modedescs[j].desc, desc)) + { + // mode(0): 320x200 is always standard VGA, not vesa + if (optionsmenu.modedescs[j].modenum) + { + optionsmenu.modedescs[j].modenum = i; + vdup = 1; + + if (i == vid.modenum) + optionsmenu.vidm_selected = j; + } + else + vdup = 1; + + break; + } + } + + if (!vdup) + { + optionsmenu.modedescs[optionsmenu.vidm_nummodes].modenum = i; + optionsmenu.modedescs[optionsmenu.vidm_nummodes].desc = desc; + + if (i == vid.modenum) + optionsmenu.vidm_selected = optionsmenu.vidm_nummodes; + + // Pull out the width and height + sscanf(desc, "%u%*c%u", &width, &height); + + // Show multiples of 320x200 as green. + if (SCR_IsAspectCorrect(width, height)) + optionsmenu.modedescs[optionsmenu.vidm_nummodes].goodratio = 1; + + optionsmenu.vidm_nummodes++; + } + } + } + + optionsmenu.vidm_column_size = (optionsmenu.vidm_nummodes+2) / 3; + + M_SetupNextMenu(&OPTIONS_VideoModesDef, false); +} + +// special menuitem key handler for video mode list +void M_HandleVideoModes(INT32 ch) +{ + + const UINT8 pid = 0; + (void)ch; + + if (optionsmenu.vidm_testingmode > 0) + { + // change back to the previous mode quickly + if (M_MenuBackPressed(pid)) + { + setmodeneeded = optionsmenu.vidm_previousmode + 1; + optionsmenu.vidm_testingmode = 0; + } + else if (M_MenuConfirmPressed(pid)) + { + S_StartSound(NULL, sfx_s3k5b); + optionsmenu.vidm_testingmode = 0; // stop testing + } + } + + else + { + if (menucmd[pid].dpad_ud > 0) + { + S_StartSound(NULL, sfx_s3k5b); + if (++optionsmenu.vidm_selected >= optionsmenu.vidm_nummodes) + optionsmenu.vidm_selected = 0; + + M_SetMenuDelay(pid); + } + + else if (menucmd[pid].dpad_ud < 0) + { + S_StartSound(NULL, sfx_s3k5b); + if (--optionsmenu.vidm_selected < 0) + optionsmenu.vidm_selected = optionsmenu.vidm_nummodes - 1; + + M_SetMenuDelay(pid); + } + + else if (menucmd[pid].dpad_lr < 0) + { + S_StartSound(NULL, sfx_s3k5b); + optionsmenu.vidm_selected -= optionsmenu.vidm_column_size; + if (optionsmenu.vidm_selected < 0) + optionsmenu.vidm_selected = (optionsmenu.vidm_column_size*3) + optionsmenu.vidm_selected; + if (optionsmenu.vidm_selected >= optionsmenu.vidm_nummodes) + optionsmenu.vidm_selected = optionsmenu.vidm_nummodes - 1; + + M_SetMenuDelay(pid); + } + + else if (menucmd[pid].dpad_lr > 0) + { + S_StartSound(NULL, sfx_s3k5b); + optionsmenu.vidm_selected += optionsmenu.vidm_column_size; + if (optionsmenu.vidm_selected >= (optionsmenu.vidm_column_size*3)) + optionsmenu.vidm_selected %= optionsmenu.vidm_column_size; + if (optionsmenu.vidm_selected >= optionsmenu.vidm_nummodes) + optionsmenu.vidm_selected = optionsmenu.vidm_nummodes - 1; + + M_SetMenuDelay(pid); + } + + else if (M_MenuConfirmPressed(pid)) + { + M_SetMenuDelay(pid); + S_StartSound(NULL, sfx_s3k5b); + if (vid.modenum == optionsmenu.modedescs[optionsmenu.vidm_selected].modenum) + SCR_SetDefaultMode(); + else + { + optionsmenu.vidm_testingmode = 15*TICRATE; + optionsmenu.vidm_previousmode = vid.modenum; + if (!setmodeneeded) // in case the previous setmode was not finished + setmodeneeded = optionsmenu.modedescs[optionsmenu.vidm_selected].modenum + 1; + } + } + + else if (M_MenuBackPressed(pid)) + { + M_SetMenuDelay(pid); + if (currentMenu->prevMenu) + M_SetupNextMenu(currentMenu->prevMenu, false); + else + M_ClearMenus(true); + } + } +} diff --git a/src/menus/play-char-select.c b/src/menus/play-char-select.c index cf3306cca..1116dfa06 100644 --- a/src/menus/play-char-select.c +++ b/src/menus/play-char-select.c @@ -2,6 +2,8 @@ /// \brief Character Select #include "../k_menu.h" +#include "../r_skins.h" +#include "../s_sound.h" menuitem_t PLAY_CharSelect[] = { @@ -22,3 +24,1461 @@ menu_t PLAY_CharSelectDef = { M_CharacterSelectQuit, M_CharacterSelectHandler }; + +static CV_PossibleValue_t skins_cons_t[MAXSKINS+1] = {{1, DEFAULTSKIN}}; +consvar_t cv_chooseskin = CVAR_INIT ("chooseskin", DEFAULTSKIN, CV_HIDDEN, skins_cons_t, NULL); + +static void Splitplayers_OnChange(void); +CV_PossibleValue_t splitplayers_cons_t[] = {{1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}, {0, NULL}}; +consvar_t cv_splitplayers = CVAR_INIT ("splitplayers", "One", CV_CALL, splitplayers_cons_t, Splitplayers_OnChange); + +UINT16 nummenucolors = 0; + +// Character Select! +// @TODO: Splitscreen handling when profiles are added into the game. ...I probably won't be the one to handle this however. -Lat' + +struct setup_chargrid_s setup_chargrid[9][9]; +setup_player_t setup_player[MAXSPLITSCREENPLAYERS]; + +UINT8 setup_followercategories[MAXFOLLOWERCATEGORIES][2]; +UINT8 setup_numfollowercategories; + +UINT8 setup_numplayers = 0; // This variable is very important, it was extended to determine how many players exist in ALL menus. +tic_t setup_animcounter = 0; + +UINT8 setup_page = 0; +UINT8 setup_maxpage = 0; // For charsel page to identify alts easier... + +void M_AddMenuColor(UINT16 color) { + menucolor_t *c; + + if (color >= numskincolors) { + CONS_Printf("M_AddMenuColor: color %d does not exist.",color); + return; + } + + // SRB2Kart: I do not understand vanilla doesn't need this but WE do???!?!??! + if (!skincolors[color].accessible) { + return; + } + + c = (menucolor_t *)malloc(sizeof(menucolor_t)); + c->color = color; + if (menucolorhead == NULL) { + c->next = c; + c->prev = c; + menucolorhead = c; + menucolortail = c; + } else { + c->next = menucolorhead; + c->prev = menucolortail; + menucolortail->next = c; + menucolorhead->prev = c; + menucolortail = c; + } + + nummenucolors++; +} + +void M_MoveColorBefore(UINT16 color, UINT16 targ) { + menucolor_t *look, *c = NULL, *t = NULL; + + if (color == targ) + return; + if (color >= numskincolors) { + CONS_Printf("M_MoveColorBefore: color %d does not exist.",color); + return; + } + if (targ >= numskincolors) { + CONS_Printf("M_MoveColorBefore: target color %d does not exist.",targ); + return; + } + + for (look=menucolorhead;;look=look->next) { + if (look->color == color) + c = look; + else if (look->color == targ) + t = look; + if (c != NULL && t != NULL) + break; + if (look==menucolortail) + return; + } + + if (c == t->prev) + return; + + if (t==menucolorhead) + menucolorhead = c; + if (c==menucolortail) + menucolortail = c->prev; + + c->prev->next = c->next; + c->next->prev = c->prev; + + c->prev = t->prev; + c->next = t; + t->prev->next = c; + t->prev = c; +} + +void M_MoveColorAfter(UINT16 color, UINT16 targ) { + menucolor_t *look, *c = NULL, *t = NULL; + + if (color == targ) + return; + if (color >= numskincolors) { + CONS_Printf("M_MoveColorAfter: color %d does not exist.\n",color); + return; + } + if (targ >= numskincolors) { + CONS_Printf("M_MoveColorAfter: target color %d does not exist.\n",targ); + return; + } + + for (look=menucolorhead;;look=look->next) { + if (look->color == color) + c = look; + else if (look->color == targ) + t = look; + if (c != NULL && t != NULL) + break; + if (look==menucolortail) + return; + } + + if (t == c->prev) + return; + + if (t==menucolortail) + menucolortail = c; + else if (c==menucolortail) + menucolortail = c->prev; + + c->prev->next = c->next; + c->next->prev = c->prev; + + c->next = t->next; + c->prev = t; + t->next->prev = c; + t->next = c; +} + +UINT16 M_GetColorBefore(UINT16 color, UINT16 amount, boolean follower) +{ + menucolor_t *look = NULL; + + for (; amount > 0; amount--) + { + if (follower == true) + { + if (color == FOLLOWERCOLOR_OPPOSITE) + { + look = menucolortail; + color = menucolortail->color; + continue; + } + + if (color == FOLLOWERCOLOR_MATCH) + { + look = NULL; + color = FOLLOWERCOLOR_OPPOSITE; + continue; + } + + if (color == menucolorhead->color) + { + look = NULL; + color = FOLLOWERCOLOR_MATCH; + continue; + } + } + + if (color == 0 || color >= numskincolors) + { + CONS_Printf("M_GetColorBefore: color %d does not exist.\n",color); + return 0; + } + + if (look == NULL) + { + for (look = menucolorhead;; look = look->next) + { + if (look->color == color) + { + break; + } + if (look == menucolortail) + { + return 0; + } + } + } + + look = look->prev; + color = look->color; + } + return color; +} + +UINT16 M_GetColorAfter(UINT16 color, UINT16 amount, boolean follower) +{ + menucolor_t *look = NULL; + + for (; amount > 0; amount--) + { + if (follower == true) + { + if (color == menucolortail->color) + { + look = NULL; + color = FOLLOWERCOLOR_OPPOSITE; + continue; + } + + if (color == FOLLOWERCOLOR_OPPOSITE) + { + look = NULL; + color = FOLLOWERCOLOR_MATCH; + continue; + } + + if (color == FOLLOWERCOLOR_MATCH) + { + look = menucolorhead; + color = menucolorhead->color; + continue; + } + } + + if (color == 0 || color >= numskincolors) + { + CONS_Printf("M_GetColorAfter: color %d does not exist.\n",color); + return 0; + } + + if (look == NULL) + { + for (look = menucolorhead;; look = look->next) + { + if (look->color == color) + { + break; + } + if (look == menucolortail) + { + return 0; + } + } + } + + look = look->next; + color = look->color; + } + return color; +} + +void M_InitPlayerSetupColors(void) { + UINT8 i; + numskincolors = SKINCOLOR_FIRSTFREESLOT; + menucolorhead = menucolortail = NULL; + for (i=0; inext; + free(tmp); + } else { + free(look); + return; + } + } + + menucolorhead = menucolortail = NULL; +} + +// sets up the grid pos for the skin used by the profile. +static void M_SetupProfileGridPos(setup_player_t *p) +{ + profile_t *pr = PR_GetProfile(p->profilen); + INT32 i = R_SkinAvailable(pr->skinname); + INT32 alt = 0; // Hey it's my character's name! + + // While we're here, read follower values. + p->followern = K_FollowerAvailable(pr->follower); + + if (p->followern < 0 || p->followern >= numfollowers || followers[p->followern].category >= numfollowercategories || !K_FollowerUsable(p->followern)) + p->followercategory = p->followern = -1; + else + p->followercategory = followers[p->followern].category; + + p->followercolor = pr->followercolor; + + if (!R_SkinUsable(g_localplayers[0], i, false)) + { + i = GetSkinNumClosestToStats(skins[i].kartspeed, skins[i].kartweight, skins[i].flags, false); + } + + // Now position the grid for skin + p->gridx = skins[i].kartspeed-1; + p->gridy = skins[i].kartweight-1; + + // Now this put our cursor on the good alt + while (alt < setup_chargrid[p->gridx][p->gridy].numskins && setup_chargrid[p->gridx][p->gridy].skinlist[alt] != i) + alt++; + + p->clonenum = alt; + p->color = PR_GetProfileColor(pr); +} + +static void M_SetupMidGameGridPos(setup_player_t *p, UINT8 num) +{ + INT32 i = R_SkinAvailable(cv_skin[num].zstring); + INT32 alt = 0; // Hey it's my character's name! + + // While we're here, read follower values. + p->followern = cv_follower[num].value; + p->followercolor = cv_followercolor[num].value; + + if (p->followern < 0 || p->followern >= numfollowers || followers[p->followern].category >= numfollowercategories || !K_FollowerUsable(p->followern)) + p->followercategory = p->followern = -1; + else + p->followercategory = followers[p->followern].category; + + // Now position the grid for skin + p->gridx = skins[i].kartspeed-1; + p->gridy = skins[i].kartweight-1; + + // Now this put our cursor on the good alt + while (alt < setup_chargrid[p->gridx][p->gridy].numskins && setup_chargrid[p->gridx][p->gridy].skinlist[alt] != i) + alt++; + + p->clonenum = alt; + p->color = cv_playercolor[num].value; + return; // we're done here +} + + +void M_CharacterSelectInit(void) +{ + UINT8 i, j; + setup_maxpage = 0; + + // While we're editing profiles, don't unset the devices for p1 + if (gamestate == GS_MENU) + { + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + // Un-set devices for other players. + if (i != 0 || optionsmenu.profile) + { + CV_SetValue(&cv_usejoystick[i], -1); + CONS_Printf("M_CharacterSelectInit: Device for %d set to %d\n", i, -1); + } + } + } + + memset(setup_chargrid, -1, sizeof(setup_chargrid)); + for (i = 0; i < 9; i++) + { + for (j = 0; j < 9; j++) + setup_chargrid[i][j].numskins = 0; + } + + memset(setup_player, 0, sizeof(setup_player)); + setup_numplayers = 0; + + memset(setup_explosions, 0, sizeof(setup_explosions)); + setup_animcounter = 0; + + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + // Default to no follower / match colour. + setup_player[i].followern = -1; + setup_player[i].followercategory = -1; + setup_player[i].followercolor = FOLLOWERCOLOR_MATCH; + + // Set default selected profile to the last used profile for each player: + // (Make sure we don't overshoot it somehow if we deleted profiles or whatnot) + setup_player[i].profilen = min(cv_lastprofile[i].value, PR_GetNumProfiles()); + } + + for (i = 0; i < numskins; i++) + { + UINT8 x = skins[i].kartspeed-1; + UINT8 y = skins[i].kartweight-1; + + if (!R_SkinUsable(g_localplayers[0], i, false)) + continue; + + if (setup_chargrid[x][y].numskins >= MAXCLONES) + CONS_Alert(CONS_ERROR, "Max character alts reached for %d,%d\n", x+1, y+1); + else + { + setup_chargrid[x][y].skinlist[setup_chargrid[x][y].numskins] = i; + setup_chargrid[x][y].numskins++; + + setup_maxpage = max(setup_maxpage, setup_chargrid[x][y].numskins-1); + } + + for (j = 0; j < MAXSPLITSCREENPLAYERS; j++) + { + if (!strcmp(cv_skin[j].string, skins[i].name)) + { + setup_player[j].gridx = x; + setup_player[j].gridy = y; + setup_player[j].color = skins[i].prefcolor; + + // If we're on prpfile select, skip straight to CSSTEP_CHARS + // do the same if we're midgame, but make sure to consider splitscreen properly. + if ((optionsmenu.profile && j == 0) || (gamestate != GS_MENU && j <= splitscreen)) + { + if (optionsmenu.profile) // In menu, setting up profile character/follower + { + setup_player[j].profilen = optionsmenu.profilen; + PR_ApplyProfileLight(setup_player[j].profilen, 0); + M_SetupProfileGridPos(&setup_player[j]); + } + else // gamestate != GS_MENU, in that case, assume this is whatever profile we chose to play with. + { + setup_player[j].profilen = cv_lastprofile[j].value; + M_SetupMidGameGridPos(&setup_player[j], j); + } + + // Don't reapply the profile here, it was already applied. + setup_player[j].mdepth = CSSTEP_CHARS; + } + } + } + } + + setup_numfollowercategories = 0; + for (i = 0; i < numfollowercategories; i++) + { + if (followercategories[i].numincategory == 0) + continue; + + setup_followercategories[setup_numfollowercategories][0] = 0; + + for (j = 0; j < numfollowers; j++) + { + if (followers[j].category != i) + continue; + + if (!K_FollowerUsable(j)) + continue; + + setup_followercategories[setup_numfollowercategories][0]++; + setup_followercategories[setup_numfollowercategories][1] = i; + } + + if (!setup_followercategories[setup_numfollowercategories][0]) + continue; + + setup_numfollowercategories++; + } + + setup_page = 0; +} + +void M_CharacterSelect(INT32 choice) +{ + (void)choice; + PLAY_CharSelectDef.prevMenu = currentMenu; + M_SetupNextMenu(&PLAY_CharSelectDef, false); +} + + +// Gets the selected follower's state for a given setup player. +static void M_GetFollowerState(setup_player_t *p) +{ + + p->follower_state = &states[followers[p->followern].followstate]; + + if (p->follower_state->frame & FF_ANIMATE) + p->follower_tics = p->follower_state->var2; // support for FF_ANIMATE + else + p->follower_tics = p->follower_state->tics; + + p->follower_frame = p->follower_state->frame & FF_FRAMEMASK; +} + +static boolean M_DeviceAvailable(INT32 deviceID, UINT8 numPlayers) +{ + INT32 i; + + if (numPlayers == 0) + { + // All of them are available! + return true; + } + + for (i = 0; i < numPlayers; i++) + { + if (cv_usejoystick[i].value == deviceID) + { + // This one's already being used. + return false; + } + } + + // This device is good to go. + return true; +} + +static boolean M_HandlePressStart(setup_player_t *p, UINT8 num) +{ + INT32 i, j; + + if (optionsmenu.profile) + return false; // Don't allow for the possibility of SOMEHOW another player joining in. + + // Detect B press first ... this means P1 can actually exit out of the menu. + if (M_MenuBackPressed(num)) + { + M_SetMenuDelay(num); + + if (num == 0) + { + // We're done here. + memset(setup_player, 0, sizeof(setup_player)); // Reset this to avoid funky things with profile display. + M_GoBack(0); + return true; + } + + // Don't allow this press to ever count as "start". + return false; + } + + if (num != setup_numplayers) + { + // Only detect devices for the last player. + return false; + } + + // Now detect new devices trying to join. + for (i = 0; i < MAXDEVICES; i++) + { + if (deviceResponding[i] != true) + { + // No buttons are being pushed. + continue; + } + + if (M_DeviceAvailable(i, setup_numplayers) == true) + { + // Available!! Let's use this one!! + + // if P1 is setting up using keyboard (device 0), save their last used device. + // this is to allow them to retain controller usage when they play alone. + // Because let's face it, when you test mods, you're often lazy to grab your controller for menuing :) + if (!i && !num) + { + setup_player[num].ponedevice = cv_usejoystick[num].value; + } + else if (num) + { + // For any player past player 1, set controls to default profile controls, otherwise it's generally awful to do any menuing... + memcpy(&gamecontrol[num], gamecontroldefault, sizeof(gamecontroldefault)); + } + + + CV_SetValue(&cv_usejoystick[num], i); + CONS_Printf("M_HandlePressStart: Device for %d set to %d\n", num, i); + + for (j = num+1; j < MAXSPLITSCREENPLAYERS; j++) + { + // Un-set devices for other players. + CV_SetValue(&cv_usejoystick[j], -1); + CONS_Printf("M_HandlePressStart: Device for %d set to %d\n", j, -1); + } + + //setup_numplayers++; + p->mdepth = CSSTEP_PROFILE; + S_StartSound(NULL, sfx_s3k65); + + // Prevent quick presses for multiple players + for (j = 0; j < MAXSPLITSCREENPLAYERS; j++) + { + setup_player[j].delay = MENUDELAYTIME; + M_SetMenuDelay(j); + menucmd[j].buttonsHeld |= MBT_X; + } + + memset(deviceResponding, false, sizeof(deviceResponding)); + return true; + } + } + + return false; +} + +static boolean M_HandleCSelectProfile(setup_player_t *p, UINT8 num) +{ + const UINT8 maxp = PR_GetNumProfiles() -1; + UINT8 realnum = num; // Used for profile when using splitdevice. + UINT8 i; + + if (cv_splitdevice.value) + num = 0; + + if (menucmd[num].dpad_ud > 0) + { + p->profilen++; + if (p->profilen > maxp) + p->profilen = 0; + + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(num); + } + else if (menucmd[num].dpad_ud < 0) + { + if (p->profilen == 0) + p->profilen = maxp; + else + p->profilen--; + + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(num); + } + else if (M_MenuBackPressed(num)) + { + if (num == setup_numplayers-1) + { + + p->mdepth = CSSTEP_NONE; + S_StartSound(NULL, sfx_s3k5b); + + // Prevent quick presses for multiple players + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + setup_player[i].delay = MENUDELAYTIME; + M_SetMenuDelay(i); + menucmd[i].buttonsHeld |= MBT_X; + } + + if (num > 0) + { + CV_StealthSetValue(&cv_usejoystick[num], -1); + CONS_Printf("M_HandleCSelectProfile: Device for %d set to %d\n", num, -1); + } + + return true; + } + else + { + S_StartSound(NULL, sfx_s3kb2); + } + + M_SetMenuDelay(num); + } + else if (M_MenuConfirmPressed(num)) + { + SINT8 belongsTo = -1; + + if (p->profilen != PROFILE_GUEST) + { + for (i = 0; i < setup_numplayers; i++) + { + if (setup_player[i].mdepth > CSSTEP_PROFILE + && setup_player[i].profilen == p->profilen) + { + belongsTo = i; + break; + } + } + } + + if (belongsTo != -1 && belongsTo != num) + { + S_StartSound(NULL, sfx_s3k7b); + M_SetMenuDelay(num); + return false; + } + + // Apply the profile. + PR_ApplyProfile(p->profilen, realnum); // Otherwise P1 would inherit the last player's profile in splitdevice and that's not what we want... + M_SetupProfileGridPos(p); + + p->changeselect = 0; + + if (p->profilen == PROFILE_GUEST) + { + // Guest profile, always ask for options. + p->mdepth = CSSTEP_CHARS; + } + else + { + p->mdepth = CSSTEP_ASKCHANGES; + } + + S_StartSound(NULL, sfx_s3k63); + } + else if (M_MenuExtraPressed(num)) + { + UINT8 yourprofile = min(cv_lastprofile[realnum].value, PR_GetNumProfiles()); + if (p->profilen == yourprofile) + p->profilen = PROFILE_GUEST; + else + p->profilen = yourprofile; + S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s + M_SetMenuDelay(num); + } + + return false; + +} + + +static void M_HandleCharAskChange(setup_player_t *p, UINT8 num) +{ + + if (cv_splitdevice.value) + num = 0; + + // there's only 2 options so lol + if (menucmd[num].dpad_ud != 0) + { + p->changeselect = (p->changeselect == 0) ? 1 : 0; + + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(num); + } + else if (M_MenuBackPressed(num)) + { + p->changeselect = 0; + p->mdepth = CSSTEP_PROFILE; + + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(num); + } + else if (M_MenuConfirmPressed(num)) + { + if (!p->changeselect) + { + // no changes + M_GetFollowerState(p); + p->mdepth = CSSTEP_READY; + p->delay = TICRATE; + + S_StartSound(NULL, sfx_s3k4e); + M_SetupReadyExplosions(true, p->gridx, p->gridy, p->color); + } + else + { + // changes + p->mdepth = CSSTEP_CHARS; + S_StartSound(NULL, sfx_s3k63); + } + + M_SetMenuDelay(num); + } +} + +static boolean M_HandleCharacterGrid(setup_player_t *p, UINT8 num) +{ + UINT8 numclones; + INT32 skin; + + if (cv_splitdevice.value) + num = 0; + + if (menucmd[num].dpad_ud > 0) + { + p->gridy++; + if (p->gridy > 8) + p->gridy = 0; + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(num); + } + else if (menucmd[num].dpad_ud < 0) + { + p->gridy--; + if (p->gridy < 0) + p->gridy = 8; + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(num); + } + + if (menucmd[num].dpad_lr > 0) + { + p->gridx++; + if (p->gridx > 8) + p->gridx = 0; + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(num); + } + else if (menucmd[num].dpad_lr < 0) + { + p->gridx--; + if (p->gridx < 0) + p->gridx = 8; + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(num); + } + else if (M_MenuExtraPressed(num)) + { + p->gridx /= 3; + p->gridx = (3*p->gridx) + 1; + p->gridy /= 3; + p->gridy = (3*p->gridy) + 1; + S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s + M_SetMenuDelay(num); + } + + // try to set the clone num to the page # if possible. + p->clonenum = setup_page; + + // Process this after possible pad movement, + // this makes sure we don't have a weird ghost hover on a character with no clones. + numclones = setup_chargrid[p->gridx][p->gridy].numskins; + + if (p->clonenum >= numclones) + p->clonenum = 0; + + if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/) + { + skin = setup_chargrid[p->gridx][p->gridy].skinlist[setup_page]; + if (setup_page >= setup_chargrid[p->gridx][p->gridy].numskins || skin == -1) + { + S_StartSound(NULL, sfx_s3k7b); //sfx_s3kb2 + } + else + { + if (setup_page+1 == setup_chargrid[p->gridx][p->gridy].numskins) + p->mdepth = CSSTEP_COLORS; // Skip clones menu if there are none on this page. + else + p->mdepth = CSSTEP_ALTS; + + S_StartSound(NULL, sfx_s3k63); + } + + M_SetMenuDelay(num); + } + else if (M_MenuBackPressed(num)) + { + // for profiles / gameplay, exit out of the menu instantly, + // we don't want to go to the input detection menu. + if (optionsmenu.profile || gamestate != GS_MENU) + { + memset(setup_player, 0, sizeof(setup_player)); // Reset setup_player otherwise it does some VERY funky things. + M_SetMenuDelay(0); + M_GoBack(0); + return true; + } + else // in main menu + { + p->mdepth = CSSTEP_PROFILE; + S_StartSound(NULL, sfx_s3k5b); + } + M_SetMenuDelay(num); + } + + if (num == 0 && setup_numplayers == 1 && setup_maxpage) // ONLY one player. + { + if (M_MenuButtonPressed(num, MBT_L)) + { + if (setup_page == 0) + setup_page = setup_maxpage; + else + setup_page--; + + S_StartSound(NULL, sfx_s3k63); + M_SetMenuDelay(num); + } + else if (M_MenuButtonPressed(num, MBT_R)) + { + if (setup_page == setup_maxpage) + setup_page = 0; + else + setup_page++; + + S_StartSound(NULL, sfx_s3k63); + M_SetMenuDelay(num); + } + } + + return false; +} + +static void M_HandleCharRotate(setup_player_t *p, UINT8 num) +{ + UINT8 numclones = setup_chargrid[p->gridx][p->gridy].numskins; + + if (cv_splitdevice.value) + num = 0; + + if (menucmd[num].dpad_lr > 0) + { + p->clonenum++; + if (p->clonenum >= numclones) + p->clonenum = 0; + p->rotate = CSROTATETICS; + p->delay = CSROTATETICS; + S_StartSound(NULL, sfx_s3kc3s); + } + else if (menucmd[num].dpad_lr < 0) + { + p->clonenum--; + if (p->clonenum < 0) + p->clonenum = numclones-1; + p->rotate = -CSROTATETICS; + p->delay = CSROTATETICS; + S_StartSound(NULL, sfx_s3kc3s); + } + + if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/) + { + p->mdepth = CSSTEP_COLORS; + S_StartSound(NULL, sfx_s3k63); + M_SetMenuDelay(num); + } + else if (M_MenuBackPressed(num)) + { + p->mdepth = CSSTEP_CHARS; + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(num); + } + else if (M_MenuExtraPressed(num)) + { + p->clonenum = 0; + p->rotate = CSROTATETICS; + p->hitlag = true; + S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s + M_SetMenuDelay(num); + } +} + +static void M_HandleColorRotate(setup_player_t *p, UINT8 num) +{ + if (cv_splitdevice.value) + num = 0; + + if (menucmd[num].dpad_lr > 0) + { + p->color = M_GetColorAfter(p->color, 1, false); + p->rotate = CSROTATETICS; + M_SetMenuDelay(num); //CSROTATETICS + S_StartSound(NULL, sfx_s3k5b); //sfx_s3kc3s + } + else if (menucmd[num].dpad_lr < 0) + { + p->color = M_GetColorBefore(p->color, 1, false); + p->rotate = -CSROTATETICS; + M_SetMenuDelay(num); //CSROTATETICS + S_StartSound(NULL, sfx_s3k5b); //sfx_s3kc3s + } + + if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/) + { + p->mdepth = CSSTEP_FOLLOWERCATEGORY; + S_StartSound(NULL, sfx_s3k63); + M_SetMenuDelay(num); + } + else if (M_MenuBackPressed(num)) + { + if (setup_chargrid[p->gridx][p->gridy].numskins == 1) + { + p->mdepth = CSSTEP_CHARS; // Skip clones menu + } + else + { + p->mdepth = CSSTEP_ALTS; + } + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(num); + } + else if (M_MenuExtraPressed(num)) + { + if (p->skin >= 0) + { + p->color = skins[p->skin].prefcolor; + p->rotate = CSROTATETICS; + p->hitlag = true; + S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s + M_SetMenuDelay(num); + } + } +} + +static void M_AnimateFollower(setup_player_t *p) +{ + if (--p->follower_tics <= 0) + { + + // FF_ANIMATE; cycle through FRAMES and get back afterwards. This will be prominent amongst followers hence why it's being supported here. + if (p->follower_state->frame & FF_ANIMATE) + { + p->follower_frame++; + p->follower_tics = p->follower_state->var2; + if (p->follower_frame > (p->follower_state->frame & FF_FRAMEMASK) + p->follower_state->var1) // that's how it works, right? + p->follower_frame = p->follower_state->frame & FF_FRAMEMASK; + } + else + { + if (p->follower_state->nextstate != S_NULL) + p->follower_state = &states[p->follower_state->nextstate]; + p->follower_tics = p->follower_state->tics; + /*if (p->follower_tics == -1) + p->follower_tics = 15; // er, what?*/ + // get spritedef: + p->follower_frame = p->follower_state->frame & FF_FRAMEMASK; + } + } + + p->follower_timer++; +} + +static void M_HandleFollowerCategoryRotate(setup_player_t *p, UINT8 num) +{ + if (cv_splitdevice.value) + num = 0; + + if (menucmd[num].dpad_lr > 0) + { + p->followercategory++; + if (p->followercategory >= setup_numfollowercategories) + p->followercategory = -1; + + p->rotate = CSROTATETICS; + p->delay = CSROTATETICS; + S_StartSound(NULL, sfx_s3kc3s); + } + else if (menucmd[num].dpad_lr < 0) + { + p->followercategory--; + if (p->followercategory < -1) + p->followercategory = setup_numfollowercategories-1; + + p->rotate = -CSROTATETICS; + p->delay = CSROTATETICS; + S_StartSound(NULL, sfx_s3kc3s); + } + + if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/) + { + if (p->followercategory < 0) + { + p->followern = -1; + p->mdepth = CSSTEP_READY; + p->delay = TICRATE; + M_SetupReadyExplosions(true, p->gridx, p->gridy, p->color); + S_StartSound(NULL, sfx_s3k4e); + } + else + { + if (p->followern < 0 || followers[p->followern].category != p->followercategory) + { + p->followern = 0; + while (p->followern < numfollowers + && (followers[p->followern].category != setup_followercategories[p->followercategory][1] + || !K_FollowerUsable(p->followern))) + p->followern++; + } + + if (p->followern >= numfollowers) + { + p->followern = -1; + S_StartSound(NULL, sfx_s3kb2); + } + else + { + M_GetFollowerState(p); + p->mdepth = CSSTEP_FOLLOWER; + S_StartSound(NULL, sfx_s3k63); + } + } + + M_SetMenuDelay(num); + } + else if (M_MenuBackPressed(num)) + { + p->mdepth = CSSTEP_COLORS; + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(num); + } + else if (M_MenuExtraPressed(num)) + { + if (p->followercategory >= 0 || p->followern < 0 || p->followern >= numfollowers || followers[p->followern].category >= numfollowercategories) + p->followercategory = -1; + else + p->followercategory = followers[p->followern].category; + p->rotate = CSROTATETICS; + p->hitlag = true; + S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s + M_SetMenuDelay(num); + } +} + +static void M_HandleFollowerRotate(setup_player_t *p, UINT8 num) +{ + INT16 startfollowern = p->followern; + + if (cv_splitdevice.value) + num = 0; + + if (menucmd[num].dpad_lr > 0) + { + do + { + p->followern++; + if (p->followern >= numfollowers) + p->followern = 0; + if (p->followern == startfollowern) + break; + } + while (followers[p->followern].category != setup_followercategories[p->followercategory][1] || !K_FollowerUsable(p->followern)); + + M_GetFollowerState(p); + + p->rotate = CSROTATETICS; + p->delay = CSROTATETICS; + S_StartSound(NULL, sfx_s3kc3s); + } + else if (menucmd[num].dpad_lr < 0) + { + do + { + p->followern--; + if (p->followern < 0) + p->followern = numfollowers-1; + if (p->followern == startfollowern) + break; + } + while (followers[p->followern].category != setup_followercategories[p->followercategory][1] || !K_FollowerUsable(p->followern)); + + M_GetFollowerState(p); + + p->rotate = -CSROTATETICS; + p->delay = CSROTATETICS; + S_StartSound(NULL, sfx_s3kc3s); + } + + if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/) + { + if (p->followern > -1) + { + p->mdepth = CSSTEP_FOLLOWERCOLORS; + S_StartSound(NULL, sfx_s3k63); + } + else + { + p->mdepth = CSSTEP_READY; + p->delay = TICRATE; + M_SetupReadyExplosions(true, p->gridx, p->gridy, p->color); + S_StartSound(NULL, sfx_s3k4e); + } + + M_SetMenuDelay(num); + } + else if (M_MenuBackPressed(num)) + { + p->mdepth = CSSTEP_FOLLOWERCATEGORY; + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(num); + } + else if (M_MenuExtraPressed(num)) + { + p->mdepth = CSSTEP_FOLLOWERCATEGORY; + p->followercategory = -1; + p->rotate = CSROTATETICS; + p->hitlag = true; + S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s + M_SetMenuDelay(num); + } +} + +static void M_HandleFollowerColorRotate(setup_player_t *p, UINT8 num) +{ + if (cv_splitdevice.value) + num = 0; + + M_AnimateFollower(p); + + if (menucmd[num].dpad_lr > 0) + { + p->followercolor = M_GetColorAfter(p->followercolor, 1, true); + p->rotate = CSROTATETICS; + M_SetMenuDelay(num); //CSROTATETICS + S_StartSound(NULL, sfx_s3k5b); //sfx_s3kc3s + } + else if (menucmd[num].dpad_lr < 0) + { + p->followercolor = M_GetColorBefore(p->followercolor, 1, true); + p->rotate = -CSROTATETICS; + M_SetMenuDelay(num); //CSROTATETICS + S_StartSound(NULL, sfx_s3k5b); //sfx_s3kc3s + } + + if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/) + { + p->mdepth = CSSTEP_READY; + p->delay = TICRATE; + M_SetupReadyExplosions(true, p->gridx, p->gridy, p->color); + S_StartSound(NULL, sfx_s3k4e); + M_SetMenuDelay(num); + } + else if (M_MenuBackPressed(num)) + { + M_GetFollowerState(p); + p->mdepth = CSSTEP_FOLLOWER; + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(num); + } + else if (M_MenuExtraPressed(num)) + { + if (p->followercolor == FOLLOWERCOLOR_MATCH) + p->followercolor = FOLLOWERCOLOR_OPPOSITE; + else if (p->followercolor == followers[p->followern].defaultcolor) + p->followercolor = FOLLOWERCOLOR_MATCH; + else + p->followercolor = followers[p->followern].defaultcolor; + p->rotate = CSROTATETICS; + p->hitlag = true; + S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s + M_SetMenuDelay(num); + } +} + +boolean M_CharacterSelectHandler(INT32 choice) +{ + INT32 i; + + (void)choice; + + for (i = MAXSPLITSCREENPLAYERS-1; i >= 0; i--) + { + setup_player_t *p = &setup_player[i]; + boolean playersChanged = false; + + if (p->delay == 0 && menucmd[i].delay == 0) + { + if (!optionsmenu.profile) + { + // If splitdevice is true, only do the last non-ready setups. + if (cv_splitdevice.value) + { + // Previous setup isn't ready, go there. + // In any case, do setup 0 first. + if (i > 0 && setup_player[i-1].mdepth < CSSTEP_READY) + continue; + } + } + + switch (p->mdepth) + { + case CSSTEP_NONE: // Enter Game + if (gamestate == GS_MENU) // do NOT handle that outside of GS_MENU. + playersChanged = M_HandlePressStart(p, i); + break; + case CSSTEP_PROFILE: + playersChanged = M_HandleCSelectProfile(p, i); + break; + case CSSTEP_ASKCHANGES: + M_HandleCharAskChange(p, i); + break; + case CSSTEP_CHARS: // Character Select grid + M_HandleCharacterGrid(p, i); + break; + case CSSTEP_ALTS: // Select clone + M_HandleCharRotate(p, i); + break; + case CSSTEP_COLORS: // Select color + M_HandleColorRotate(p, i); + break; + case CSSTEP_FOLLOWERCATEGORY: + M_HandleFollowerCategoryRotate(p, i); + break; + case CSSTEP_FOLLOWER: + M_HandleFollowerRotate(p, i); + break; + case CSSTEP_FOLLOWERCOLORS: + M_HandleFollowerColorRotate(p, i); + break; + case CSSTEP_READY: + default: // Unready + if (M_MenuBackPressed(i)) + { + p->mdepth = CSSTEP_COLORS; + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(i); + } + break; + } + } + + // Just makes it easier to access later + p->skin = setup_chargrid[p->gridx][p->gridy].skinlist[p->clonenum]; + + // Keep profile colour. + /*if (p->mdepth < CSSTEP_COLORS) + { + p->color = skins[p->skin].prefcolor; + + }*/ + + if (playersChanged == true) + { + setup_page = 0; // reset that. + break; + } + } + + // Setup new numplayers + setup_numplayers = 0; + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + if (setup_player[i].mdepth == CSSTEP_NONE) + break; + + setup_numplayers = i+1; + } + + return true; +} + +// Apply character skin and colour changes while ingame (we just call the skin / color commands.) +// ...Will this cause command buffer issues? -Lat' +static void M_MPConfirmCharacterSelection(void) +{ + UINT8 i; + INT16 col; + + for (i = 0; i < splitscreen +1; i++) + { + // colour + // (convert the number that's saved to a string we can use) + col = setup_player[i].color; + CV_StealthSetValue(&cv_playercolor[i], col); + + // follower + if (setup_player[i].followern < 0) + CV_StealthSet(&cv_follower[i], "None"); + else + CV_StealthSet(&cv_follower[i], followers[setup_player[i].followern].name); + + // finally, call the skin[x] console command. + // This will call SendNameAndColor which will synch everything we sent here and apply the changes! + + CV_StealthSet(&cv_skin[i], skins[setup_player[i].skin].name); + + // ...actually, let's do this last - Skin_OnChange has some return-early occasions + // follower color + CV_SetValue(&cv_followercolor[i], setup_player[i].followercolor); + + } + M_ClearMenus(true); +} + +void M_CharacterSelectTick(void) +{ + UINT8 i; + boolean setupnext = true; + + setup_animcounter++; + + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + if (setup_player[i].delay) + setup_player[i].delay--; + + if (setup_player[i].rotate > 0) + setup_player[i].rotate--; + else if (setup_player[i].rotate < 0) + setup_player[i].rotate++; + else + setup_player[i].hitlag = false; + + if (i >= setup_numplayers) + continue; + + if (setup_player[i].mdepth < CSSTEP_READY || setup_player[i].delay > 0) + { + // Someone's not ready yet. + setupnext = false; + } + } + + for (i = 0; i < CSEXPLOSIONS; i++) + { + if (setup_explosions[i].tics > 0) + setup_explosions[i].tics--; + } + + if (setupnext && setup_numplayers > 0) + { + // Selecting from the menu + if (gamestate == GS_MENU) + { + // in a profile; update the selected profile and then go back to the profile menu. + if (optionsmenu.profile) + { + // save player + strcpy(optionsmenu.profile->skinname, skins[setup_player[0].skin].name); + optionsmenu.profile->color = setup_player[0].color; + + // save follower + strcpy(optionsmenu.profile->follower, followers[setup_player[0].followern].name); + optionsmenu.profile->followercolor = setup_player[0].followercolor; + + // reset setup_player + memset(setup_player, 0, sizeof(setup_player)); + setup_numplayers = 0; + + M_GoBack(0); + return; + } + else // in a normal menu, stealthset the cvars and then go to the play menu. + { + for (i = 0; i < setup_numplayers; i++) + { + CV_StealthSet(&cv_skin[i], skins[setup_player[i].skin].name); + CV_StealthSetValue(&cv_playercolor[i], setup_player[i].color); + + if (setup_player[i].followern < 0) + CV_StealthSet(&cv_follower[i], "None"); + else + CV_StealthSet(&cv_follower[i], followers[setup_player[i].followern].name); + CV_StealthSetValue(&cv_followercolor[i], setup_player[i].followercolor); + } + + CV_StealthSetValue(&cv_splitplayers, setup_numplayers); + + // P1 is alone, set their old device just in case. + if (setup_numplayers < 2 && setup_player[0].ponedevice) + { + CV_StealthSetValue(&cv_usejoystick[0], setup_player[0].ponedevice); + } + + M_SetupNextMenu(&PLAY_MainDef, false); + } + } + else // In a game + { + // 23/05/2022: Since there's already restrictskinchange, just allow this to happen regardless. + M_MPConfirmCharacterSelection(); + } + } +} + +boolean M_CharacterSelectQuit(void) +{ + return true; +} + +static void Splitplayers_OnChange(void) +{ +#if 0 + if (cv_splitplayers.value < setupm_pselect) + setupm_pselect = 1; +#endif +} diff --git a/src/menus/play-local-1.c b/src/menus/play-local-1.c index 6267f91b6..bea8a1686 100644 --- a/src/menus/play-local-1.c +++ b/src/menus/play-local-1.c @@ -2,6 +2,7 @@ /// \brief Local Play, gamemode selection menu #include "../k_menu.h" +#include "../m_cond.h" // Condition Sets menuitem_t PLAY_GamemodesMenu[] = { @@ -21,3 +22,48 @@ menuitem_t PLAY_GamemodesMenu[] = }; menu_t PLAY_GamemodesDef = KARTGAMEMODEMENU(PLAY_GamemodesMenu, &PLAY_MainDef); + +void M_SetupGametypeMenu(INT32 choice) +{ + (void)choice; + + PLAY_GamemodesDef.prevMenu = currentMenu; + + // Battle and Capsules (and Special) disabled + PLAY_GamemodesMenu[1].status = IT_DISABLED; + PLAY_GamemodesMenu[2].status = IT_DISABLED; + PLAY_GamemodesMenu[3].status = IT_DISABLED; + + if (cv_splitplayers.value > 1) + { + // Re-add Battle + PLAY_GamemodesMenu[1].status = IT_STRING | IT_CALL; + } + else + { + boolean anyunlocked = false; + + if (M_SecretUnlocked(SECRET_BREAKTHECAPSULES, true)) + { + // Re-add Capsules + PLAY_GamemodesMenu[2].status = IT_STRING | IT_CALL; + anyunlocked = true; + } + + if (M_SecretUnlocked(SECRET_SPECIALATTACK, true)) + { + // Re-add Special + PLAY_GamemodesMenu[3].status = IT_STRING | IT_CALL; + anyunlocked = true; + } + + if (!anyunlocked) + { + // Only one non-Back entry, let's skip straight to Race. + M_SetupRaceMenu(-1); + return; + } + } + + M_SetupNextMenu(&PLAY_GamemodesDef, false); +} diff --git a/src/menus/play-local-race-1.c b/src/menus/play-local-race-1.c index 84faa4a8f..92a092db6 100644 --- a/src/menus/play-local-race-1.c +++ b/src/menus/play-local-race-1.c @@ -2,6 +2,7 @@ /// \brief Race Mode Menu #include "../k_menu.h" +#include "../m_cond.h" // Condition Sets menuitem_t PLAY_RaceGamemodesMenu[] = { @@ -18,3 +19,22 @@ menuitem_t PLAY_RaceGamemodesMenu[] = }; menu_t PLAY_RaceGamemodesDef = KARTGAMEMODEMENU(PLAY_RaceGamemodesMenu, &PLAY_GamemodesDef); + +void M_SetupRaceMenu(INT32 choice) +{ + (void)choice; + + PLAY_RaceGamemodesDef.prevMenu = currentMenu; + + // Time Attack disabled + PLAY_RaceGamemodesMenu[2].status = IT_DISABLED; + + // Time Attack is 1P only + if (cv_splitplayers.value <= 1 + && M_SecretUnlocked(SECRET_TIMEATTACK, true)) + { + PLAY_RaceGamemodesMenu[2].status = IT_STRING | IT_CALL; + } + + M_SetupNextMenu(&PLAY_RaceGamemodesDef, false); +} diff --git a/src/menus/play-local-race-difficulty.c b/src/menus/play-local-race-difficulty.c index a55ede90b..49dec06cb 100644 --- a/src/menus/play-local-race-difficulty.c +++ b/src/menus/play-local-race-difficulty.c @@ -2,6 +2,7 @@ /// \brief difficulty selection -- see drace_e #include "../k_menu.h" +#include "../m_cond.h" // Condition Sets menuitem_t PLAY_RaceDifficulty[] = { @@ -45,3 +46,65 @@ menu_t PLAY_RaceDifficultyDef = { NULL, NULL }; + +consvar_t cv_dummygpdifficulty = CVAR_INIT ("dummygpdifficulty", "Normal", CV_HIDDEN, gpdifficulty_cons_t, NULL); +consvar_t cv_dummykartspeed = CVAR_INIT ("dummykartspeed", "Normal", CV_HIDDEN, dummykartspeed_cons_t, NULL); +consvar_t cv_dummygpencore = CVAR_INIT ("dummygpencore", "Off", CV_HIDDEN, CV_OnOff, NULL); + +static CV_PossibleValue_t dummymatchbots_cons_t[] = { + {0, "Off"}, + {1, "Lv.1"}, + {2, "Lv.2"}, + {3, "Lv.3"}, + {4, "Lv.4"}, + {5, "Lv.5"}, + {6, "Lv.6"}, + {7, "Lv.7"}, + {8, "Lv.8"}, + {9, "Lv.9"}, + {10, "Lv.10"}, + {11, "Lv.11"}, + {12, "Lv.12"}, + {13, "Lv.MAX"}, + {0, NULL} +}; +consvar_t cv_dummymatchbots = CVAR_INIT ("dummymatchbots", "Off", CV_HIDDEN, dummymatchbots_cons_t, NULL); + +void M_SetupDifficultySelect(INT32 choice) +{ + // check what we picked. + choice = currentMenu->menuitems[itemOn].mvar1; + + // setup the difficulty menu and then remove choices depending on choice + PLAY_RaceDifficultyDef.prevMenu = currentMenu; + + PLAY_RaceDifficulty[drace_gpdifficulty].status = IT_DISABLED; + PLAY_RaceDifficulty[drace_mrkartspeed].status = IT_DISABLED; + PLAY_RaceDifficulty[drace_mrcpu].status = IT_DISABLED; + PLAY_RaceDifficulty[drace_mrracers].status = IT_DISABLED; + PLAY_RaceDifficulty[drace_encore].status = IT_DISABLED; + PLAY_RaceDifficulty[drace_cupselect].status = IT_DISABLED; + PLAY_RaceDifficulty[drace_mapselect].status = IT_DISABLED; + + if (choice) // Match Race + { + PLAY_RaceDifficulty[drace_mrkartspeed].status = IT_STRING|IT_CVAR; // Kart Speed + PLAY_RaceDifficulty[drace_mrcpu].status = IT_STRING2|IT_CVAR; // CPUs on/off + PLAY_RaceDifficulty[drace_mrracers].status = IT_STRING2|IT_CVAR; // CPU amount + PLAY_RaceDifficulty[drace_mapselect].status = IT_STRING|IT_CALL; // Level Select (Match Race) + PLAY_RaceDifficultyDef.lastOn = drace_mapselect; // Select map select by default. + } + else // GP + { + PLAY_RaceDifficulty[drace_gpdifficulty].status = IT_STRING|IT_CVAR; // Difficulty + PLAY_RaceDifficulty[drace_cupselect].status = IT_STRING|IT_CALL; // Level Select (GP) + PLAY_RaceDifficultyDef.lastOn = drace_cupselect; // Select cup select by default. + } + + if (M_SecretUnlocked(SECRET_ENCORE, false)) + { + PLAY_RaceDifficulty[drace_encore].status = IT_STRING2|IT_CVAR; // Encore on/off + } + + M_SetupNextMenu(&PLAY_RaceDifficultyDef, false); +} diff --git a/src/menus/play-local-race-time-attack.c b/src/menus/play-local-race-time-attack.c index 488a1b42d..6ed559773 100644 --- a/src/menus/play-local-race-time-attack.c +++ b/src/menus/play-local-race-time-attack.c @@ -2,6 +2,12 @@ /// \brief Race Time Attack Menu #include "../k_menu.h" +#include "../r_local.h" // SplitScreen_OnChange +#include "../s_sound.h" +#include "../f_finale.h" // F_WipeStartScreen +#include "../v_video.h" +#include "../d_main.h" // srb2home +#include "../m_misc.h" // M_MkdirEach // see ta_e menuitem_t PLAY_TimeAttack[] = @@ -114,3 +120,91 @@ menu_t PLAY_TAGhostsDef = { NULL, NULL }; + +// autorecord demos for time attack +consvar_t cv_autorecord = CVAR_INIT ("autorecord", "Yes", 0, CV_YesNo, NULL); + +CV_PossibleValue_t ghost_cons_t[] = {{0, "Hide"}, {1, "Show Character"}, {2, "Show All"}, {0, NULL}}; +CV_PossibleValue_t ghost2_cons_t[] = {{0, "Hide"}, {1, "Show"}, {0, NULL}}; + +consvar_t cv_ghost_besttime = CVAR_INIT ("ghost_besttime", "Show All", CV_SAVE, ghost_cons_t, NULL); +consvar_t cv_ghost_bestlap = CVAR_INIT ("ghost_bestlap", "Show All", CV_SAVE, ghost_cons_t, NULL); +consvar_t cv_ghost_last = CVAR_INIT ("ghost_last", "Show All", CV_SAVE, ghost_cons_t, NULL); +consvar_t cv_ghost_guest = CVAR_INIT ("ghost_guest", "Show", CV_SAVE, ghost2_cons_t, NULL); +consvar_t cv_ghost_staff = CVAR_INIT ("ghost_staff", "Show", CV_SAVE, ghost2_cons_t, NULL); + +// time attack stuff... +void M_HandleStaffReplay(INT32 choice) +{ + // @TODO: + (void) choice; +} + +void M_ReplayTimeAttack(INT32 choice) +{ + // @TODO: + (void) choice; +} + +void M_SetGuestReplay(INT32 choice) +{ + // @TODO: + (void) choice; +} + +void M_StartTimeAttack(INT32 choice) +{ + char *gpath; + char nameofdemo[256]; + + (void)choice; + + modeattacking = ATTACKING_TIME; + + if ((gametypes[levellist.newgametype]->rules & GTR_CIRCUIT) + && (mapheaderinfo[levellist.choosemap]->numlaps != 1)) + { + modeattacking |= ATTACKING_LAP; + } + + // Still need to reset devmode + cht_debug = 0; + emeralds = 0; + + if (demo.playback) + G_StopDemo(); + if (metalrecording) + G_StopMetalDemo(); + + splitscreen = 0; + SplitScreen_OnChange(); + + S_StartSound(NULL, sfx_s3k63); + + paused = false; + + // Early fadeout to let the sound finish playing + F_WipeStartScreen(); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + F_WipeEndScreen(); + F_RunWipe(wipedefs[wipe_level_toblack], false, "FADEMAP0", false, false); + + SV_StartSinglePlayerServer(levellist.newgametype, false); + + gpath = va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s", + srb2home, timeattackfolder); + M_MkdirEach(gpath, M_PathParts(gpath) - 3, 0755); + + strcat(gpath, PATHSEP); + strcat(gpath, G_BuildMapName(levellist.choosemap+1)); + + snprintf(nameofdemo, sizeof nameofdemo, "%s-%s-last", gpath, cv_skin[0].string); + + if (!cv_autorecord.value) + remove(va("%s"PATHSEP"%s.lmp", srb2home, nameofdemo)); + else + G_RecordDemo(nameofdemo); + + M_ClearMenus(true); + D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_dummygpencore.value == 1), 1, 1, false, false); +} diff --git a/src/menus/play-online-1.c b/src/menus/play-online-1.c index 18c8c0568..32ab3ca27 100644 --- a/src/menus/play-online-1.c +++ b/src/menus/play-online-1.c @@ -30,3 +30,55 @@ menu_t PLAY_MP_OptSelectDef = { NULL, NULL }; + +struct mpmenu_s mpmenu; + +// Use this as a quit routine within the HOST GAME and JOIN BY IP "sub" menus +boolean M_MPResetOpts(void) +{ + UINT8 i = 0; + + for (; i < 3; i++) + mpmenu.modewinextend[i][0] = 0; // Undo this + + return true; +} + +void M_MPOptSelectInit(INT32 choice) +{ + INT16 arrcpy[3][3] = {{0,68,0}, {0,12,0}, {0,74,0}}; + UINT8 i = 0, j = 0; // To copy the array into the struct + const UINT32 forbidden = GTR_FORBIDMP; + + (void)choice; + + mpmenu.modechoice = 0; + mpmenu.ticker = 0; + + for (; i < 3; i++) + for (j = 0; j < 3; j++) + mpmenu.modewinextend[i][j] = arrcpy[i][j]; // I miss Lua already + + // Guarantee menugametype is good + M_NextMenuGametype(forbidden); + M_PrevMenuGametype(forbidden); + + M_SetupNextMenu(&PLAY_MP_OptSelectDef, false); +} + +void M_MPOptSelectTick(void) +{ + UINT8 i = 0; + + // 3 Because we have 3 options in the menu + for (; i < 3; i++) + { + if (mpmenu.modewinextend[i][0]) + mpmenu.modewinextend[i][2] += 8; + else + mpmenu.modewinextend[i][2] -= 8; + + mpmenu.modewinextend[i][2] = min(mpmenu.modewinextend[i][1], max(0, mpmenu.modewinextend[i][2])); + //CONS_Printf("%d - %d,%d,%d\n", i, mpmenu.modewinextend[i][0], mpmenu.modewinextend[i][1], mpmenu.modewinextend[i][2]); + } +} diff --git a/src/menus/play-online-host.c b/src/menus/play-online-host.c index 0a0faea74..8e6a2bdd8 100644 --- a/src/menus/play-online-host.c +++ b/src/menus/play-online-host.c @@ -2,6 +2,7 @@ /// \brief MULTIPLAYER HOST SCREEN -- see mhost_e #include "../k_menu.h" +#include "../s_sound.h" // MULTIPLAYER HOST SCREEN -- see mhost_e menuitem_t PLAY_MP_Host[] = @@ -39,3 +40,73 @@ menu_t PLAY_MP_HostDef = { M_MPResetOpts, NULL }; + +void M_MPHostInit(INT32 choice) +{ + + (void)choice; + mpmenu.modewinextend[0][0] = 1; + M_SetupNextMenu(&PLAY_MP_HostDef, true); + itemOn = mhost_go; +} + +void M_HandleHostMenuGametype(INT32 choice) +{ + const UINT8 pid = 0; + const UINT32 forbidden = GTR_FORBIDMP; + + (void)choice; + + if (M_MenuBackPressed(pid)) + { + M_GoBack(0); + M_SetMenuDelay(pid); + return; + } + else if (menucmd[pid].dpad_lr > 0 || M_MenuConfirmPressed(pid)) + { + M_NextMenuGametype(forbidden); + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + else if (menucmd[pid].dpad_lr < 0) + { + M_PrevMenuGametype(forbidden); + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + + if (menucmd[pid].dpad_ud > 0) + { + M_NextOpt(); + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + else if (menucmd[pid].dpad_ud < 0) + { + M_PrevOpt(); + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } +} + +void M_MPSetupNetgameMapSelect(INT32 choice) +{ + (void)choice; + + // Yep, we'll be starting a netgame. + levellist.netgame = true; + // Make sure we reset those + levellist.levelsearch.timeattack = false; + levellist.levelsearch.checklocked = true; + cupgrid.grandprix = false; + + // okay this is REALLY stupid but this fixes the host menu re-folding on itself when we go back. + mpmenu.modewinextend[0][0] = 1; + + if (!M_LevelListFromGametype(menugametype)) + { + S_StartSound(NULL, sfx_s3kb2); + M_StartMessage(va("No levels available for\n%s Mode!\n\nPress (B)\n", gametypes[menugametype]->name), NULL, MM_NOTHING); + } +} diff --git a/src/menus/play-online-join-ip.c b/src/menus/play-online-join-ip.c index 398756eb9..ee084e2e6 100644 --- a/src/menus/play-online-join-ip.c +++ b/src/menus/play-online-join-ip.c @@ -2,6 +2,10 @@ /// \brief MULTIPLAYER JOIN BY IP #include "../k_menu.h" +#include "../v_video.h" +#include "../i_system.h" // I_OsPolling +#include "../i_video.h" // I_UpdateNoBlit +#include "../m_misc.h" // NUMLOGIP menuitem_t PLAY_MP_JoinIP[] = { @@ -41,3 +45,66 @@ menu_t PLAY_MP_JoinIPDef = { M_MPResetOpts, M_JoinIPInputs }; + +consvar_t cv_dummyip = CVAR_INIT ("dummyip", "", CV_HIDDEN, NULL, NULL); + +void M_MPJoinIPInit(INT32 choice) +{ + + (void)choice; + mpmenu.modewinextend[2][0] = 1; + M_SetupNextMenu(&PLAY_MP_JoinIPDef, true); +} + +// Attempts to join a given IP from the menu. +void M_JoinIP(const char *ipa) +{ + if (*(ipa) == '\0') // Jack shit + { + M_StartMessage("Please specify an address.\n", NULL, MM_NOTHING); + return; + } + + COM_BufAddText(va("connect \"%s\"\n", ipa)); + + // A little "please wait" message. + M_DrawTextBox(56, BASEVIDHEIGHT/2-12, 24, 2); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, "Connecting to server..."); + I_OsPolling(); + I_UpdateNoBlit(); + if (rendermode == render_soft) + I_FinishUpdate(); // page flip or blit buffer +} + +boolean M_JoinIPInputs(INT32 ch) +{ + + const UINT8 pid = 0; + (void) ch; + + if (itemOn == 1) // connect field + { + // enter: connect + if (M_MenuConfirmPressed(pid)) + { + M_JoinIP(cv_dummyip.string); + M_SetMenuDelay(pid); + return true; + } + } + else if (currentMenu->numitems - itemOn <= NUMLOGIP && M_MenuConfirmPressed(pid)) // On one of the last 3 options for IP rejoining + { + UINT8 index = NUMLOGIP - (currentMenu->numitems - itemOn); + M_SetMenuDelay(pid); + + // Is there an address at this part of the table? + if (*joinedIPlist[index][0]) + M_JoinIP(joinedIPlist[index][0]); + else + S_StartSound(NULL, sfx_lose); + + return true; // eat input. + } + + return false; +} diff --git a/src/menus/play-online-room-select.c b/src/menus/play-online-room-select.c new file mode 100644 index 000000000..d9f0fdd49 --- /dev/null +++ b/src/menus/play-online-room-select.c @@ -0,0 +1,66 @@ +/// \file menus/play-online-room-select.c +/// \brief MULTIPLAYER ROOM SELECT MENU + +#include "../k_menu.h" +#include "../s_sound.h" + +menuitem_t PLAY_MP_RoomSelect[] = +{ + {IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, {.routine = M_MPRoomSelect}, 0, 0}, +}; + +menu_t PLAY_MP_RoomSelectDef = { + sizeof (PLAY_MP_RoomSelect) / sizeof (menuitem_t), + &PLAY_MP_OptSelectDef, + 0, + PLAY_MP_RoomSelect, + 0, 0, + 0, 0, + 0, 0, + M_DrawMPRoomSelect, + M_MPRoomSelectTick, + NULL, + NULL, + NULL +}; + +void M_MPRoomSelect(INT32 choice) +{ + const UINT8 pid = 0; + (void) choice; + + if (menucmd[pid].dpad_lr) + { + mpmenu.room = (!mpmenu.room) ? 1 : 0; + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + else if (M_MenuBackPressed(pid)) + { + M_GoBack(0); + M_SetMenuDelay(pid); + } + + else if (M_MenuConfirmPressed(pid)) + { + M_ServersMenu(0); + M_SetMenuDelay(pid); + } +} + +void M_MPRoomSelectTick(void) +{ + mpmenu.ticker++; +} + +void M_MPRoomSelectInit(INT32 choice) +{ + (void)choice; + mpmenu.room = 0; + mpmenu.ticker = 0; + mpmenu.servernum = 0; + mpmenu.scrolln = 0; + mpmenu.slide = 0; + + M_SetupNextMenu(&PLAY_MP_RoomSelectDef, false); +} diff --git a/src/menus/play-online-server-browser.c b/src/menus/play-online-server-browser.c index 6549340a7..5aebbd771 100644 --- a/src/menus/play-online-server-browser.c +++ b/src/menus/play-online-server-browser.c @@ -1,30 +1,15 @@ /// \file menus/play-online-server-browser.c -/// \brief Online server, CORE / MODDED +/// \brief MULTIPLAYER ROOM FETCH / REFRESH THREADS #include "../k_menu.h" +#include "../v_video.h" +#include "../i_system.h" // I_OsPolling +#include "../i_video.h" // I_UpdateNoBlit -// MULTIPLAYER ROOM SELECT (CORE / MODDED) -menuitem_t PLAY_MP_RoomSelect[] = -{ - {IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, {.routine = M_MPRoomSelect}, 0, 0}, -}; +#ifdef SERVERLISTDEBUG +#include "../m_random.h" +#endif -menu_t PLAY_MP_RoomSelectDef = { - sizeof (PLAY_MP_RoomSelect) / sizeof (menuitem_t), - &PLAY_MP_OptSelectDef, - 0, - PLAY_MP_RoomSelect, - 0, 0, - 0, 0, - 0, 0, - M_DrawMPRoomSelect, - M_MPRoomSelectTick, - NULL, - NULL, - NULL -}; - -// SERVER BROWSER menuitem_t PLAY_MP_ServerBrowser[] = { @@ -51,3 +36,459 @@ menu_t PLAY_MP_ServerBrowserDef = { NULL, M_ServerBrowserInputs }; + +static CV_PossibleValue_t serversort_cons_t[] = { + {0,"Ping"}, + {1,"AVG. Power Level"}, + {2,"Most Players"}, + {3,"Least Players"}, + {4,"Max Player Slots"}, + {5,"Gametype"}, + {0,NULL} +}; +consvar_t cv_serversort = CVAR_INIT ("serversort", "Ping", CV_CALL, serversort_cons_t, M_SortServerList); + +// for server fetch threads... +M_waiting_mode_t m_waiting_mode = M_NOT_WAITING; + +// depending on mpmenu.room, either allows only unmodded servers or modded ones. Remove others from the list. +// we do this by iterating backwards. +static void M_CleanServerList(void) +{ + UINT8 i = serverlistcount; + + while (i) + { + + if (serverlist[i].info.modifiedgame != mpmenu.room) + { + // move everything after this index 1 slot down... + if (i != serverlistcount) + memcpy(&serverlist[i], &serverlist[i+1], sizeof(serverelem_t)*(serverlistcount-i)); + + serverlistcount--; + } + + i--; + } +} + +void +M_SetWaitingMode (int mode) +{ +#ifdef HAVE_THREADS + I_lock_mutex(&k_menu_mutex); +#endif + { + m_waiting_mode = mode; + } +#ifdef HAVE_THREADS + I_unlock_mutex(k_menu_mutex); +#endif +} + +int +M_GetWaitingMode (void) +{ + int mode; + +#ifdef HAVE_THREADS + I_lock_mutex(&k_menu_mutex); +#endif + { + mode = m_waiting_mode; + } +#ifdef HAVE_THREADS + I_unlock_mutex(k_menu_mutex); +#endif + + return mode; +} + +#ifdef MASTERSERVER +#ifdef HAVE_THREADS +void +Spawn_masterserver_thread (const char *name, void (*thread)(int*)) +{ + int *id = malloc(sizeof *id); + + I_lock_mutex(&ms_QueryId_mutex); + { + *id = ms_QueryId; + } + I_unlock_mutex(ms_QueryId_mutex); + + I_spawn_thread(name, (I_thread_fn)thread, id); +} + +int +Same_instance (int id) +{ + int okay; + + I_lock_mutex(&ms_QueryId_mutex); + { + okay = ( id == ms_QueryId ); + } + I_unlock_mutex(ms_QueryId_mutex); + + return okay; +} +#endif/*HAVE_THREADS*/ + +void +Fetch_servers_thread (int *id) +{ + msg_server_t * server_list; + + (void)id; + + M_SetWaitingMode(M_WAITING_SERVERS); + +#ifdef HAVE_THREADS + server_list = GetShortServersList(*id); +#else + server_list = GetShortServersList(0); +#endif + + if (server_list) + { +#ifdef HAVE_THREADS + if (Same_instance(*id)) +#endif + { + M_SetWaitingMode(M_NOT_WAITING); + +#ifdef HAVE_THREADS + I_lock_mutex(&ms_ServerList_mutex); + { + ms_ServerList = server_list; + } + I_unlock_mutex(ms_ServerList_mutex); +#else + CL_QueryServerList(server_list); + free(server_list); +#endif + } +#ifdef HAVE_THREADS + else + { + free(server_list); + } +#endif + } + +#ifdef HAVE_THREADS + free(id); +#endif +} +#endif/*MASTERSERVER*/ + +// updates serverlist +void M_RefreshServers(INT32 choice) +{ + (void)choice; + + // Display a little "please wait" message. + M_DrawTextBox(52, BASEVIDHEIGHT/2-10, 25, 3); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, "Searching for servers..."); + V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2)+12, 0, "Please wait."); + I_OsPolling(); + I_UpdateNoBlit(); + if (rendermode == render_soft) + I_FinishUpdate(); // page flip or blit buffer + +#ifdef MASTERSERVER +#ifdef HAVE_THREADS + Spawn_masterserver_thread("fetch-servers", Fetch_servers_thread); +#else/*HAVE_THREADS*/ + Fetch_servers_thread(NULL); +#endif/*HAVE_THREADS*/ +#else/*MASTERSERVER*/ + CL_UpdateServerList(); +#endif/*MASTERSERVER*/ + +#ifdef SERVERLISTDEBUG + M_ServerListFillDebug(); +#endif + M_CleanServerList(); + M_SortServerList(); + +} + +#ifdef UPDATE_ALERT +static void M_CheckMODVersion(int id) +{ + char updatestring[500]; + const char *updatecheck = GetMODVersion(id); + if(updatecheck) + { + sprintf(updatestring, UPDATE_ALERT_STRING, VERSIONSTRING, updatecheck); +#ifdef HAVE_THREADS + I_lock_mutex(&k_menu_mutex); +#endif + M_StartMessage(updatestring, NULL, MM_NOTHING); +#ifdef HAVE_THREADS + I_unlock_mutex(k_menu_mutex); +#endif + } +} +#endif/*UPDATE_ALERT*/ + +#if defined (UPDATE_ALERT) && defined (HAVE_THREADS) +static void +Check_new_version_thread (int *id) +{ + M_SetWaitingMode(M_WAITING_VERSION); + + M_CheckMODVersion(*id); + + if (Same_instance(*id)) + { + Fetch_servers_thread(id); + } + else + { + free(id); + } +} +#endif/*defined (UPDATE_ALERT) && defined (HAVE_THREADS)*/ + + +// Initializes serverlist when entering the menu... +void M_ServersMenu(INT32 choice) +{ + (void)choice; + // modified game check: no longer handled + // we don't request a restart unless the filelist differs + + mpmenu.servernum = 0; + mpmenu.scrolln = 0; + mpmenu.slide = 0; + + M_SetupNextMenu(&PLAY_MP_ServerBrowserDef, false); + itemOn = 0; + +#if defined (MASTERSERVER) && defined (HAVE_THREADS) + I_lock_mutex(&ms_QueryId_mutex); + { + ms_QueryId++; + } + I_unlock_mutex(ms_QueryId_mutex); + + I_lock_mutex(&ms_ServerList_mutex); + { + if (ms_ServerList) + { + free(ms_ServerList); + ms_ServerList = NULL; + } + } + I_unlock_mutex(ms_ServerList_mutex); + +#ifdef UPDATE_ALERT + Spawn_masterserver_thread("check-new-version", Check_new_version_thread); +#else/*UPDATE_ALERT*/ + Spawn_masterserver_thread("fetch-servers", Fetch_servers_thread); +#endif/*UPDATE_ALERT*/ +#else/*defined (MASTERSERVER) && defined (HAVE_THREADS)*/ +#ifdef UPDATE_ALERT + M_CheckMODVersion(0); +#endif/*UPDATE_ALERT*/ + M_RefreshServers(0); +#endif/*defined (MASTERSERVER) && defined (HAVE_THREADS)*/ + +#ifdef SERVERLISTDEBUG + M_ServerListFillDebug(); +#endif + + M_CleanServerList(); + M_SortServerList(); +} + +#ifdef SERVERLISTDEBUG + +// Fill serverlist with a bunch of garbage to make our life easier in debugging +void M_ServerListFillDebug(void) +{ + UINT8 i = 0; + + serverlistcount = 10; + memset(serverlist, 0, sizeof(serverlist)); // zero out the array for convenience... + + for (i = 0; i < serverlistcount; i++) + { + // We don't really care about the server node for this, let's just fill in the info so that we have a visual... + serverlist[i].info.numberofplayer = min(i, 8); + serverlist[i].info.maxplayer = 8; + + serverlist[i].info.avgpwrlv = P_RandomRange(PR_UNDEFINED, 500, 1500); + serverlist[i].info.time = P_RandomRange(PR_UNDEFINED, 1, 8); // ping + + strcpy(serverlist[i].info.servername, va("Serv %d", i+1)); + + strcpy(serverlist[i].info.gametypename, i & 1 ? "Race" : "Battle"); + + P_RandomRange(PR_UNDEFINED, 0, 5); // change results... + serverlist[i].info.kartvars = P_RandomRange(PR_UNDEFINED, 0, 3) & SV_SPEEDMASK; + + serverlist[i].info.modifiedgame = P_RandomRange(PR_UNDEFINED, 0, 1); + + CONS_Printf("Serv %d | %d...\n", i, serverlist[i].info.modifiedgame); + } +} + +#endif // SERVERLISTDEBUG + +// Ascending order, not descending. +// The casts are safe as long as the caller doesn't do anything stupid. +#define SERVER_LIST_ENTRY_COMPARATOR(key) \ +static int ServerListEntryComparator_##key(const void *entry1, const void *entry2) \ +{ \ + const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2; \ + if (sa->info.key != sb->info.key) \ + return sa->info.key - sb->info.key; \ + return strcmp(sa->info.servername, sb->info.servername); \ +} + +// This does descending instead of ascending. +#define SERVER_LIST_ENTRY_COMPARATOR_REVERSE(key) \ +static int ServerListEntryComparator_##key##_reverse(const void *entry1, const void *entry2) \ +{ \ + const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2; \ + if (sb->info.key != sa->info.key) \ + return sb->info.key - sa->info.key; \ + return strcmp(sb->info.servername, sa->info.servername); \ +} + +SERVER_LIST_ENTRY_COMPARATOR(time) +SERVER_LIST_ENTRY_COMPARATOR(numberofplayer) +SERVER_LIST_ENTRY_COMPARATOR_REVERSE(numberofplayer) +SERVER_LIST_ENTRY_COMPARATOR_REVERSE(maxplayer) +SERVER_LIST_ENTRY_COMPARATOR(avgpwrlv) + + +static int ServerListEntryComparator_gametypename(const void *entry1, const void *entry2) +{ + const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2; + int c; + if (( c = strcasecmp(sa->info.gametypename, sb->info.gametypename) )) + return c; + return strcmp(sa->info.servername, sb->info.servername); \ +} + +void M_SortServerList(void) +{ + switch(cv_serversort.value) + { + case 0: // Ping. + qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_time); + break; + case 1: // AVG. Power Level + qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_avgpwrlv); + break; + case 2: // Most players. + qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_numberofplayer_reverse); + break; + case 3: // Least players. + qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_numberofplayer); + break; + case 4: // Max players. + qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_maxplayer_reverse); + break; + case 5: // Gametype. + qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_gametypename); + break; + } +} + + +// Server browser inputs & ticker +void M_MPServerBrowserTick(void) +{ + mpmenu.slide /= 2; +} + +// Input handler for server browser. +boolean M_ServerBrowserInputs(INT32 ch) +{ + UINT8 pid = 0; + UINT8 maxscroll = serverlistcount-(SERVERSPERPAGE/2); + (void) ch; + + if (!itemOn && menucmd[pid].dpad_ud < 0) + { + M_PrevOpt(); // go to itemOn 2 + if (serverlistcount) + { + UINT8 prevscroll = mpmenu.scrolln; + + mpmenu.servernum = serverlistcount; + mpmenu.scrolln = maxscroll; + mpmenu.slide = SERVERSPACE * (prevscroll - mpmenu.scrolln); + } + else + { + itemOn = 1; // Sike! If there are no servers, go to refresh instead. + } + + return true; // overwrite behaviour. + } + else if (itemOn == 2) // server browser itself... + { + // we have to manually do that here. + if (M_MenuBackPressed(pid)) + { + M_GoBack(0); + M_SetMenuDelay(pid); + } + + else if (menucmd[pid].dpad_ud > 0) // down + { + if (mpmenu.servernum >= serverlistcount-1) + { + UINT8 prevscroll = mpmenu.scrolln; + mpmenu.servernum = 0; + mpmenu.scrolln = 0; + mpmenu.slide = SERVERSPACE * (prevscroll - mpmenu.scrolln); + + M_NextOpt(); // Go back to the top of the real menu. + } + else + { + mpmenu.servernum++; + if (mpmenu.scrolln < maxscroll && mpmenu.servernum > SERVERSPERPAGE/2) + { + mpmenu.scrolln++; + mpmenu.slide += SERVERSPACE; + } + } + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + + } + else if (menucmd[pid].dpad_ud < 0) + { + + if (!mpmenu.servernum) + { + M_PrevOpt(); + } + else + { + if (mpmenu.servernum <= serverlistcount-(SERVERSPERPAGE/2) && mpmenu.scrolln) + { + mpmenu.scrolln--; + mpmenu.slide -= SERVERSPACE; + } + + mpmenu.servernum--; + } + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + + } + return true; // Overwrite behaviour. + } + return false; // use normal behaviour. +} diff --git a/src/menus/transient/CMakeLists.txt b/src/menus/transient/CMakeLists.txt index 305c82829..bea478d5f 100644 --- a/src/menus/transient/CMakeLists.txt +++ b/src/menus/transient/CMakeLists.txt @@ -1,6 +1,11 @@ target_sources(SRB2SDL2 PRIVATE + cup-select.c + explosions.c level-select.c + gametype.c manual.c + message-box.c pause-game.c pause-replay.c + virtual-keyboard.c ) diff --git a/src/menus/transient/cup-select.c b/src/menus/transient/cup-select.c new file mode 100644 index 000000000..b65f1ea3d --- /dev/null +++ b/src/menus/transient/cup-select.c @@ -0,0 +1,195 @@ +/// \file menus/transient/cup-select.c +/// \brief Cup Select + +#include "../../k_menu.h" +#include "../../s_sound.h" +#include "../../f_finale.h" // F_WipeStartScreen +#include "../../v_video.h" +#include "../../k_grandprix.h" +#include "../../r_local.h" // SplitScreen_OnChange + +menuitem_t PLAY_CupSelect[] = +{ + {IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, {.routine = M_CupSelectHandler}, 0, 0}, +}; + +menu_t PLAY_CupSelectDef = { + sizeof(PLAY_CupSelect) / sizeof(menuitem_t), + &PLAY_RaceGamemodesDef, + 0, + PLAY_CupSelect, + 0, 0, + 0, 0, + 2, 5, + M_DrawCupSelect, + M_CupSelectTick, + NULL, + NULL, + NULL +}; + +struct cupgrid_s cupgrid; + +void M_CupSelectHandler(INT32 choice) +{ + const UINT8 pid = 0; + + (void)choice; + + if (menucmd[pid].dpad_lr > 0) + { + cupgrid.x++; + if (cupgrid.x >= CUPMENU_COLUMNS) + { + cupgrid.x = 0; + cupgrid.pageno++; + if (cupgrid.pageno >= cupgrid.numpages) + cupgrid.pageno = 0; + } + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + else if (menucmd[pid].dpad_lr < 0) + { + cupgrid.x--; + if (cupgrid.x < 0) + { + cupgrid.x = CUPMENU_COLUMNS-1; + if (cupgrid.pageno == 0) + cupgrid.pageno = cupgrid.numpages-1; + else + cupgrid.pageno--; + } + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + + if (menucmd[pid].dpad_ud > 0) + { + cupgrid.y++; + if (cupgrid.y >= CUPMENU_ROWS) + cupgrid.y = 0; + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + else if (menucmd[pid].dpad_ud < 0) + { + cupgrid.y--; + if (cupgrid.y < 0) + cupgrid.y = CUPMENU_ROWS-1; + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + + if (M_MenuConfirmPressed(pid) /*|| M_MenuButtonPressed(pid, MBT_START)*/) + { + INT16 count; + cupheader_t *newcup = cupgrid.builtgrid[CUPMENU_CURSORID]; + cupheader_t *oldcup = levellist.levelsearch.cup; + + M_SetMenuDelay(pid); + + levellist.levelsearch.cup = newcup; + count = M_CountLevelsToShowInList(&levellist.levelsearch); + + if ((!newcup) + || (count <= 0) + || (cupgrid.grandprix == true && newcup->cachedlevels[0] == NEXTMAP_INVALID)) + { + S_StartSound(NULL, sfx_s3kb2); + return; + } + + if (cupgrid.grandprix == true) + { + INT32 levelNum; + UINT8 ssplayers = cv_splitplayers.value-1; + + S_StartSound(NULL, sfx_s3k63); + + // Early fadeout to let the sound finish playing + F_WipeStartScreen(); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + F_WipeEndScreen(); + F_RunWipe(wipedefs[wipe_level_toblack], false, "FADEMAP0", false, false); + + memset(&grandprixinfo, 0, sizeof(struct grandprixinfo)); + + if (cv_maxconnections.value < ssplayers+1) + CV_SetValue(&cv_maxconnections, ssplayers+1); + + if (splitscreen != ssplayers) + { + splitscreen = ssplayers; + SplitScreen_OnChange(); + } + + // read our dummy cvars + + grandprixinfo.gamespeed = min(KARTSPEED_HARD, cv_dummygpdifficulty.value); + grandprixinfo.masterbots = (cv_dummygpdifficulty.value == 3); + grandprixinfo.encore = (boolean)cv_dummygpencore.value; + + grandprixinfo.cup = newcup; + + grandprixinfo.gp = true; + grandprixinfo.roundnum = 1; + grandprixinfo.initalize = true; + + paused = false; + + // Don't restart the server if we're already in a game lol + if (gamestate == GS_MENU) + { + SV_StartSinglePlayerServer(levellist.newgametype, levellist.netgame); + } + + levelNum = grandprixinfo.cup->cachedlevels[0]; + + D_MapChange( + levelNum + 1, + GT_RACE, + grandprixinfo.encore, + true, + 1, + false, + false + ); + + M_ClearMenus(true); + } + else if (count == 1) + { + PLAY_TimeAttackDef.transitionID = currentMenu->transitionID+1; + M_LevelSelected(0); + } + else + { + // Keep cursor position if you select the same cup again, reset if it's a different cup + if (oldcup != newcup || levellist.cursor >= count) + { + levellist.cursor = 0; + } + + M_LevelSelectScrollDest(); + levellist.y = levellist.dest; + + M_SetupNextMenu(&PLAY_LevelSelectDef, false); + S_StartSound(NULL, sfx_s3k63); + } + } + else if (M_MenuBackPressed(pid)) + { + M_SetMenuDelay(pid); + + if (currentMenu->prevMenu) + M_SetupNextMenu(currentMenu->prevMenu, false); + else + M_ClearMenus(true); + } +} + +void M_CupSelectTick(void) +{ + cupgrid.previewanim++; +} diff --git a/src/menus/transient/explosions.c b/src/menus/transient/explosions.c new file mode 100644 index 000000000..3c5c868ed --- /dev/null +++ b/src/menus/transient/explosions.c @@ -0,0 +1,63 @@ +/// \file menus/transient/explosions.c +/// \brief Explosions used on the character select grid and +/// challenges grid. + +#include "../../k_menu.h" +#include "../../m_cond.h" // Condition Sets + +struct setup_explosions_s setup_explosions[CSEXPLOSIONS]; + +void M_SetupReadyExplosions(boolean charsel, UINT16 basex, UINT16 basey, UINT16 color) +{ + UINT8 i, j; + UINT8 e = 0; + UINT16 maxx = (charsel ? 9 : gamedata->challengegridwidth); + UINT16 maxy = (charsel ? 9 : CHALLENGEGRIDHEIGHT); + + while (setup_explosions[e].tics) + { + e++; + if (e == CSEXPLOSIONS) + return; + } + + for (i = 0; i < 3; i++) + { + UINT8 t = 5 + (i*2); + UINT8 offset = (i+1); + + for (j = 0; j < 4; j++) + { + INT16 x = basex, y = basey; + + switch (j) + { + case 0: x += offset; break; + case 1: x -= offset; break; + case 2: y += offset; break; + case 3: y -= offset; break; + } + + if ((y < 0 || y >= maxy)) + continue; + + if (charsel || !challengegridloops) + { + if (x < 0 || x >= maxx) + continue; + } + + setup_explosions[e].tics = t; + setup_explosions[e].color = color; + setup_explosions[e].x = x; + setup_explosions[e].y = y; + + while (setup_explosions[e].tics) + { + e++; + if (e == CSEXPLOSIONS) + return; + } + } + } +} diff --git a/src/menus/transient/gametype.c b/src/menus/transient/gametype.c new file mode 100644 index 000000000..7bb0ba425 --- /dev/null +++ b/src/menus/transient/gametype.c @@ -0,0 +1,34 @@ +/// \file menus/transient/gametype.c +/// \brief Gametype selection + +#include "../../k_menu.h" + +INT16 menugametype = GT_RACE; + +void M_NextMenuGametype(UINT32 forbidden) +{ + const INT16 currentmenugametype = menugametype; + do + { + menugametype++; + if (menugametype >= numgametypes) + menugametype = 0; + + if (!(gametypes[menugametype]->rules & forbidden)) + break; + } while (menugametype != currentmenugametype); +} + +void M_PrevMenuGametype(UINT32 forbidden) +{ + const INT16 currentmenugametype = menugametype; + do + { + if (menugametype == 0) + menugametype = numgametypes; + menugametype--; + + if (!(gametypes[menugametype]->rules & forbidden)) + break; + } while (menugametype != currentmenugametype); +} diff --git a/src/menus/transient/level-select.c b/src/menus/transient/level-select.c index ab124b8e5..9480e762f 100644 --- a/src/menus/transient/level-select.c +++ b/src/menus/transient/level-select.c @@ -2,26 +2,12 @@ /// \brief Level Select #include "../../k_menu.h" - -menuitem_t PLAY_CupSelect[] = -{ - {IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, {.routine = M_CupSelectHandler}, 0, 0}, -}; - -menu_t PLAY_CupSelectDef = { - sizeof(PLAY_CupSelect) / sizeof(menuitem_t), - &PLAY_RaceGamemodesDef, - 0, - PLAY_CupSelect, - 0, 0, - 0, 0, - 2, 5, - M_DrawCupSelect, - M_CupSelectTick, - NULL, - NULL, - NULL -}; +#include "../../m_cond.h" // Condition Sets +#include "../../z_zone.h" +#include "../../s_sound.h" +#include "../../r_local.h" // SplitScreen_OnChange +#include "../../f_finale.h" // F_WipeStartScreen +#include "../../v_video.h" menuitem_t PLAY_LevelSelect[] = { @@ -42,3 +28,524 @@ menu_t PLAY_LevelSelectDef = { NULL, NULL }; + +struct levellist_s levellist; + +// +// M_CanShowLevelInList +// +// Determines whether to show a given map in the various level-select lists. +// +boolean M_CanShowLevelInList(INT16 mapnum, levelsearch_t *levelsearch) +{ + if (!levelsearch) + return false; + + if (mapnum >= nummapheaders) + return false; + + // Does the map exist? + if (!mapheaderinfo[mapnum]) + return false; + + // Does the map have a name? + if (!mapheaderinfo[mapnum]->lvlttl[0]) + return false; + + // Does the map have a LUMP? + if (mapheaderinfo[mapnum]->lumpnum == LUMPERROR) + return false; + + // Check for TOL + if (!(mapheaderinfo[mapnum]->typeoflevel & levelsearch->typeoflevel)) + return false; + + // Should the map be hidden? + if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU) + return false; + + // I don't know why, but some may have exceptions. + if (levelsearch->timeattack && (mapheaderinfo[mapnum]->menuflags & LF2_NOTIMEATTACK)) + return false; + + // Don't permit cup when no cup requested (also no dupes in time attack) + if (levelsearch->cupmode + && (levelsearch->timeattack || !levelsearch->cup) + && mapheaderinfo[mapnum]->cup != levelsearch->cup) + return false; + + // Finally, the most complex check: does the map have lock conditions? + if (levelsearch->checklocked) + { + // Check for completion + if ((mapheaderinfo[mapnum]->menuflags & LF2_FINISHNEEDED) + && !(mapheaderinfo[mapnum]->mapvisited & MV_BEATEN)) + return false; + + // Check for unlock + if (M_MapLocked(mapnum+1)) + return false; + } + + // Survived our checks. + return true; +} + +UINT16 M_CountLevelsToShowInList(levelsearch_t *levelsearch) +{ + INT16 i, count = 0; + + if (!levelsearch) + return false; + + if (levelsearch->cup) + { + if (levelsearch->checklocked && M_CupLocked(levelsearch->cup)) + return 0; + + for (i = 0; i < CUPCACHE_MAX; i++) + { + if (!M_CanShowLevelInList(levelsearch->cup->cachedlevels[i], levelsearch)) + continue; + count++; + } + + return count; + } + + for (i = 0; i < nummapheaders; i++) + if (M_CanShowLevelInList(i, levelsearch)) + count++; + + return count; +} + +UINT16 M_GetFirstLevelInList(UINT8 *i, levelsearch_t *levelsearch) +{ + INT16 mapnum = NEXTMAP_INVALID; + + if (!levelsearch) + return false; + + if (levelsearch->cup) + { + if (levelsearch->checklocked && M_CupLocked(levelsearch->cup)) + { + *i = CUPCACHE_MAX; + return NEXTMAP_INVALID; + } + + *i = 0; + mapnum = NEXTMAP_INVALID; + for (; *i < CUPCACHE_MAX; (*i)++) + { + if (!M_CanShowLevelInList(levelsearch->cup->cachedlevels[*i], levelsearch)) + continue; + mapnum = levelsearch->cup->cachedlevels[*i]; + break; + } + } + else + { + for (mapnum = 0; mapnum < nummapheaders; mapnum++) + if (M_CanShowLevelInList(mapnum, levelsearch)) + break; + } + + return mapnum; +} + +UINT16 M_GetNextLevelInList(UINT16 mapnum, UINT8 *i, levelsearch_t *levelsearch) +{ + if (!levelsearch) + return false; + + if (levelsearch->cup) + { + mapnum = NEXTMAP_INVALID; + (*i)++; + for (; *i < CUPCACHE_MAX; (*i)++) + { + if (!M_CanShowLevelInList(levelsearch->cup->cachedlevels[*i], levelsearch)) + continue; + mapnum = levelsearch->cup->cachedlevels[*i]; + break; + } + } + else + { + mapnum++; + while (!M_CanShowLevelInList(mapnum, levelsearch) && mapnum < nummapheaders) + mapnum++; + } + + return mapnum; +} + +void M_LevelSelectScrollDest(void) +{ + UINT16 m = M_CountLevelsToShowInList(&levellist.levelsearch)-1; + + levellist.dest = (6*levellist.cursor); + + if (levellist.dest < 3) + levellist.dest = 3; + + if (levellist.dest > (6*m)-3) + levellist.dest = (6*m)-3; +} + +// Builds the level list we'll be using from the gametype we're choosing and send us to the apropriate menu. +boolean M_LevelListFromGametype(INT16 gt) +{ + static boolean first = true; + UINT8 temp = 0; + + if (first || gt != levellist.newgametype || levellist.guessgt != MAXGAMETYPES) + { + if (first) + { + cupgrid.cappages = 0; + cupgrid.builtgrid = NULL; + } + + levellist.newgametype = gt; + + levellist.levelsearch.typeoflevel = G_TOLFlag(gt); + if (levellist.levelsearch.timeattack == true && gt == GT_SPECIAL) + { + // Sneak in an extra. + levellist.levelsearch.typeoflevel |= G_TOLFlag(GT_VERSUS); + levellist.guessgt = gt; + } + else + { + levellist.guessgt = MAXGAMETYPES; + } + + levellist.levelsearch.cupmode = (!(gametypes[gt]->rules & GTR_NOCUPSELECT)); + levellist.levelsearch.cup = NULL; + + first = false; + } + + // Obviously go to Cup Select in gametypes that have cups. + // Use a really long level select in gametypes that don't use cups. + + if (levellist.levelsearch.cupmode) + { + levelsearch_t templevelsearch = levellist.levelsearch; // full copy + size_t currentid = 0, highestunlockedid = 0; + const size_t pagelen = sizeof(cupheader_t*) * (CUPMENU_COLUMNS * CUPMENU_ROWS); + boolean foundany = false; + + templevelsearch.cup = kartcupheaders; + +#if 0 + // Make sure there's valid cups before going to this menu. -- rip sweet prince + if (templevelsearch.cup == NULL) + I_Error("Can you really call this a racing game, I didn't recieve any Cups on my pillow or anything"); +#endif + + if (cupgrid.cappages == 0) + { + cupgrid.cappages = 2; + cupgrid.builtgrid = Z_Calloc( + cupgrid.cappages * pagelen, + PU_STATIC, + NULL); + + if (!cupgrid.builtgrid) + { + I_Error("M_LevelListFromGametype: Not enough memory to allocate builtgrid"); + } + } + memset(cupgrid.builtgrid, 0, cupgrid.cappages * pagelen); + + while (templevelsearch.cup) + { + templevelsearch.checklocked = false; + if (!M_CountLevelsToShowInList(&templevelsearch)) + { + // No valid maps, skip. + templevelsearch.cup = templevelsearch.cup->next; + continue; + } + + foundany = true; + + if ((currentid * sizeof(cupheader_t*)) >= cupgrid.cappages * pagelen) + { + // Double the size of the buffer, and clear the other stuff. + const size_t firstlen = cupgrid.cappages * pagelen; + cupgrid.builtgrid = Z_Realloc(cupgrid.builtgrid, + firstlen * 2, + PU_STATIC, NULL); + + if (!cupgrid.builtgrid) + { + I_Error("M_LevelListFromGametype: Not enough memory to reallocate builtgrid"); + } + + memset(cupgrid.builtgrid + firstlen, 0, firstlen); + cupgrid.cappages *= 2; + } + + cupgrid.builtgrid[currentid] = templevelsearch.cup; + + templevelsearch.checklocked = true; + if (M_GetFirstLevelInList(&temp, &templevelsearch) != NEXTMAP_INVALID) + { + highestunlockedid = currentid; + if (Playing() && mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->cup == templevelsearch.cup) + { + cupgrid.x = currentid % CUPMENU_COLUMNS; + cupgrid.y = (currentid / CUPMENU_COLUMNS) % CUPMENU_ROWS; + cupgrid.pageno = currentid / (CUPMENU_COLUMNS * CUPMENU_ROWS); + } + } + + currentid++; + templevelsearch.cup = templevelsearch.cup->next; + } + + if (foundany == false) + { + return false; + } + + cupgrid.numpages = (highestunlockedid / (CUPMENU_COLUMNS * CUPMENU_ROWS)) + 1; + if (cupgrid.pageno >= cupgrid.numpages) + { + cupgrid.pageno = 0; + } + + PLAY_CupSelectDef.prevMenu = currentMenu; + PLAY_LevelSelectDef.prevMenu = &PLAY_CupSelectDef; + M_SetupNextMenu(&PLAY_CupSelectDef, false); + + return true; + } + + // Okay, just a list of maps then. + + if (M_GetFirstLevelInList(&temp, &levellist.levelsearch) == NEXTMAP_INVALID) + { + return false; + } + + // Reset position properly if you go back & forth between gametypes + if (levellist.levelsearch.cup) + { + levellist.cursor = 0; + levellist.levelsearch.cup = NULL; + } + + M_LevelSelectScrollDest(); + levellist.y = levellist.dest; + + PLAY_LevelSelectDef.prevMenu = currentMenu; + M_SetupNextMenu(&PLAY_LevelSelectDef, false); + + return true; +} + +// Init level select for use in local play using the last choice we made. +// For the online MP version used to START HOSTING A GAME, see M_MPSetupNetgameMapSelect() +// (We still use this one midgame) + +void M_LevelSelectInit(INT32 choice) +{ + INT32 gt = currentMenu->menuitems[itemOn].mvar2; + + (void)choice; + + // Make sure this is reset as we'll only be using this function for offline games! + levellist.netgame = false; + levellist.levelsearch.checklocked = true; + + switch (currentMenu->menuitems[itemOn].mvar1) + { + case 0: + cupgrid.grandprix = false; + levellist.levelsearch.timeattack = false; + break; + case 1: + cupgrid.grandprix = false; + levellist.levelsearch.timeattack = true; + break; + case 2: + cupgrid.grandprix = true; + levellist.levelsearch.timeattack = false; + break; + default: + CONS_Alert(CONS_WARNING, "Bad level select init\n"); + return; + } + + if (gt == -1) + { + gt = menugametype; + } + + if (!M_LevelListFromGametype(gt)) + { + S_StartSound(NULL, sfx_s3kb2); + M_StartMessage(va("No levels available for\n%s Mode!\n\nPress (B)\n", gametypes[gt]->name), NULL, MM_NOTHING); + } +} + +void M_LevelSelected(INT16 add) +{ + UINT8 i = 0; + INT16 map = M_GetFirstLevelInList(&i, &levellist.levelsearch); + + while (add > 0) + { + map = M_GetNextLevelInList(map, &i, &levellist.levelsearch); + + if (map >= nummapheaders) + { + break; + } + + add--; + } + + if (map >= nummapheaders) + { + // This shouldn't happen + return; + } + + levellist.choosemap = map; + + if (levellist.levelsearch.timeattack) + { + S_StartSound(NULL, sfx_s3k63); + + if (levellist.guessgt != MAXGAMETYPES) + levellist.newgametype = G_GuessGametypeByTOL(levellist.levelsearch.typeoflevel); + + PLAY_TimeAttackDef.lastOn = ta_start; + PLAY_TimeAttackDef.prevMenu = currentMenu; + M_SetupNextMenu(&PLAY_TimeAttackDef, false); + } + else + { + if (gamestate == GS_MENU) + { + UINT8 ssplayers = cv_splitplayers.value-1; + + netgame = false; + multiplayer = true; + + strncpy(connectedservername, cv_servername.string, MAXSERVERNAME); + + // Still need to reset devmode + cht_debug = 0; + + if (demo.playback) + G_StopDemo(); + if (metalrecording) + G_StopMetalDemo(); + + /*if (levellist.choosemap == 0) + levellist.choosemap = G_RandMap(G_TOLFlag(levellist.newgametype), -1, 0, 0, false, NULL);*/ + + if (cv_maxconnections.value < ssplayers+1) + CV_SetValue(&cv_maxconnections, ssplayers+1); + + if (splitscreen != ssplayers) + { + splitscreen = ssplayers; + SplitScreen_OnChange(); + } + + S_StartSound(NULL, sfx_s3k63); + + paused = false; + + // Early fadeout to let the sound finish playing + F_WipeStartScreen(); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + F_WipeEndScreen(); + F_RunWipe(wipedefs[wipe_level_toblack], false, "FADEMAP0", false, false); + + SV_StartSinglePlayerServer(levellist.newgametype, levellist.netgame); + + CV_StealthSet(&cv_kartbot, cv_dummymatchbots.string); + CV_StealthSet(&cv_kartencore, (cv_dummygpencore.value == 1) ? "On" : "Auto"); + CV_StealthSet(&cv_kartspeed, (cv_dummykartspeed.value == KARTSPEED_NORMAL) ? "Auto" : cv_dummykartspeed.string); + + D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_kartencore.value == 1), 1, 1, false, false); + } + else + { + // directly do the map change + D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_kartencore.value == 1), 1, 1, false, false); + } + + M_ClearMenus(true); + } +} + +void M_LevelSelectHandler(INT32 choice) +{ + INT16 maxlevels = M_CountLevelsToShowInList(&levellist.levelsearch); + const UINT8 pid = 0; + + (void)choice; + + if (levellist.y != levellist.dest) + { + return; + } + + if (menucmd[pid].dpad_ud > 0) + { + levellist.cursor++; + if (levellist.cursor >= maxlevels) + levellist.cursor = 0; + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + else if (menucmd[pid].dpad_ud < 0) + { + levellist.cursor--; + if (levellist.cursor < 0) + levellist.cursor = maxlevels-1; + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + + M_LevelSelectScrollDest(); + + if (M_MenuConfirmPressed(pid) /*|| M_MenuButtonPressed(pid, MBT_START)*/) + { + M_SetMenuDelay(pid); + + PLAY_TimeAttackDef.transitionID = currentMenu->transitionID; + M_LevelSelected(levellist.cursor); + } + else if (M_MenuBackPressed(pid)) + { + M_SetMenuDelay(pid); + + if (currentMenu->prevMenu) + M_SetupNextMenu(currentMenu->prevMenu, false); + else + M_ClearMenus(true); + } +} + +void M_LevelSelectTick(void) +{ + + INT16 dist = levellist.dest - levellist.y; + + if (abs(dist) == 1) // cheating to avoid off by 1 errors with divisions. + levellist.y = levellist.dest; + else + levellist.y += dist/2; +} diff --git a/src/menus/transient/manual.c b/src/menus/transient/manual.c index 2ba3c32a9..e6ca008eb 100644 --- a/src/menus/transient/manual.c +++ b/src/menus/transient/manual.c @@ -2,6 +2,7 @@ /// \brief Manual #include "../../k_menu.h" +#include "../../s_sound.h" menuitem_t MISC_Manual[] = { {IT_NOTHING | IT_KEYHANDLER, "MANUAL00", NULL, NULL, {.routine = M_HandleImageDef}, 0, 0}, @@ -21,3 +22,52 @@ menuitem_t MISC_Manual[] = { }; menu_t MISC_ManualDef = IMAGEDEF(MISC_Manual); + +// Handles the ImageDefs. Just a specialized function that +// uses left and right movement. +void M_HandleImageDef(INT32 choice) +{ + const UINT8 pid = 0; + boolean exitmenu = false; + (void) choice; + + if (menucmd[pid].dpad_lr > 0) + { + if (itemOn >= (INT16)(currentMenu->numitems-1)) + return; + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + itemOn++; + } + else if (menucmd[pid].dpad_lr < 0) + { + if (!itemOn) + return; + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + itemOn--; + } + else if (M_MenuConfirmPressed(pid) || M_MenuButtonPressed(pid, MBT_X) || M_MenuButtonPressed(pid, MBT_Y)) + { + exitmenu = true; + M_SetMenuDelay(pid); + } + + + if (exitmenu) + { + if (currentMenu->prevMenu) + M_SetupNextMenu(currentMenu->prevMenu, false); + else + M_ClearMenus(true); + } +} + +// Opening manual +void M_Manual(INT32 choice) +{ + (void)choice; + + MISC_ManualDef.prevMenu = (choice == INT32_MAX ? NULL : currentMenu); + M_SetupNextMenu(&MISC_ManualDef, true); +} diff --git a/src/menus/transient/message-box.c b/src/menus/transient/message-box.c new file mode 100644 index 000000000..1f3c0b47a --- /dev/null +++ b/src/menus/transient/message-box.c @@ -0,0 +1,200 @@ +// \file menus/transient/message-box.c +// \brief MESSAGE BOX (aka: a hacked, cobbled together menu) + +#include "../../k_menu.h" +#include "../../z_zone.h" + +static menuitem_t MessageMenu[] = +{ + // TO HACK + {0, NULL, NULL, NULL, {NULL}, 0, 0} +}; + +menu_t MessageDef = +{ + 1, // # of menu items + NULL, // previous menu (TO HACK) + 0, // lastOn, flags (TO HACK) + MessageMenu, // menuitem_t -> + 0, 0, // x, y (TO HACK) + 0, 0, // extra1, extra2 + 0, 0, // transition tics + NULL, // drawing routine -> + NULL, // ticker routine + NULL, // init routine + NULL, // quit routine + NULL // input routine +}; + +// message prompt struct +struct menumessage_s menumessage; + +// +// M_StringHeight +// +// Find string height from hu_font chars +// +static inline size_t M_StringHeight(const char *string) +{ + size_t h = 8, i; + + for (i = 0; i < strlen(string); i++) + if (string[i] == '\n') + h += 8; + + return h; +} + +// default message handler +void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtype) +{ + const UINT8 pid = 0; + size_t max = 0, start = 0, strlines = 0, i; + static char *message = NULL; + Z_Free(message); + message = Z_StrDup(string); + DEBFILE(message); + + // Rudementary word wrapping. + // Simple and effective. Does not handle nonuniform letter sizes, etc. but who cares. + for (i = 0; message[i]; i++) + { + if (message[i] == ' ') + { + start = i; + max += 4; + } + else if (message[i] == '\n') + { + strlines = i; + start = 0; + max = 0; + continue; + } + else if (message[i] & 0x80) + continue; + else + max += 8; + + // Start trying to wrap if presumed length exceeds the screen width. + if (max >= BASEVIDWIDTH && start > 0) + { + message[start] = '\n'; + max -= (start-strlines)*8; + strlines = start; + start = 0; + } + } + + strncpy(menumessage.message, string, MAXMENUMESSAGE); + menumessage.flags = itemtype; + *(void**)&menumessage.routine = routine; + menumessage.fadetimer = (gamestate == GS_WAITINGPLAYERS) ? 9 : 1; + menumessage.active = true; + + start = 0; + max = 0; + + if (!routine || menumessage.flags == MM_NOTHING) + { + menumessage.flags = MM_NOTHING; + menumessage.routine = M_StopMessage; + } + + // event routine + if (menumessage.flags == MM_EVENTHANDLER) + { + *(void**)&menumessage.eroutine = routine; + menumessage.routine = NULL; + } + + //added : 06-02-98: now draw a textbox around the message + // compute lenght max and the numbers of lines + for (strlines = 0; *(message+start); strlines++) + { + for (i = 0;i < strlen(message+start);i++) + { + if (*(message+start+i) == '\n') + { + if (i > max) + max = i; + start += i; + i = (size_t)-1; //added : 07-02-98 : damned! + start++; + break; + } + } + + if (i == strlen(message+start)) + { + start += i; + if (i > max) + max = i; + } + } + + menumessage.x = (INT16)((BASEVIDWIDTH - 8*max-16)/2); + menumessage.y = (INT16)((BASEVIDHEIGHT - M_StringHeight(message))/2); + + menumessage.m = (INT16)((strlines<<8)+max); + + M_SetMenuDelay(pid); // Set menu delay to avoid setting off any of the handlers. +} + +void M_StopMessage(INT32 choice) +{ + const char pid = 0; + (void) choice; + + menumessage.active = false; + M_SetMenuDelay(pid); +} + +// regular handler for MM_NOTHING and MM_YESNO +void M_HandleMenuMessage(void) +{ + const UINT8 pid = 0; + boolean btok = M_MenuConfirmPressed(pid); + boolean btnok = M_MenuBackPressed(pid); + + if (menumessage.fadetimer < 9) + menumessage.fadetimer++; + + switch (menumessage.flags) + { + // Send 1 to the routine if we're pressing A/B/X/Y + case MM_NOTHING: + { + // send 1 if any button is pressed, 0 otherwise. + if (btok || btnok) + menumessage.routine(0); + + break; + } + // Send 1 to the routine if we're pressing A/X, 2 if B/Y, 0 otherwise. + case MM_YESNO: + { + INT32 answer = MA_NONE; + if (btok) + answer = MA_YES; + else if (btnok) + answer = MA_NO; + + // send 1 if btok is pressed, 2 if nok is pressed, 0 otherwise. + if (answer) + { + menumessage.routine(answer); + M_StopMessage(0); + } + + break; + } + // MM_EVENTHANDLER: In M_Responder to allow full event compat. + default: + break; + } + + // if we detect any keypress, don't forget to set the menu delay regardless. + if (btok || btnok) + M_SetMenuDelay(pid); +} diff --git a/src/menus/transient/pause-game.c b/src/menus/transient/pause-game.c index 5a29da812..5619a739e 100644 --- a/src/menus/transient/pause-game.c +++ b/src/menus/transient/pause-game.c @@ -2,6 +2,8 @@ /// \brief In-game/pause menus #include "../../k_menu.h" +#include "../../k_grandprix.h" // K_CanChangeRules +#include "../../s_sound.h" // ESC pause menu // Since there's no descriptions to each item, we'll use the descriptions as the names of the patches we want to draw for each option :) @@ -68,3 +70,286 @@ menu_t PAUSE_MainDef = { NULL, M_PauseInputs }; + +static void Dummymenuplayer_OnChange(void); + +static CV_PossibleValue_t dummymenuplayer_cons_t[] = {{0, "NOPE"}, {1, "P1"}, {2, "P2"}, {3, "P3"}, {4, "P4"}, {0, NULL}}; + +//static consvar_t cv_dummymenuplayer = CVAR_INIT ("dummymenuplayer", "P1", CV_HIDDEN|CV_CALL, dummymenuplayer_cons_t, Dummymenuplayer_OnChange); +consvar_t cv_dummymenuplayer = CVAR_INIT ("dummymenuplayer", "P1", CV_HIDDEN|CV_CALL, dummymenuplayer_cons_t, Dummymenuplayer_OnChange); + +struct pausemenu_s pausemenu; + +static void Dummymenuplayer_OnChange(void) +{ + if (cv_dummymenuplayer.value < 1) + CV_StealthSetValue(&cv_dummymenuplayer, splitscreen+1); + else if (cv_dummymenuplayer.value > splitscreen+1) + CV_StealthSetValue(&cv_dummymenuplayer, 1); +} + +// Pause menu! +void M_OpenPauseMenu(void) +{ + INT32 i = 0; + + currentMenu = &PAUSE_MainDef; + + // Ready the variables + pausemenu.ticker = 0; + + pausemenu.offset = 0; + pausemenu.openoffset = 256; + pausemenu.closing = false; + + currentMenu->lastOn = mpause_continue; // Make sure we select "RESUME GAME" by default + + // Now the hilarious balancing act of deciding what options should be enabled and which ones shouldn't be! + // By default, disable anything sensitive: + + PAUSE_Main[mpause_addons].status = IT_DISABLED; + PAUSE_Main[mpause_changegametype].status = IT_DISABLED; + PAUSE_Main[mpause_switchmap].status = IT_DISABLED; + PAUSE_Main[mpause_restartmap].status = IT_DISABLED; + PAUSE_Main[mpause_tryagain].status = IT_DISABLED; +#ifdef HAVE_DISCORDRPC + PAUSE_Main[mpause_discordrequests].status = IT_DISABLED; +#endif + + PAUSE_Main[mpause_spectate].status = IT_DISABLED; + PAUSE_Main[mpause_entergame].status = IT_DISABLED; + PAUSE_Main[mpause_canceljoin].status = IT_DISABLED; + PAUSE_Main[mpause_spectatemenu].status = IT_DISABLED; + PAUSE_Main[mpause_psetup].status = IT_DISABLED; + + Dummymenuplayer_OnChange(); // Make sure the consvar is within bounds of the amount of splitscreen players we have. + + if (K_CanChangeRules(false)) + { + PAUSE_Main[mpause_psetup].status = IT_STRING | IT_CALL; + + if (server || IsPlayerAdmin(consoleplayer)) + { + PAUSE_Main[mpause_changegametype].status = IT_STRING | IT_KEYHANDLER; + menugametype = gametype; + + PAUSE_Main[mpause_switchmap].status = IT_STRING | IT_CALL; + PAUSE_Main[mpause_restartmap].status = IT_STRING | IT_CALL; + PAUSE_Main[mpause_addons].status = IT_STRING | IT_CALL; + } + } + else if (!netgame && !demo.playback) + { + boolean retryallowed = (modeattacking != ATTACKING_NONE); + if (G_GametypeUsesLives()) + { + for (i = 0; i <= splitscreen; i++) + { + if (players[g_localplayers[i]].lives <= 1) + continue; + retryallowed = true; + break; + } + } + + if (retryallowed) + { + PAUSE_Main[mpause_tryagain].status = IT_STRING | IT_CALL; + } + } + + if (G_GametypeHasSpectators()) + { + if (splitscreen) + PAUSE_Main[mpause_spectatemenu].status = IT_STRING|IT_SUBMENU; + else + { + if (!players[consoleplayer].spectator) + PAUSE_Main[mpause_spectate].status = IT_STRING | IT_CALL; + else if (players[consoleplayer].pflags & PF_WANTSTOJOIN) + PAUSE_Main[mpause_canceljoin].status = IT_STRING | IT_CALL; + else + PAUSE_Main[mpause_entergame].status = IT_STRING | IT_CALL; + } + } +} + +void M_QuitPauseMenu(INT32 choice) +{ + (void)choice; + // M_PauseTick actually handles the quitting when it's been long enough. + pausemenu.closing = true; + pausemenu.openoffset = 4; +} + +void M_PauseTick(void) +{ + pausemenu.offset /= 2; + pausemenu.ticker++; + + if (pausemenu.closing) + { + pausemenu.openoffset *= 2; + if (pausemenu.openoffset > 255) + M_ClearMenus(true); + + } + else + pausemenu.openoffset /= 2; +} + +boolean M_PauseInputs(INT32 ch) +{ + + const UINT8 pid = 0; + (void) ch; + + if (pausemenu.closing) + return true; // Don't allow inputs. + + if (menucmd[pid].dpad_ud < 0) + { + M_SetMenuDelay(pid); + pausemenu.offset -= 50; // Each item is spaced by 50 px + S_StartSound(NULL, sfx_s3k5b); + M_PrevOpt(); + return true; + } + + else if (menucmd[pid].dpad_ud > 0) + { + pausemenu.offset += 50; // Each item is spaced by 50 px + S_StartSound(NULL, sfx_s3k5b); + M_NextOpt(); + M_SetMenuDelay(pid); + return true; + } + + else if (M_MenuBackPressed(pid) || M_MenuButtonPressed(pid, MBT_START)) + { + M_QuitPauseMenu(-1); + M_SetMenuDelay(pid); + return true; + } + return false; +} + +// Change gametype +void M_HandlePauseMenuGametype(INT32 choice) +{ + const UINT8 pid = 0; + const UINT32 forbidden = GTR_FORBIDMP; + + (void)choice; + + if (M_MenuConfirmPressed(pid)) + { + if (menugametype != gametype) + { + M_ClearMenus(true); + COM_ImmedExecute(va("randommap -gt %s", gametypes[menugametype]->name)); + return; + } + + M_SetMenuDelay(pid); + S_StartSound(NULL, sfx_s3k7b); + } + else if (M_MenuExtraPressed(pid)) + { + menugametype = gametype; + M_SetMenuDelay(pid); + S_StartSound(NULL, sfx_s3k7b); + } + else if (menucmd[pid].dpad_lr > 0) + { + M_NextMenuGametype(forbidden); + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } + else if (menucmd[pid].dpad_lr < 0) + { + M_PrevMenuGametype(forbidden); + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + } +} + +// Restart map +void M_RestartMap(INT32 choice) +{ + (void)choice; + M_ClearMenus(false); + COM_ImmedExecute("restartlevel"); +} + +// Try again +void M_TryAgain(INT32 choice) +{ + (void)choice; + if (demo.playback) + return; + + if (netgame || !Playing()) // Should never happen! + return; + + M_ClearMenus(false); + + if (modeattacking != ATTACKING_NONE) + { + G_CheckDemoStatus(); // Cancel recording + M_StartTimeAttack(-1); + } + else + { + G_SetRetryFlag(); + } +} + +// Pause spectate / join functions +void M_ConfirmSpectate(INT32 choice) +{ + (void)choice; + // We allow switching to spectator even if team changing is not allowed + M_QuitPauseMenu(-1); + COM_ImmedExecute("changeteam spectator"); +} + +void M_ConfirmEnterGame(INT32 choice) +{ + (void)choice; + if (!cv_allowteamchange.value) + { + M_StartMessage(M_GetText("The server is not allowing\nteam changes at this time.\n\nPress (B)\n"), NULL, MM_NOTHING); + return; + } + M_QuitPauseMenu(-1); + COM_ImmedExecute("changeteam playing"); +} + +static void M_ExitGameResponse(INT32 ch) +{ + if (ch != MA_YES) + return; + + if (modeattacking) + { + M_EndModeAttackRun(); + } + else + { + G_SetExitGameFlag(); + M_ClearMenus(true); + } +} + +void M_EndGame(INT32 choice) +{ + (void)choice; + if (demo.playback) + return; + + if (!Playing()) + return; + + M_StartMessage(M_GetText("Are you sure you want to\nreturn to the menu?\nPress (A) to confirm or (B) to cancel\n"), FUNCPTRCAST(M_ExitGameResponse), MM_YESNO); +} diff --git a/src/menus/transient/pause-replay.c b/src/menus/transient/pause-replay.c index 06b0dd594..e16bba8e7 100644 --- a/src/menus/transient/pause-replay.c +++ b/src/menus/transient/pause-replay.c @@ -2,6 +2,12 @@ /// \brief Replay popup menu #include "../../k_menu.h" +#include "../../s_sound.h" +#include "../../p_tick.h" // leveltime +#include "../../i_time.h" +#include "../../r_main.h" // R_ExecuteSetViewSize +#include "../../p_local.h" // P_InitCameraCmd +#include "../../d_main.h" // D_StartTitle menuitem_t PAUSE_PlaybackMenu[] = { @@ -38,3 +44,153 @@ menu_t PAUSE_PlaybackMenuDef = { NULL, NULL }; + +void M_EndModeAttackRun(void) +{ + G_CheckDemoStatus(); // Cancel recording + + if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) + Command_ExitGame_f(); + + M_StartControlPanel(); + + currentMenu = &PLAY_TimeAttackDef; + itemOn = currentMenu->lastOn; + + G_SetGamestate(GS_MENU); + S_ChangeMusicInternal("menu", true); + + modeattacking = ATTACKING_NONE; +} + +// Replay Playback Menu +void M_SetPlaybackMenuPointer(void) +{ + itemOn = playback_pause; +} + +void M_PlaybackRewind(INT32 choice) +{ + static tic_t lastconfirmtime; + + (void)choice; + + if (!demo.rewinding) + { + if (paused) + { + G_ConfirmRewind(leveltime-1); + paused = true; + S_PauseAudio(); + } + else + demo.rewinding = paused = true; + } + else if (lastconfirmtime + TICRATE/2 < I_GetTime()) + { + lastconfirmtime = I_GetTime(); + G_ConfirmRewind(leveltime); + } + + CV_SetValue(&cv_playbackspeed, 1); +} + +void M_PlaybackPause(INT32 choice) +{ + (void)choice; + + paused = !paused; + + if (demo.rewinding) + { + G_ConfirmRewind(leveltime); + paused = true; + S_PauseAudio(); + } + else if (paused) + S_PauseAudio(); + else + S_ResumeAudio(); + + CV_SetValue(&cv_playbackspeed, 1); +} + +void M_PlaybackFastForward(INT32 choice) +{ + (void)choice; + + if (demo.rewinding) + { + G_ConfirmRewind(leveltime); + paused = false; + S_ResumeAudio(); + } + CV_SetValue(&cv_playbackspeed, cv_playbackspeed.value == 1 ? 4 : 1); +} + +void M_PlaybackAdvance(INT32 choice) +{ + (void)choice; + + paused = false; + TryRunTics(1); + paused = true; +} + +void M_PlaybackSetViews(INT32 choice) +{ + if (choice > 0) + { + if (splitscreen < 3) + G_AdjustView(splitscreen + 2, 0, true); + } + else if (splitscreen) + { + splitscreen--; + R_ExecuteSetViewSize(); + } +} + +void M_PlaybackAdjustView(INT32 choice) +{ + G_AdjustView(itemOn - playback_viewcount, (choice > 0) ? 1 : -1, true); +} + +// this one's rather tricky +void M_PlaybackToggleFreecam(INT32 choice) +{ + (void)choice; + M_ClearMenus(true); + + // remove splitscreen: + splitscreen = 0; + R_ExecuteSetViewSize(); + + P_InitCameraCmd(); // init camera controls + if (!demo.freecam) // toggle on + { + demo.freecam = true; + democam.cam = &camera[0]; // this is rather useful + } + else // toggle off + { + demo.freecam = false; + // reset democam vars: + democam.cam = NULL; + //democam.turnheld = false; + democam.keyboardlook = false; // reset only these. localangle / aiming gets set before the cam does anything anyway + } +} + +void M_PlaybackQuit(INT32 choice) +{ + (void)choice; + G_StopDemo(); + + if (demo.inreplayhut) + M_ReplayHut(choice); + else if (modeattacking) + M_EndModeAttackRun(); + else + D_StartTitle(); +} diff --git a/src/menus/transient/virtual-keyboard.c b/src/menus/transient/virtual-keyboard.c new file mode 100644 index 000000000..3211538a3 --- /dev/null +++ b/src/menus/transient/virtual-keyboard.c @@ -0,0 +1,226 @@ +/// \file menus/transient/virtual-keyboard.c +/// \brief Keyboard input + +#include "../../k_menu.h" +#include "../../s_sound.h" +#include "../../hu_stuff.h" // shiftxform + +// Typing "sub"-menu +struct menutyping_s menutyping; + +// keyboard layouts +INT16 virtualKeyboard[5][13] = { + + {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0}, + {'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 0}, + {'a', 's', 'd', 'f', 'g', 'h', 'i', 'j', 'k', 'l', ';', '\'', '\\'}, + {'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, 0, 0}, + {KEY_SPACE, KEY_RSHIFT, KEY_BACKSPACE, KEY_CAPSLOCK, KEY_ENTER, 0, 0, 0, 0, 0, 0, 0, 0} +}; + +INT16 shift_virtualKeyboard[5][13] = { + + {'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 0}, + {'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', 0}, + {'A', 'S', 'D', 'F', 'G', 'H', 'I', 'J', 'K', 'L', ':', '\"', '|'}, + {'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 0, 0, 0}, + {KEY_SPACE, KEY_RSHIFT, KEY_BACKSPACE, KEY_CAPSLOCK, KEY_ENTER, 0, 0, 0, 0, 0, 0, 0, 0} +}; + +boolean M_ChangeStringCvar(INT32 choice) +{ + consvar_t *cv = currentMenu->menuitems[itemOn].itemaction.cvar; + char buf[MAXSTRINGLENGTH]; + size_t len; + + if (shiftdown && choice >= 32 && choice <= 127) + choice = shiftxform[choice]; + + switch (choice) + { + case KEY_BACKSPACE: + len = strlen(cv->string); + if (len > 0) + { + S_StartSound(NULL, sfx_s3k5b); // Tails + M_Memcpy(buf, cv->string, len); + buf[len-1] = 0; + CV_Set(cv, buf); + } + return true; + case KEY_DEL: + if (cv->string[0]) + { + S_StartSound(NULL, sfx_s3k5b); // Tails + CV_Set(cv, ""); + } + return true; + default: + if (choice >= 32 && choice <= 127) + { + len = strlen(cv->string); + if (len < MAXSTRINGLENGTH - 1) + { + S_StartSound(NULL, sfx_s3k5b); // Tails + M_Memcpy(buf, cv->string, len); + buf[len++] = (char)choice; + buf[len] = 0; + CV_Set(cv, buf); + } + return true; + } + break; + } + + return false; +} + +// Updates the x coordinate of the keybord so prevent it from going in weird places +static void M_UpdateKeyboardX(void) +{ + // 0s are only at the rightmost edges of the keyboard table, so just go backwards until we get something. + while (!virtualKeyboard[menutyping.keyboardy][menutyping.keyboardx]) + menutyping.keyboardx--; +} + +static boolean M_IsTypingKey(INT32 key) +{ + return key == KEY_BACKSPACE || key == KEY_ENTER || + key == KEY_ESCAPE || key == KEY_DEL || isprint(key); +} + +void M_MenuTypingInput(INT32 key) +{ + + const UINT8 pid = 0; + + // Fade-in + + if (menutyping.menutypingclose) // closing + { + menutyping.menutypingfade--; + if (!menutyping.menutypingfade) + menutyping.active = false; + + return; // prevent inputs while closing the menu. + } + else // opening + { + menutyping.menutypingfade++; + if (menutyping.menutypingfade > 9) // Don't fade all the way, but have it VERY strong to be readable + menutyping.menutypingfade = 9; + else if (menutyping.menutypingfade < 9) + return; // Don't allow typing until it's fully opened. + } + + // Determine when to check for keyboard inputs or controller inputs using menuKey, which is the key passed here as argument. + if (!menutyping.keyboardtyping) // controller inputs + { + // we pressed a keyboard input that's not any of our buttons + if (M_IsTypingKey(key) && menucmd[pid].dpad_lr == 0 && menucmd[pid].dpad_ud == 0 + && !(menucmd[pid].buttons & MBT_A) + && !(menucmd[pid].buttons & MBT_B) + && !(menucmd[pid].buttons & MBT_C) + && !(menucmd[pid].buttons & MBT_X) + && !(menucmd[pid].buttons & MBT_Y) + && !(menucmd[pid].buttons & MBT_Z)) + { + menutyping.keyboardtyping = true; + } + } + else // Keyboard inputs. + { + // On the flipside, if we're pressing any keyboard input, switch to controller inputs. + if (!M_IsTypingKey(key) && ( + M_MenuButtonPressed(pid, MBT_A) + || M_MenuButtonPressed(pid, MBT_B) + || M_MenuButtonPressed(pid, MBT_C) + || M_MenuButtonPressed(pid, MBT_X) + || M_MenuButtonPressed(pid, MBT_Y) + || M_MenuButtonPressed(pid, MBT_Z) + || menucmd[pid].dpad_lr != 0 + || menucmd[pid].dpad_ud != 0 + )) + { + menutyping.keyboardtyping = false; + return; + } + + // OTHERWISE, process keyboard inputs for typing! + if (key == KEY_ENTER || key == KEY_ESCAPE) + { + menutyping.menutypingclose = true; // close menu. + return; + } + + } + + if (menucmd[pid].delay == 0 && !menutyping.keyboardtyping) // We must check for this here because we bypass the normal delay check to allow for normal keyboard inputs + { + if (menucmd[pid].dpad_ud > 0) // down + { + menutyping.keyboardy++; + if (menutyping.keyboardy > 4) + menutyping.keyboardy = 0; + + M_UpdateKeyboardX(); + M_SetMenuDelay(pid); + S_StartSound(NULL, sfx_s3k5b); + } + else if (menucmd[pid].dpad_ud < 0) // up + { + menutyping.keyboardy--; + if (menutyping.keyboardy < 0) + menutyping.keyboardy = 4; + + M_UpdateKeyboardX(); + M_SetMenuDelay(pid); + S_StartSound(NULL, sfx_s3k5b); + } + else if (menucmd[pid].dpad_lr > 0) // right + { + menutyping.keyboardx++; + if (!virtualKeyboard[menutyping.keyboardy][menutyping.keyboardx]) + menutyping.keyboardx = 0; + + M_SetMenuDelay(pid); + S_StartSound(NULL, sfx_s3k5b); + } + else if (menucmd[pid].dpad_lr < 0) // left + { + menutyping.keyboardx--; + if (menutyping.keyboardx < 0) + { + menutyping.keyboardx = 12; + M_UpdateKeyboardX(); + } + M_SetMenuDelay(pid); + S_StartSound(NULL, sfx_s3k5b); + } + else if (M_MenuConfirmPressed(pid)) + { + // Add the character. First though, check what we're pressing.... + INT16 c = virtualKeyboard[menutyping.keyboardy][menutyping.keyboardx]; + if (menutyping.keyboardshift ^ menutyping.keyboardcapslock) + c = shift_virtualKeyboard[menutyping.keyboardy][menutyping.keyboardx]; + + if (c == KEY_RSHIFT) + menutyping.keyboardshift = !menutyping.keyboardshift; + else if (c == KEY_CAPSLOCK) + menutyping.keyboardcapslock = !menutyping.keyboardcapslock; + else if (c == KEY_ENTER) + { + menutyping.menutypingclose = true; // close menu. + return; + } + else + { + M_ChangeStringCvar((INT32)c); // Write! + menutyping.keyboardshift = false; // undo shift if it had been pressed + } + + M_SetMenuDelay(pid); + S_StartSound(NULL, sfx_s3k5b); + } + } +} From 01ddbf6dcfade5c8816d859c7605248ff82131bd Mon Sep 17 00:00:00 2001 From: Eidolon Date: Fri, 6 Jan 2023 03:29:01 -0600 Subject: [PATCH 17/32] (WIP) hardware: add render hardware interface --- src/CMakeLists.txt | 7 + src/core/CMakeLists.txt | 3 + src/core/static_vec.hpp | 288 ++ src/d_main.c | 3 + src/hwr2/CMakeLists.txt | 8 + src/hwr2/pass.cpp | 3 + src/hwr2/pass.hpp | 35 + src/hwr2/pass_imgui.cpp | 255 ++ src/hwr2/pass_imgui.hpp | 52 + src/hwr2/pass_software.cpp | 284 ++ src/hwr2/pass_software.hpp | 44 + src/i_video.h | 15 +- src/i_video_common.cpp | 100 + src/r_data.c | 6 - src/rhi/CMakeLists.txt | 7 + src/rhi/gl3_core/CMakeLists.txt | 4 + src/rhi/gl3_core/gl3_core_rhi.cpp | 1260 +++++++ src/rhi/gl3_core/gl3_core_rhi.hpp | 148 + src/rhi/gles2/CMakeLists.txt | 1 + src/rhi/gles2/gles2_rhi.cpp | 1122 ++++++ src/rhi/gles2/gles2_rhi.hpp | 135 + src/rhi/handle.hpp | 317 ++ src/rhi/rhi.cpp | 51 + src/rhi/rhi.hpp | 466 +++ src/screen.h | 2 + src/sdl/CMakeLists.txt | 2 + src/sdl/i_video.cpp | 839 ++--- src/sdl/new_sound.cpp | 3 +- src/sdl/ogl_sdl.h | 1 - src/sdl/rhi_gl3_core_platform.cpp | 56 + src/sdl/rhi_gl3_core_platform.hpp | 23 + src/sdl/rhi_gles2_platform.cpp | 56 + src/sdl/rhi_gles2_platform.hpp | 23 + thirdparty/CMakeLists.txt | 3 + thirdparty/cpm-fmt.cmake | 6 + thirdparty/cpm-imgui.cmake | 34 + thirdparty/glad/CMakeLists.txt | 3 + thirdparty/glad/include/KHR/khrplatform.h | 311 ++ thirdparty/glad/include/glad/gl.h | 3795 +++++++++++++++++++++ thirdparty/glad/include/glad/gles2.h | 861 +++++ thirdparty/glad/src/gl.c | 2274 ++++++++++++ thirdparty/glad/src/gles2.c | 351 ++ thirdparty/imgui_config/srb2_imconfig.h | 38 + 43 files changed, 12729 insertions(+), 566 deletions(-) create mode 100644 src/core/CMakeLists.txt create mode 100644 src/core/static_vec.hpp create mode 100644 src/hwr2/CMakeLists.txt create mode 100644 src/hwr2/pass.cpp create mode 100644 src/hwr2/pass.hpp create mode 100644 src/hwr2/pass_imgui.cpp create mode 100644 src/hwr2/pass_imgui.hpp create mode 100644 src/hwr2/pass_software.cpp create mode 100644 src/hwr2/pass_software.hpp create mode 100644 src/i_video_common.cpp create mode 100644 src/rhi/CMakeLists.txt create mode 100644 src/rhi/gl3_core/CMakeLists.txt create mode 100644 src/rhi/gl3_core/gl3_core_rhi.cpp create mode 100644 src/rhi/gl3_core/gl3_core_rhi.hpp create mode 100644 src/rhi/gles2/CMakeLists.txt create mode 100644 src/rhi/gles2/gles2_rhi.cpp create mode 100644 src/rhi/gles2/gles2_rhi.hpp create mode 100644 src/rhi/handle.hpp create mode 100644 src/rhi/rhi.cpp create mode 100644 src/rhi/rhi.hpp create mode 100644 src/sdl/rhi_gl3_core_platform.cpp create mode 100644 src/sdl/rhi_gl3_core_platform.hpp create mode 100644 src/sdl/rhi_gles2_platform.cpp create mode 100644 src/sdl/rhi_gles2_platform.hpp create mode 100644 thirdparty/cpm-fmt.cmake create mode 100644 thirdparty/cpm-imgui.cmake create mode 100644 thirdparty/glad/CMakeLists.txt create mode 100644 thirdparty/glad/include/KHR/khrplatform.h create mode 100644 thirdparty/glad/include/glad/gl.h create mode 100644 thirdparty/glad/include/glad/gles2.h create mode 100644 thirdparty/glad/src/gl.c create mode 100644 thirdparty/glad/src/gles2.c create mode 100644 thirdparty/imgui_config/srb2_imconfig.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5197ab3d6..87676244f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -26,6 +26,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 font.c hu_stuff.c i_time.c + i_video_common.cpp y_inter.c st_stuff.c m_aatree.c @@ -224,6 +225,9 @@ target_sources(SRB2SDL2 PRIVATE discord.c stun.c) target_link_libraries(SRB2SDL2 PRIVATE tcbrindle::span) target_link_libraries(SRB2SDL2 PRIVATE stb_vorbis) target_link_libraries(SRB2SDL2 PRIVATE xmp-lite::xmp-lite) +target_link_libraries(SRB2SDL2 PRIVATE glad::glad) +target_link_libraries(SRB2SDL2 PRIVATE fmt) +target_link_libraries(SRB2SDL2 PRIVATE imgui::imgui) set(SRB2_HAVE_THREADS ON) target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_THREADS) @@ -528,9 +532,12 @@ if(SRB2_CONFIG_PROFILEMODE AND "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") endif() add_subdirectory(audio) +add_subdirectory(core) +add_subdirectory(hwr2) add_subdirectory(io) add_subdirectory(sdl) add_subdirectory(objects) +add_subdirectory(rhi) add_subdirectory(tests) add_subdirectory(menus) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt new file mode 100644 index 000000000..f4ee13e1f --- /dev/null +++ b/src/core/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(SRB2SDL2 PRIVATE + static_vec.hpp +) diff --git a/src/core/static_vec.hpp b/src/core/static_vec.hpp new file mode 100644 index 000000000..f7bd26d69 --- /dev/null +++ b/src/core/static_vec.hpp @@ -0,0 +1,288 @@ +#ifndef __SRB2_CORE_STATIC_VEC_HPP__ +#define __SRB2_CORE_STATIC_VEC_HPP__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../cxxutil.hpp" + +namespace srb2 { + +template +class StaticVec +{ + std::array arr_ {{}}; + size_t size_ = 0; + +public: + constexpr StaticVec() {} + + StaticVec(const StaticVec& rhs) + { + for (size_t i = size_; i > 0; i--) + { + arr_[i] = T(); + } + size_ = rhs.size(); + for (size_t i = 0; i < size_; i++) + { + arr_[i] = rhs.arr_[i]; + } + } + + StaticVec(StaticVec&& rhs) noexcept(std::is_nothrow_move_assignable_v) + { + for (size_t i = size_; i > 0; i--) + { + arr_[i] = T(); + } + size_ = rhs.size(); + for (size_t i = 0; i < size_; i++) + { + arr_[i] = std::move(rhs.arr_[i]); + } + while (rhs.size() > 0) + { + rhs.pop_back(); + } + } + + constexpr StaticVec(std::initializer_list list) noexcept(std::is_nothrow_move_assignable_v) + { + size_ = list.size(); + size_t i = 0; + for (auto itr = list.begin(); itr != list.end(); itr++) + { + arr_[i] = *itr; + i++; + } + } + + ~StaticVec() = default; + + StaticVec& operator=(const StaticVec& rhs) + { + for (size_t i = size_; i > 0; i--) + { + arr_[i] = T(); + } + size_ = rhs.size(); + for (size_t i = 0; i < size_; i++) + { + arr_[i] = rhs.arr_[i]; + } + return *this; + } + + StaticVec& operator=(StaticVec&& rhs) noexcept(std::is_nothrow_move_constructible_v) + { + for (size_t i = size_; i > 0; i--) + { + arr_[i] = T(); + } + size_ = rhs.size(); + for (size_t i = 0; i < size_; i++) + { + arr_[i] = std::move(rhs.arr_[i]); + } + while (rhs.size() > 0) + { + rhs.pop_back(); + } + return *this; + } + + void push_back(const T& value) + { + arr_[size_++] = value; + } + + void pop_back() + { + arr_[size_--] = T(); + } + + void resize(size_t size, T value = T()) + { + if (size >= Limit) + { + throw std::length_error("new size >= Capacity"); + } + + if (size == size_) + { + return; + } + else if (size < size_) + { + while (size_ > size) + { + pop_back(); + } + } + else + { + while (size_ < size) + { + push_back(value); + } + } + } + + constexpr T* begin() noexcept + { + return &arr_[0]; + } + + constexpr const T* begin() const noexcept + { + return cbegin(); + } + + constexpr const T* cbegin() const noexcept + { + return &arr_[0]; + } + + constexpr T* end() noexcept + { + return &arr_[size_]; + } + + constexpr const T* end() const noexcept + { + return cend(); + } + + constexpr const T* cend() const noexcept + { + return &arr_[size_]; + } + + constexpr std::reverse_iterator rbegin() noexcept + { + return &arr_[size_]; + } + + constexpr std::reverse_iterator crbegin() const noexcept + { + return &arr_[size_]; + } + + constexpr std::reverse_iterator rend() noexcept + { + return &arr_[0]; + } + + constexpr std::reverse_iterator crend() const noexcept + { + return &arr_[0]; + } + + constexpr bool empty() const noexcept + { + return size_ == 0; + } + + constexpr size_t size() const noexcept + { + return size_; + } + + constexpr size_t capacity() const noexcept + { + return Limit; + } + + constexpr size_t max_size() const noexcept + { + return Limit; + } + + constexpr T& operator[](size_t index) noexcept + { + return arr_[index]; + } + + T& at(size_t index) + { + if (index >= size_) + { + throw std::out_of_range("index >= size"); + } + return this[index]; + } + + constexpr const T& operator[](size_t index) const noexcept + { + return arr_[index]; + } + + const T& at(size_t index) const + { + if (index >= size_) + { + throw std::out_of_range("index >= size"); + } + return this[index]; + } + + T& front() + { + return *arr_[0]; + } + + T& back() + { + return *arr_[size_ - 1]; + } +}; + +} // namespace srb2 + +template +bool operator==(const srb2::StaticVec& lhs, const srb2::StaticVec& rhs) +{ + const size_t size = lhs.size(); + if (size != rhs.size()) + { + return false; + } + for (size_t i = 0; i < lhs; i++) { + if (rhs[i] != lhs[i]) + { + return false; + } + } + return true; +} + +template +bool operator!=(const srb2::StaticVec& lhs, const srb2::StaticVec& rhs) +{ + return !(lhs == rhs); +} + +template +struct std::hash> +{ + uint64_t operator()(const srb2::StaticVec& input) const + { + constexpr const uint64_t prime { 0x00000100000001B3 }; + std::size_t ret { 0xcbf29ce484222325 }; + + for (auto itr = input.begin(); itr != input.end(); itr++) + { + ret = (ret * prime) ^ std::hash(*itr); + } + return ret; + } +}; + +#endif // __SRB2_CORE_STATIC_VEC_HPP__ diff --git a/src/d_main.c b/src/d_main.c index 128fe9c0b..94183e53d 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1115,6 +1115,7 @@ static void IdentifyVersion(void) #define PATCHNAME "MISC_SCRIPTS.pk3" #define UNLOCKNAME "MISC_UNLOCKS.pk3" #define MUSICNAME "MISC_MUSIC.PK3" +#define SHADERSNAME "MISC_SHADERS.pk3" //// #else //// @@ -1123,6 +1124,7 @@ static void IdentifyVersion(void) #define PATCHNAME "scripts.pk3" #define UNLOCKNAME "unlocks.pk3" #define MUSICNAME "music.pk3" +#define SHADERSNAME "shaders.pk3" //// #endif //// @@ -1140,6 +1142,7 @@ static void IdentifyVersion(void) #if defined(DEVELOP) && defined(UNLOCKTESTING) D_AddFile(startupiwads, va(pandf,srb2waddir,UNLOCKNAME)); #endif + D_AddFile(startupiwads, va(pandf,srb2waddir,SHADERSNAME)); //// #undef TEXTURESNAME #undef MAPSNAME diff --git a/src/hwr2/CMakeLists.txt b/src/hwr2/CMakeLists.txt new file mode 100644 index 000000000..504818105 --- /dev/null +++ b/src/hwr2/CMakeLists.txt @@ -0,0 +1,8 @@ +target_sources(SRB2SDL2 PRIVATE + pass_imgui.cpp + pass_imgui.hpp + pass_software.cpp + pass_software.hpp + pass.cpp + pass.hpp +) diff --git a/src/hwr2/pass.cpp b/src/hwr2/pass.cpp new file mode 100644 index 000000000..48b331492 --- /dev/null +++ b/src/hwr2/pass.cpp @@ -0,0 +1,3 @@ +#include "pass.hpp" + +srb2::hwr2::Pass::~Pass() = default; diff --git a/src/hwr2/pass.hpp b/src/hwr2/pass.hpp new file mode 100644 index 000000000..2556bf8f8 --- /dev/null +++ b/src/hwr2/pass.hpp @@ -0,0 +1,35 @@ +#ifndef __SRB2_HWR2_PASS_HPP__ +#define __SRB2_HWR2_PASS_HPP__ + +#include "../rhi/rhi.hpp" + +namespace srb2::hwr2 +{ + +/// @brief A rendering pass which performs logic during each phase of a frame render. +/// During rendering, all registered Pass's individual stages will be run together. +struct Pass { + virtual ~Pass(); + + /// @brief Perform rendering logic and create necessary GPU resources. + /// @param rhi + virtual void prepass(rhi::Rhi& rhi) = 0; + + /// @brief Upload contents for needed GPU resources. + /// @param rhi + /// @param ctx + virtual void transfer(rhi::Rhi& rhi, rhi::Handle ctx) = 0; + + /// @brief Issue draw calls. + /// @param rhi + /// @param ctx + virtual void graphics(rhi::Rhi& rhi, rhi::Handle ctx) = 0; + + /// @brief Cleanup GPU resources. Transient resources should be cleaned up here. + /// @param rhi + virtual void postpass(rhi::Rhi& rhi) = 0; +}; + +} // namespace srb2::hwr2 + +#endif // __SRB2_HWR2_PASS_HPP__ diff --git a/src/hwr2/pass_imgui.cpp b/src/hwr2/pass_imgui.cpp new file mode 100644 index 000000000..6d8e02861 --- /dev/null +++ b/src/hwr2/pass_imgui.cpp @@ -0,0 +1,255 @@ +#include "pass_imgui.hpp" + +#include + +#include "../v_video.h" + +using namespace srb2; +using namespace srb2::hwr2; +using namespace srb2::rhi; + +static const PipelineDesc kPipelineDesc = +{ + PipelineProgram::kUnshaded, + { + { + {sizeof(ImDrawVert)} + }, + { + {VertexAttributeName::kPosition, 0, 0}, + {VertexAttributeName::kTexCoord0, 0, 12}, + {VertexAttributeName::kColor, 0, 24} + } + }, + {{ + {{UniformName::kProjection}}, + {{UniformName::kModelView, UniformName::kTexCoord0Transform}} + }}, + {{ + SamplerName::kSampler0 + }}, + PipelineDepthAttachmentDesc { + PixelFormat::kDepth16, + CompareFunc::kAlways, + true + }, + { + PixelFormat::kRGBA8, + BlendDesc { + BlendFactor::kSourceAlpha, + BlendFactor::kOneMinusSourceAlpha, + BlendFunction::kAdd, + BlendFactor::kOne, + BlendFactor::kOneMinusSourceAlpha, + BlendFunction::kAdd + }, + {true, true, true, true} + }, + PrimitiveType::kTriangles, + CullMode::kNone, + FaceWinding::kCounterClockwise, + {0.f, 0.f, 0.f, 1.f} +}; + +ImguiPass::~ImguiPass() = default; + +void ImguiPass::prepass(Rhi& rhi) +{ + if (!pipeline_) + { + pipeline_ = rhi.create_pipeline(kPipelineDesc); + } + + ImGuiIO& io = ImGui::GetIO(); + + if (!font_atlas_) + { + unsigned char* pixels; + int width; + int height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + + uint32_t uwidth = static_cast(width); + uint32_t uheight = static_cast(height); + + font_atlas_ = rhi.create_texture({TextureFormat::kRGBA, uwidth, uheight}); + io.Fonts->SetTexID(font_atlas_); + } + + ImGui::Render(); + + ImDrawData* data = ImGui::GetDrawData(); + ImVec2 clip_off(data->DisplayPos); + ImVec2 clip_scale(data->FramebufferScale); + tcb::span draw_lists = tcb::span(data->CmdLists, data->CmdListsCount); + + for (auto list : draw_lists) + { + Handle vbo = rhi.create_buffer( + { + static_cast(list->VtxBuffer.size_in_bytes()), + BufferType::kVertexBuffer, + BufferUsage::kImmutable + } + ); + Handle ibo = rhi.create_buffer( + { + static_cast(list->IdxBuffer.size_in_bytes()), + BufferType::kIndexBuffer, + BufferUsage::kImmutable + } + ); + + DrawList hwr2_list; + hwr2_list.list = list; + hwr2_list.vbo = vbo; + hwr2_list.ibo = ibo; + + for (auto& cmd : list->CmdBuffer) + { + if (cmd.UserCallback) + { + cmd.UserCallback(list, &cmd); + continue; + } + + ImVec2 clip_min((cmd.ClipRect.x - clip_off.x) * clip_scale.x, (cmd.ClipRect.y - clip_off.y) * clip_scale.y); + ImVec2 clip_max((cmd.ClipRect.z - clip_off.x) * clip_scale.x, (cmd.ClipRect.w - clip_off.y) * clip_scale.y); + if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) + { + continue; + } + + DrawCmd draw_cmd; + ImTextureID tex_id = cmd.GetTexID(); + draw_cmd.tex = tex_id; + draw_cmd.v_offset = cmd.VtxOffset; + draw_cmd.i_offset = cmd.IdxOffset; + draw_cmd.elems = cmd.ElemCount; + draw_cmd.clip = + { + static_cast(clip_min.x), + static_cast((data->DisplaySize.y * data->FramebufferScale.y) - clip_max.y), + static_cast(clip_max.x - clip_min.x), + static_cast(clip_max.y - clip_min.y) + }; + hwr2_list.cmds.push_back(std::move(draw_cmd)); + } + draw_lists_.push_back(std::move(hwr2_list)); + } +} + +void ImguiPass::transfer(Rhi& rhi, Handle ctx) +{ + ImGuiIO& io = ImGui::GetIO(); + + { + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + rhi.update_texture( + ctx, + font_atlas_, + {0, 0, static_cast(width), static_cast(height)}, + rhi::PixelFormat::kRGBA8, + tcb::as_bytes(tcb::span(pixels, static_cast(width * height * 4))) + ); + } + + for (auto& draw_list : draw_lists_) + { + Handle vbo = draw_list.vbo; + Handle ibo = draw_list.ibo; + + ImDrawList* im_list = static_cast(draw_list.list); + + for (auto& vtx : im_list->VtxBuffer) + { + vtx.pos.z = 0.f; + vtx.colf[0] = ((vtx.col & 0xFF) >> 0) / 255.f; + vtx.colf[1] = ((vtx.col & 0xFF00) >> 8) / 255.f; + vtx.colf[2] = ((vtx.col & 0xFF0000) >> 16) / 255.f; + vtx.colf[3] = ((vtx.col & 0xFF000000) >> 24) / 255.f; + } + + tcb::span vert_span = tcb::span(im_list->VtxBuffer.Data, im_list->VtxBuffer.size()); + rhi.update_buffer_contents(ctx, vbo, 0, tcb::as_bytes(vert_span)); + + tcb::span index_span = tcb::span(im_list->IdxBuffer.Data, im_list->IdxBuffer.size()); + rhi.update_buffer_contents(ctx, ibo, 0, tcb::as_bytes(index_span)); + + // Uniform sets + std::array g1_uniforms = + {{ + // Projection + std::array, 4> + {{ + {2.f / vid.realwidth, 0.f, 0.f, 0.f}, + {0.f, 2.f / vid.realheight, 0.f, 0.f}, + {0.f, 0.f, 1.f, 0.f}, + {-1.f, 1.f, 0.f, 1.f} + }}, + }}; + std::array g2_uniforms = + {{ + // ModelView + std::array, 4> + {{ + {1.f, 0.f, 0.f, 0.f}, + {0.f, -1.f, 0.f, 0.f}, + {0.f, 0.f, 1.f, 0.f}, + {0.f, 0, 0.f, 1.f} + }}, + // Texcoord0 Transform + std::array, 3> + {{ + {1.f, 0.f, 0.f}, + {0.f, 1.f, 0.f}, + {0.f, 0.f, 1.f} + }} + }}; + Handle us_1 = rhi.create_uniform_set(ctx, {g1_uniforms}); + Handle us_2 = rhi.create_uniform_set(ctx, {g2_uniforms}); + + draw_list.us_1 = us_1; + draw_list.us_2 = us_2; + + for (auto& draw_cmd : draw_list.cmds) + { + // Binding set + std::array vbos = {{0, vbo}}; + std::array tbs = {{{rhi::SamplerName::kSampler0, draw_cmd.tex}}}; + rhi::Handle binding_set = rhi.create_binding_set(ctx, pipeline_, {vbos, tbs}); + draw_cmd.binding_set = binding_set; + } + } +} + +void ImguiPass::graphics(Rhi& rhi, Handle ctx) +{ + rhi.begin_default_render_pass(ctx, false); + rhi.bind_pipeline(ctx, pipeline_); + for (auto& draw_list : draw_lists_) + { + rhi.bind_uniform_set(ctx, 0, draw_list.us_1); + rhi.bind_uniform_set(ctx, 1, draw_list.us_2); + for (auto& cmd : draw_list.cmds) + { + rhi.bind_binding_set(ctx, cmd.binding_set); + rhi.bind_index_buffer(ctx, draw_list.ibo); + rhi.set_scissor(ctx, cmd.clip); + rhi.draw_indexed(ctx, cmd.elems, cmd.i_offset); + } + } + rhi.end_render_pass(ctx); +} + +void ImguiPass::postpass(Rhi& rhi) +{ + for (auto& list : draw_lists_) + { + rhi.destroy_buffer(list.vbo); + rhi.destroy_buffer(list.ibo); + } + draw_lists_.clear(); +} diff --git a/src/hwr2/pass_imgui.hpp b/src/hwr2/pass_imgui.hpp new file mode 100644 index 000000000..280e7fc9c --- /dev/null +++ b/src/hwr2/pass_imgui.hpp @@ -0,0 +1,52 @@ +#ifndef __SRB2_HWR2_PASS_IMGUI_HPP__ +#define __SRB2_HWR2_PASS_IMGUI_HPP__ + +#include + +#include "../rhi/rhi.hpp" +#include "pass.hpp" + +namespace srb2::hwr2 +{ + +class ImguiPass : public Pass +{ + struct DrawCmd + { + rhi::Handle tex; + uint32_t v_offset; + uint32_t elems; + uint32_t i_offset; + rhi::Rect clip; + rhi::Handle binding_set; + }; + struct DrawList + { + void* list; + rhi::Handle vbo; + rhi::Handle ibo; + rhi::Handle us_1; + rhi::Handle us_2; + std::vector cmds; + }; + + rhi::Handle pipeline_; + rhi::Handle font_atlas_; + + std::vector draw_lists_; + +public: + virtual ~ImguiPass(); + + virtual void prepass(rhi::Rhi& rhi) override; + + virtual void transfer(rhi::Rhi& rhi, rhi::Handle ctx) override; + + virtual void graphics(rhi::Rhi& rhi, rhi::Handle ctx) override; + + virtual void postpass(rhi::Rhi& rhi) override; +}; + +} // namespace srb2::hwr2 + +#endif // __SRB2_HWR2_PASS_IMGUI_HPP__ diff --git a/src/hwr2/pass_software.cpp b/src/hwr2/pass_software.cpp new file mode 100644 index 000000000..4876a52cd --- /dev/null +++ b/src/hwr2/pass_software.cpp @@ -0,0 +1,284 @@ +#include "pass_software.hpp" + +#include + +#include + +#include "../cxxutil.hpp" +#include "../d_netcmd.h" +#ifdef HAVE_DISCORDRPC +#include "../discord.h" +#endif +#include "../doomstat.h" +#include "../st_stuff.h" +#include "../s_sound.h" +#include "../v_video.h" + +using namespace srb2; +using namespace srb2::hwr2; +using namespace srb2::rhi; + +SoftwareBlitPass::~SoftwareBlitPass() = default; + +namespace +{ +struct SwBlitVertex +{ + float x = 0.f; + float y = 0.f; + float z = 0.f; + float u = 0.f; + float v = 0.f; +}; +} // namespace + +static const SwBlitVertex kVerts[] = +{ + {-.5f, -.5f, 0.f, 0.f, 0.f}, + {.5f, -.5f, 0.f, 1.f, 0.f}, + {-.5f, .5f, 0.f, 0.f, 1.f}, + {.5f, .5f, 0.f, 1.f, 1.f} +}; + +static const uint16_t kIndices[] = {0, 1, 2, 1, 3, 2}; + +static const PipelineDesc kPipelineDescription = +{ + PipelineProgram::kUnshadedPaletted, + { + { + {sizeof(SwBlitVertex)} + }, + { + {VertexAttributeName::kPosition, 0, 0}, + {VertexAttributeName::kTexCoord0, 0, 12} + } + }, + {{ + {{UniformName::kProjection}}, + {{UniformName::kModelView, UniformName::kTexCoord0Transform}} + }}, + {{ + // R8 index texture + SamplerName::kSampler0, + // 256x1 palette texture + SamplerName::kSampler1 + }}, + std::nullopt, + { + PixelFormat::kRGBA8, + std::nullopt, + {true, true, true, true} + }, + PrimitiveType::kTriangles, + CullMode::kNone, + FaceWinding::kCounterClockwise, + {0.f, 0.f, 0.f, 1.f} +}; + +static uint32_t next_pow_of_2(uint32_t in) +{ + in--; + in |= in >> 1; + in |= in >> 2; + in |= in >> 4; + in |= in >> 8; + in |= in >> 16; + in++; + return in; +} + +static void temp_legacy_finishupdate_draws() +{ + SCR_CalculateFPS(); + if (st_overlay) + { + if (cv_ticrate.value) + SCR_DisplayTicRate(); + + if (cv_showping.value && netgame && + ( consoleplayer != serverplayer || ! server_lagless )) + { + if (server_lagless) + { + if (consoleplayer != serverplayer) + SCR_DisplayLocalPing(); + } + else + { + for ( + int player = 1; + player < MAXPLAYERS; + player++ + ){ + if (D_IsPlayerHumanAndGaming(player)) + { + SCR_DisplayLocalPing(); + break; + } + } + } + } + if (cv_mindelay.value && consoleplayer == serverplayer && Playing()) + SCR_DisplayLocalPing(); + } + + if (marathonmode) + SCR_DisplayMarathonInfo(); + + // draw captions if enabled + if (cv_closedcaptioning.value) + SCR_ClosedCaptions(); + +#ifdef HAVE_DISCORDRPC + if (discordRequestList != NULL) + ST_AskToJoinEnvelope(); +#endif +} + +void SoftwareBlitPass::prepass(Rhi& rhi) +{ + if (!pipeline_) + { + pipeline_ = rhi.create_pipeline(kPipelineDescription); + } + + if (!quad_vbo_) + { + quad_vbo_ = rhi.create_buffer({sizeof(kVerts), BufferType::kVertexBuffer, BufferUsage::kImmutable}); + quad_vbo_needs_upload_ = true; + } + + if (!quad_ibo_) + { + quad_ibo_ = rhi.create_buffer({sizeof(kIndices), BufferType::kIndexBuffer, BufferUsage::kImmutable}); + quad_ibo_needs_upload_ = true; + } + + temp_legacy_finishupdate_draws(); + + uint32_t vid_width = static_cast(vid.width); + uint32_t vid_height = static_cast(vid.height); + + if (screen_tex_ && (screen_tex_width_ < vid_width || screen_tex_height_ < vid_height)) + { + rhi.destroy_texture(screen_tex_); + screen_tex_ = kNullHandle; + } + + if (!screen_tex_) + { + screen_tex_width_ = next_pow_of_2(vid_width); + screen_tex_height_ = next_pow_of_2(vid_height); + screen_tex_ = rhi.create_texture({TextureFormat::kLuminance, screen_tex_width_, screen_tex_height_}); + } + + if (!palette_tex_) + { + palette_tex_ = rhi.create_texture({TextureFormat::kRGBA, 256, 1}); + } +} + +void SoftwareBlitPass::upload_screen(Rhi& rhi, Handle ctx) +{ + rhi::Rect screen_rect = { + 0, + 0, + static_cast(vid.width), + static_cast(vid.height) + }; + + tcb::span screen_span = tcb::span(vid.buffer, static_cast(vid.width * vid.height)); + rhi.update_texture(ctx, screen_tex_, screen_rect, rhi::PixelFormat::kR8, tcb::as_bytes(screen_span)); +} + +void SoftwareBlitPass::upload_palette(Rhi& rhi, Handle ctx) +{ + // Unfortunately, pMasterPalette must be swizzled to get a linear layout. + // Maybe some adjustments to palette storage can make this a straight upload. + std::array palette_32; + for (size_t i = 0; i < 256; i++) + { + palette_32[i] = pMasterPalette[i].s; + } + rhi.update_texture(ctx, palette_tex_, {0, 0, 256, 1}, rhi::PixelFormat::kRGBA8, tcb::as_bytes(tcb::span(palette_32))); +} + +void SoftwareBlitPass::transfer(Rhi& rhi, Handle ctx) +{ + if (quad_vbo_needs_upload_ && quad_vbo_) + { + rhi.update_buffer_contents(ctx, quad_vbo_, 0, tcb::as_bytes(tcb::span(kVerts))); + quad_vbo_needs_upload_ = false; + } + + if (quad_ibo_needs_upload_ && quad_ibo_) + { + rhi.update_buffer_contents(ctx, quad_ibo_, 0, tcb::as_bytes(tcb::span(kIndices))); + quad_ibo_needs_upload_ = false; + } + + upload_screen(rhi, ctx); + upload_palette(rhi, ctx); + + // Calculate aspect ratio for black borders + float aspect = static_cast(vid.width) / static_cast(vid.height); + float real_aspect = static_cast(vid.realwidth) / static_cast(vid.realheight); + bool taller = aspect > real_aspect; + + std::array g1_uniforms = {{ + // Projection + std::array, 4> {{ + {taller ? 1.f : 1.f / real_aspect, 0.f, 0.f, 0.f}, + {0.f, taller ? -1.f / (1.f / real_aspect) : -1.f, 0.f, 0.f}, + {0.f, 0.f, 1.f, 0.f}, + {0.f, 0.f, 0.f, 1.f} + }}, + }}; + + std::array g2_uniforms = + {{ + // ModelView + std::array, 4> + {{ + {taller ? 2.f : 2.f * aspect, 0.f, 0.f, 0.f}, + {0.f, taller ? 2.f * (1.f / aspect) : 2.f, 0.f, 0.f}, + {0.f, 0.f, 1.f, 0.f}, + {0.f, 0.f, 0.f, 1.f} + }}, + // Texcoord0 Transform + std::array, 3> + {{ + {vid.width / static_cast(screen_tex_width_), 0.f, 0.f}, + {0.f, vid.height / static_cast(screen_tex_height_), 0.f}, + {0.f, 0.f, 1.f} + }} + }}; + + uniform_sets_[0] = rhi.create_uniform_set(ctx, {g1_uniforms}); + uniform_sets_[1] = rhi.create_uniform_set(ctx, {g2_uniforms}); + + std::array vbs = {{{0, quad_vbo_}}}; + std::array tbs = {{ + {rhi::SamplerName::kSampler0, screen_tex_}, + {rhi::SamplerName::kSampler1, palette_tex_} + }}; + binding_set_ = rhi.create_binding_set(ctx, pipeline_, {vbs, tbs}); +} + +void SoftwareBlitPass::graphics(Rhi& rhi, Handle ctx) +{ + rhi.begin_default_render_pass(ctx, true); + rhi.bind_pipeline(ctx, pipeline_); + rhi.bind_uniform_set(ctx, 0, uniform_sets_[0]); + rhi.bind_uniform_set(ctx, 1, uniform_sets_[1]); + rhi.bind_binding_set(ctx, binding_set_); + rhi.bind_index_buffer(ctx, quad_ibo_); + rhi.draw_indexed(ctx, 6, 0); + rhi.end_render_pass(ctx); +} + +void SoftwareBlitPass::postpass(Rhi& rhi) +{ + // no-op +} diff --git a/src/hwr2/pass_software.hpp b/src/hwr2/pass_software.hpp new file mode 100644 index 000000000..f36c82973 --- /dev/null +++ b/src/hwr2/pass_software.hpp @@ -0,0 +1,44 @@ +#ifndef __SRB2_HWR2_PASS_SOFTWARE_HPP__ +#define __SRB2_HWR2_PASS_SOFTWARE_HPP__ + +#include + +#include "../rhi/rhi.hpp" +#include "pass.hpp" + +namespace srb2::hwr2 +{ + +class SoftwareBlitPass : public Pass +{ + rhi::Handle pipeline_; + rhi::Handle screen_tex_; + rhi::Handle palette_tex_; + rhi::Handle quad_vbo_; + rhi::Handle quad_ibo_; + std::array, 2> uniform_sets_; + rhi::Handle binding_set_; + + uint32_t screen_tex_width_ = 0; + uint32_t screen_tex_height_ = 0; + bool quad_vbo_needs_upload_ = false; + bool quad_ibo_needs_upload_ = false; + + void upload_screen(rhi::Rhi& rhi, rhi::Handle ctx); + void upload_palette(rhi::Rhi& rhi, rhi::Handle ctx); + +public: + virtual ~SoftwareBlitPass(); + + virtual void prepass(rhi::Rhi& rhi) override; + + virtual void transfer(rhi::Rhi& rhi, rhi::Handle ctx) override; + + virtual void graphics(rhi::Rhi& rhi, rhi::Handle ctx) override; + + virtual void postpass(rhi::Rhi& rhi) override; +}; + +} // namespace srb2::hwr2 + +#endif // __SRB2_HWR2_PASS_SOFTWARE_HPP__ diff --git a/src/i_video.h b/src/i_video.h index 1c9a9a64c..a80bd33dc 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -17,6 +17,17 @@ #include "doomtype.h" #ifdef __cplusplus + +#include "rhi/rhi.hpp" + +namespace srb2::sys { + +extern rhi::Handle g_current_rhi; + +rhi::Rhi* get_rhi(rhi::Handle handle); + +} // namespace + extern "C" { #endif @@ -44,10 +55,6 @@ extern rendermode_t rendermode; */ extern rendermode_t chosenrendermode; -/** \brief use highcolor modes if true -*/ -extern boolean highcolor; - /** \brief setup video mode */ void I_StartupGraphics(void); diff --git a/src/i_video_common.cpp b/src/i_video_common.cpp new file mode 100644 index 000000000..cd99ed618 --- /dev/null +++ b/src/i_video_common.cpp @@ -0,0 +1,100 @@ +#include "i_video.h" + +#include +#include +#include + +#include + +#include "cxxutil.hpp" +#include "v_video.h" +#include "hwr2/pass_imgui.hpp" +#include "hwr2/pass_software.hpp" + +using namespace srb2; +using namespace srb2::hwr2; +using namespace srb2::rhi; + +static SoftwareBlitPass g_sw_pass; +static ImguiPass g_imgui_pass; + +Handle srb2::sys::g_current_rhi = kNullHandle; + +static bool rhi_changed() +{ + return false; +} + +void I_FinishUpdate(void) +{ + if (rendermode == render_none) + { + return; + } + + // TODO move this to srb2loop + ImGuiIO& io = ImGui::GetIO(); + io.DisplaySize.x = vid.realwidth; + io.DisplaySize.y = vid.realheight; + ImGui::NewFrame(); + + if (rhi_changed()) + { + // reinitialize passes + g_sw_pass = SoftwareBlitPass(); + g_imgui_pass = ImguiPass(); + } + + rhi::Rhi* rhi = sys::get_rhi(sys::g_current_rhi); + + if (rhi == nullptr) + { + // ??? + return; + } + + // Prepare phase + if (rendermode == render_soft) + { + g_sw_pass.prepass(*rhi); + } + g_imgui_pass.prepass(*rhi); + + // Transfer phase + Handle tc; + tc = rhi->begin_transfer(); + + if (rendermode == render_soft) + { + g_sw_pass.transfer(*rhi, tc); + } + g_imgui_pass.transfer(*rhi, tc); + + rhi->end_transfer(tc); + + // Graphics phase + Handle gc; + gc = rhi->begin_graphics(); + + // Standard drawing passes... + if (rendermode == render_soft) + { + g_sw_pass.graphics(*rhi, gc); + } + g_imgui_pass.graphics(*rhi, gc); + + rhi->end_graphics(gc); + + // Postpass phase + if (rendermode == render_soft) + { + g_sw_pass.postpass(*rhi); + } + g_imgui_pass.postpass(*rhi); + + // Present + + rhi->present(); + + rhi->finish(); +} diff --git a/src/r_data.c b/src/r_data.c index 353a9bbf5..0174ee9ef 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1167,12 +1167,6 @@ static void R_Init8to16(void) // void R_InitTextureData(void) { - if (highcolor) - { - CONS_Printf("InitHighColor...\n"); - R_Init8to16(); - } - CONS_Printf("R_LoadTextures()...\n"); R_LoadTextures(); diff --git a/src/rhi/CMakeLists.txt b/src/rhi/CMakeLists.txt new file mode 100644 index 000000000..4ba10ae5b --- /dev/null +++ b/src/rhi/CMakeLists.txt @@ -0,0 +1,7 @@ +target_sources(SRB2SDL2 PRIVATE + handle.hpp + rhi.cpp + rhi.hpp +) + +add_subdirectory(gl3_core) diff --git a/src/rhi/gl3_core/CMakeLists.txt b/src/rhi/gl3_core/CMakeLists.txt new file mode 100644 index 000000000..0d59dde88 --- /dev/null +++ b/src/rhi/gl3_core/CMakeLists.txt @@ -0,0 +1,4 @@ +target_sources(SRB2SDL2 PRIVATE + gl3_core_rhi.cpp + gl3_core_rhi.hpp +) diff --git a/src/rhi/gl3_core/gl3_core_rhi.cpp b/src/rhi/gl3_core/gl3_core_rhi.cpp new file mode 100644 index 000000000..f80667470 --- /dev/null +++ b/src/rhi/gl3_core/gl3_core_rhi.cpp @@ -0,0 +1,1260 @@ +#include "gl3_core_rhi.hpp" + +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace srb2; + +using srb2::rhi::GlCorePlatform; +using srb2::rhi::GlCoreRhi; + +#if 1 +#define GL_ASSERT {GLenum __err = gl_->GetError(); if (__err != GL_NO_ERROR) { I_Error("GL Error at %s %d: %d", __FILE__, __LINE__, __err); }} +#else +#define GL_ASSERT ; +#endif + +namespace { + +template +std::unique_ptr> static_unique_ptr_cast(std::unique_ptr> ptr) { + D* derived = static_cast(ptr.release()); + return std::unique_ptr>(derived, std::default_delete()); +} + +constexpr GLenum map_pixel_format(rhi::PixelFormat format) { + switch (format) { + case rhi::PixelFormat::kRGBA8: + return GL_RGBA8; + case rhi::PixelFormat::kDepth16: + return GL_DEPTH_COMPONENT16; + case rhi::PixelFormat::kStencil8: + return GL_STENCIL_INDEX8; + default: + return GL_ZERO; + } +} + +constexpr std::tuple map_pixel_data_format(rhi::PixelFormat format) { + GLenum layout = GL_ZERO; + GLenum type = GL_ZERO; + GLuint size = 0; + switch (format) { + case rhi::PixelFormat::kR8: + layout = GL_RED; + type = GL_UNSIGNED_BYTE; + size = 1; + break; + case rhi::PixelFormat::kRGBA8: + layout = GL_RGBA; + type = GL_UNSIGNED_BYTE; + size = 4; + break; + default: + break; + } + return std::tuple(layout, type, size); +} + +constexpr GLenum map_texture_format(rhi::TextureFormat format) { + switch (format) { + case rhi::TextureFormat::kRGBA: + return GL_RGBA; + case rhi::TextureFormat::kRGB: + return GL_RGB; + case rhi::TextureFormat::kLuminance: + return GL_RED; + default: + return GL_ZERO; + } +} + +constexpr GLenum map_buffer_type(rhi::BufferType type) { + switch (type) { + case rhi::BufferType::kVertexBuffer: + return GL_ARRAY_BUFFER; + case rhi::BufferType::kIndexBuffer: + return GL_ELEMENT_ARRAY_BUFFER; + default: + return GL_ZERO; + } +} + +constexpr GLenum map_buffer_usage(rhi::BufferUsage usage) { + switch (usage) { + case rhi::BufferUsage::kImmutable: + return GL_STATIC_DRAW; + case rhi::BufferUsage::kDynamic: + return GL_DYNAMIC_DRAW; + default: + return GL_ZERO; + } +} + +constexpr GLenum map_compare_func(rhi::CompareFunc func) { + switch (func) { + case rhi::CompareFunc::kNever: + return GL_NEVER; + case rhi::CompareFunc::kLess: + return GL_LESS; + case rhi::CompareFunc::kEqual: + return GL_EQUAL; + case rhi::CompareFunc::kLessEqual: + return GL_LEQUAL; + case rhi::CompareFunc::kGreater: + return GL_GREATER; + case rhi::CompareFunc::kNotEqual: + return GL_NOTEQUAL; + case rhi::CompareFunc::kGreaterEqual: + return GL_GEQUAL; + case rhi::CompareFunc::kAlways: + return GL_ALWAYS; + default: + return GL_ZERO; + } +} + +constexpr GLenum map_blend_factor(rhi::BlendFactor factor) { + switch (factor) { + case rhi::BlendFactor::kZero: + return GL_ZERO; + case rhi::BlendFactor::kOne: + return GL_ONE; + case rhi::BlendFactor::kSource: + return GL_SRC_COLOR; + case rhi::BlendFactor::kOneMinusSource: + return GL_ONE_MINUS_SRC_COLOR; + case rhi::BlendFactor::kSourceAlpha: + return GL_SRC_ALPHA; + case rhi::BlendFactor::kOneMinusSourceAlpha: + return GL_ONE_MINUS_SRC_ALPHA; + case rhi::BlendFactor::kDest: + return GL_DST_COLOR; + case rhi::BlendFactor::kOneMinusDest: + return GL_ONE_MINUS_DST_COLOR; + case rhi::BlendFactor::kDestAlpha: + return GL_DST_ALPHA; + case rhi::BlendFactor::kOneMinusDestAlpha: + return GL_ONE_MINUS_DST_ALPHA; + case rhi::BlendFactor::kConstant: + return GL_CONSTANT_COLOR; + case rhi::BlendFactor::kOneMinusConstant: + return GL_ONE_MINUS_CONSTANT_COLOR; + case rhi::BlendFactor::kConstantAlpha: + return GL_CONSTANT_ALPHA; + case rhi::BlendFactor::kOneMinusConstantAlpha: + return GL_ONE_MINUS_CONSTANT_ALPHA; + case rhi::BlendFactor::kSourceAlphaSaturated: + return GL_SRC_ALPHA_SATURATE; + default: + return GL_ONE; + } +} + +constexpr GLenum map_blend_function(rhi::BlendFunction function) { + switch (function) { + case rhi::BlendFunction::kAdd: + return GL_FUNC_ADD; + case rhi::BlendFunction::kSubtract: + return GL_FUNC_SUBTRACT; + case rhi::BlendFunction::kReverseSubtract: + return GL_FUNC_REVERSE_SUBTRACT; + default: + return GL_FUNC_ADD; + } +} + +constexpr GLenum map_cull_mode(rhi::CullMode mode) { + switch (mode) { + case rhi::CullMode::kNone: + return GL_NONE; + case rhi::CullMode::kFront: + return GL_FRONT; + case rhi::CullMode::kBack: + return GL_BACK; + default: + return GL_NONE; + } +} + +constexpr GLenum map_winding(rhi::FaceWinding winding) { + switch (winding) { + case rhi::FaceWinding::kCounterClockwise: + return GL_CCW; + case rhi::FaceWinding::kClockwise: + return GL_CW; + default: + return GL_CCW; + } +} + +constexpr GLenum map_primitive_mode(rhi::PrimitiveType type) { + switch (type) { + case rhi::PrimitiveType::kPoints: + return GL_POINTS; + case rhi::PrimitiveType::kLines: + return GL_LINES; + case rhi::PrimitiveType::kLineStrip: + return GL_LINE_STRIP; + case rhi::PrimitiveType::kTriangles: + return GL_TRIANGLES; + case rhi::PrimitiveType::kTriangleStrip: + return GL_TRIANGLE_STRIP; + case rhi::PrimitiveType::kTriangleFan: + return GL_TRIANGLE_FAN; + default: + return GL_ZERO; + } +} + +constexpr const char* map_vertex_attribute_symbol_name(rhi::VertexAttributeName name) { + switch (name) { + case rhi::VertexAttributeName::kPosition: + return "a_position"; + case rhi::VertexAttributeName::kNormal: + return "a_normal"; + case rhi::VertexAttributeName::kColor: + return "a_color"; + case rhi::VertexAttributeName::kTexCoord0: + return "a_texcoord0"; + case rhi::VertexAttributeName::kTexCoord1: + return "a_texcoord1"; + default: + return nullptr; + } +} + +constexpr const char* map_vertex_attribute_enable_define(rhi::VertexAttributeName name) { + switch (name) { + case rhi::VertexAttributeName::kPosition: + return "ENABLE_VA_POSITION"; + case rhi::VertexAttributeName::kNormal: + return "ENABLE_VA_NORMAL"; + case rhi::VertexAttributeName::kColor: + return "ENABLE_VA_COLOR"; + case rhi::VertexAttributeName::kTexCoord0: + return "ENABLE_VA_TEXCOORD0"; + case rhi::VertexAttributeName::kTexCoord1: + return "ENABLE_VA_TEXCOORD1"; + default: + return nullptr; + } +} + +constexpr const char* map_uniform_attribute_symbol_name(rhi::UniformName name) { + switch (name) { + case rhi::UniformName::kTime: + return "u_time"; + case rhi::UniformName::kModelView: + return "u_modelview"; + case rhi::UniformName::kProjection: + return "u_projection"; + case rhi::UniformName::kTexCoord0Transform: + return "u_texcoord0_transform"; + default: + return nullptr; + } +} + +constexpr const char* map_sampler_symbol_name(rhi::SamplerName name) { + switch (name) { + case rhi::SamplerName::kSampler0: + return "s_sampler0"; + case rhi::SamplerName::kSampler1: + return "s_sampler1"; + case rhi::SamplerName::kSampler2: + return "s_sampler2"; + case rhi::SamplerName::kSampler3: + return "s_sampler3"; + default: + return nullptr; + } +} + +constexpr GLenum map_vertex_attribute_format(rhi::VertexAttributeFormat format) { + switch (format) { + case rhi::VertexAttributeFormat::kFloat: + return GL_FLOAT; + case rhi::VertexAttributeFormat::kFloat2: + return GL_FLOAT_VEC2; + case rhi::VertexAttributeFormat::kFloat3: + return GL_FLOAT_VEC3; + case rhi::VertexAttributeFormat::kFloat4: + return GL_FLOAT_VEC4; + default: + return GL_ZERO; + } +} + +constexpr GLenum map_vertex_attribute_type(rhi::VertexAttributeFormat format) { + switch (format) { + case rhi::VertexAttributeFormat::kFloat: + return GL_FLOAT; + case rhi::VertexAttributeFormat::kFloat2: + return GL_FLOAT; + case rhi::VertexAttributeFormat::kFloat3: + return GL_FLOAT; + case rhi::VertexAttributeFormat::kFloat4: + return GL_FLOAT; + default: + return GL_ZERO; + } +} + +constexpr GLint map_vertex_attribute_format_size(rhi::VertexAttributeFormat format) { + switch (format) { + case rhi::VertexAttributeFormat::kFloat: + return 1; + case rhi::VertexAttributeFormat::kFloat2: + return 2; + case rhi::VertexAttributeFormat::kFloat3: + return 3; + case rhi::VertexAttributeFormat::kFloat4: + return 4; + default: + return 0; + } +} + +constexpr GLenum map_uniform_format(rhi::UniformFormat format) { + switch (format) { + case rhi::UniformFormat::kFloat: + return GL_FLOAT; + case rhi::UniformFormat::kFloat2: + return GL_FLOAT_VEC2; + case rhi::UniformFormat::kFloat3: + return GL_FLOAT_VEC3; + case rhi::UniformFormat::kFloat4: + return GL_FLOAT_VEC4; + case rhi::UniformFormat::kInt: + return GL_INT; + case rhi::UniformFormat::kInt2: + return GL_INT_VEC2; + case rhi::UniformFormat::kInt3: + return GL_INT_VEC3; + case rhi::UniformFormat::kInt4: + return GL_INT_VEC4; + case rhi::UniformFormat::kMat2: + return GL_FLOAT_MAT2; + case rhi::UniformFormat::kMat3: + return GL_FLOAT_MAT3; + case rhi::UniformFormat::kMat4: + return GL_FLOAT_MAT4; + default: + return GL_ZERO; + } +} + +struct GlCoreTexture : public rhi::Texture { + GLuint texture; + rhi::TextureDesc desc; + GlCoreTexture(GLuint texture, const rhi::TextureDesc& desc) noexcept : texture(texture), desc(desc) {} +}; + +struct GlCoreBuffer : public rhi::Buffer { + GLuint buffer; + rhi::BufferDesc desc; + GlCoreBuffer(GLuint buffer, const rhi::BufferDesc& desc) noexcept : buffer(buffer), desc(desc) {} +}; + +struct GlCoreRenderPass : public rhi::RenderPass { + rhi::RenderPassDesc desc; + explicit GlCoreRenderPass(const rhi::RenderPassDesc& desc) noexcept : desc(desc) {} +}; + +struct GlCoreRenderbuffer : public rhi::Renderbuffer { + GLuint renderbuffer; + + explicit GlCoreRenderbuffer(GLuint renderbuffer) noexcept : renderbuffer(renderbuffer) {} +}; + +struct GlCoreUniformSet : public rhi::UniformSet +{ + std::vector uniforms; +}; + +struct GlCoreBindingSet : public rhi::BindingSet +{ + GLuint vao; + std::unordered_map textures {4}; +}; + +struct GlCorePipeline : public rhi::Pipeline { + GLuint vertex_shader = 0; + GLuint fragment_shader = 0; + GLuint program = 0; + std::unordered_map attrib_locations {2}; + std::unordered_map uniform_locations {2}; + std::unordered_map sampler_locations {2}; + rhi::PipelineDesc desc; +}; + +struct GlCoreGraphicsContext : public rhi::GraphicsContext {}; + +struct GlCoreTransferContext : public rhi::TransferContext {}; + +struct GlCoreActiveUniform { + GLenum type; + GLuint location; +}; + +} // namespace + +GlCorePlatform::~GlCorePlatform() = default; + +GlCoreRhi::GlCoreRhi(std::unique_ptr&& platform, GlLoadFunc load_func) + : platform_(std::move(platform)) { + gl_ = std::make_unique(); + gladLoadGLContext(gl_.get(), load_func); +} + +GlCoreRhi::~GlCoreRhi() = default; + +rhi::Handle GlCoreRhi::create_render_pass(const rhi::RenderPassDesc& desc) { + SRB2_ASSERT(graphics_context_active_ == false); + + // GL has no formal render pass object + return render_pass_slab_.insert(std::make_unique(desc)); +} + +void GlCoreRhi::destroy_render_pass(rhi::Handle handle) { + SRB2_ASSERT(graphics_context_active_ == false); + + std::unique_ptr buffer = render_pass_slab_.remove(handle); + std::unique_ptr casted(static_cast(buffer.release())); +} + +rhi::Handle GlCoreRhi::create_texture(const rhi::TextureDesc& desc) { + SRB2_ASSERT(graphics_context_active_ == false); + + GLenum internal_format = map_texture_format(desc.format); + SRB2_ASSERT(internal_format != GL_ZERO); + + GLuint name = 0; + gl_->GenTextures(1, &name); + + gl_->BindTexture(GL_TEXTURE_2D, name); + + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); GL_ASSERT + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); GL_ASSERT + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); GL_ASSERT + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); GL_ASSERT + gl_->TexImage2D(GL_TEXTURE_2D, 0, internal_format, desc.width, desc.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); GL_ASSERT + + return texture_slab_.insert(std::make_unique(name, desc)); +} + +void GlCoreRhi::destroy_texture(rhi::Handle handle) { + SRB2_ASSERT(graphics_context_active_ == false); + + SRB2_ASSERT(texture_slab_.is_valid(handle) == true); + std::unique_ptr casted = static_unique_ptr_cast(texture_slab_.remove(handle)); + GLuint name = casted->texture; + disposal_.push_back([this, name] { gl_->DeleteTextures(1, &name); }); +} + +void GlCoreRhi::update_texture(Handle ctx, Handle texture, Rect region, srb2::rhi::PixelFormat data_format, tcb::span data) { + SRB2_ASSERT(graphics_context_active_ == false); + SRB2_ASSERT(transfer_context_active_ == true); + SRB2_ASSERT(ctx.generation() == transfer_context_generation_); + + if (data.empty()) + { + return; + } + + SRB2_ASSERT(texture_slab_.is_valid(texture) == true); + auto& t = *static_cast(&texture_slab_[texture]); + + GLenum format = GL_RGBA; + GLenum type = GL_UNSIGNED_BYTE; + GLuint size = 0; + std::tie(format, type, size) = map_pixel_data_format(data_format); + SRB2_ASSERT(format != GL_ZERO && type != GL_ZERO); + SRB2_ASSERT(map_texture_format(t.desc.format) == format); + SRB2_ASSERT(region.w * region.h * size == data.size_bytes()); + SRB2_ASSERT(region.x + region.w <= t.desc.width && region.y + region.h <= t.desc.height); + + gl_->ActiveTexture(GL_TEXTURE0); GL_ASSERT + gl_->BindTexture(GL_TEXTURE_2D, t.texture); GL_ASSERT + gl_->TexSubImage2D(GL_TEXTURE_2D, 0, region.x, region.y, region.w, region.h, format, type, reinterpret_cast(data.data())); GL_ASSERT +} + +rhi::Handle GlCoreRhi::create_buffer(const rhi::BufferDesc& desc) { + SRB2_ASSERT(graphics_context_active_ == false); + + GLenum target = map_buffer_type(desc.type); + SRB2_ASSERT(target != GL_ZERO); + + GLenum usage = map_buffer_usage(desc.usage); + SRB2_ASSERT(usage != GL_ZERO); + + GLuint name = 0; + gl_->GenBuffers(1, &name); GL_ASSERT + + gl_->BindBuffer(target, name); GL_ASSERT + + gl_->BufferData(target, desc.size, nullptr, usage); GL_ASSERT + + return buffer_slab_.insert(std::make_unique(name, desc)); +} + +void GlCoreRhi::destroy_buffer(rhi::Handle handle) { + SRB2_ASSERT(graphics_context_active_ == false); + + SRB2_ASSERT(buffer_slab_.is_valid(handle) == true); + SRB2_ASSERT(graphics_context_active_ == false); + std::unique_ptr casted = static_unique_ptr_cast(buffer_slab_.remove(handle)); + GLuint name = casted->buffer; + + disposal_.push_back([this, name] { gl_->DeleteBuffers(1, &name); }); +} + +void GlCoreRhi::update_buffer_contents(rhi::Handle ctx, rhi::Handle handle, uint32_t offset, tcb::span data) { + SRB2_ASSERT(graphics_context_active_ == false); + SRB2_ASSERT(transfer_context_active_ == true); + SRB2_ASSERT(ctx.generation() == transfer_context_generation_); + + if (data.empty()) + { + return; + } + + SRB2_ASSERT(buffer_slab_.is_valid(handle) == true); + auto& b = *static_cast(&buffer_slab_[handle]); + + SRB2_ASSERT(offset < b.desc.size && offset + data.size() <= b.desc.size); + + GLenum target = GL_ZERO; + switch (b.desc.type) { + case rhi::BufferType::kVertexBuffer: + target = GL_ARRAY_BUFFER; + break; + case rhi::BufferType::kIndexBuffer: + target = GL_ELEMENT_ARRAY_BUFFER; + break; + } + + gl_->BindBuffer(target, b.buffer); GL_ASSERT + gl_->BufferSubData(target, offset, data.size(), data.data()); GL_ASSERT +} + +rhi::Handle GlCoreRhi::create_uniform_set(rhi::Handle ctx, const rhi::CreateUniformSetInfo& info) +{ + SRB2_ASSERT(graphics_context_active_ == false); + SRB2_ASSERT(transfer_context_active_ == true); + SRB2_ASSERT(ctx.generation() == transfer_context_generation_); + + GlCoreUniformSet uniform_set; + + for (auto& uniform : info.uniforms) + { + uniform_set.uniforms.push_back(uniform); + } + + return uniform_set_slab_.insert(std::make_unique(std::move(uniform_set))); +} + +rhi::Handle GlCoreRhi::create_binding_set(rhi::Handle ctx, Handle pipeline, const rhi::CreateBindingSetInfo& info) +{ + SRB2_ASSERT(graphics_context_active_ == false); + SRB2_ASSERT(transfer_context_active_ == true); + SRB2_ASSERT(ctx.generation() == transfer_context_generation_); + + SRB2_ASSERT(pipeline_slab_.is_valid(pipeline) == true); + auto& pl = *static_cast(&pipeline_slab_[pipeline]); + + SRB2_ASSERT(info.vertex_buffers.size() == pl.desc.vertex_input.buffer_layouts.size()); + + GlCoreBindingSet binding_set; + + GLuint vao = 0; + gl_->GenVertexArrays(1, &vao); GL_ASSERT + gl_->BindVertexArray(vao); GL_ASSERT + + for (auto& attr_layout : pl.desc.vertex_input.attr_layouts) + { + SRB2_ASSERT(buffer_slab_.is_valid(info.vertex_buffers[attr_layout.buffer_index].vertex_buffer)); + auto& buf = *static_cast(&buffer_slab_[info.vertex_buffers[attr_layout.buffer_index].vertex_buffer]); + SRB2_ASSERT(buf.desc.type == rhi::BufferType::kVertexBuffer); + + auto& buffer_layout = pl.desc.vertex_input.buffer_layouts[attr_layout.buffer_index]; + + gl_->BindBuffer(GL_ARRAY_BUFFER, buf.buffer); GL_ASSERT + + GLuint attrib_location = pl.attrib_locations[attr_layout.name]; + VertexAttributeFormat vert_attr_format = rhi::vertex_attribute_format(attr_layout.name); + GLenum vertex_attr_type = map_vertex_attribute_type(vert_attr_format); + SRB2_ASSERT(vertex_attr_type != GL_ZERO); + GLint vertex_attr_size = map_vertex_attribute_format_size(vert_attr_format); + SRB2_ASSERT(vertex_attr_size != 0); + uint32_t vertex_buffer_offset = 0; // TODO allow binding set to specify + gl_->EnableVertexAttribArray(pl.attrib_locations[attr_layout.name]); GL_ASSERT + gl_->VertexAttribPointer(attrib_location, vertex_attr_size, vertex_attr_type, GL_FALSE, buffer_layout.stride, reinterpret_cast(vertex_buffer_offset + attr_layout.offset)); GL_ASSERT + } + + binding_set.vao = vao; + + // Set textures + for (size_t i = 0; i < info.sampler_textures.size(); i++) + { + auto& binding = info.sampler_textures[i]; + auto& sampler_name = pl.desc.sampler_input.enabled_samplers[i]; + SRB2_ASSERT(binding.name == sampler_name); + + SRB2_ASSERT(texture_slab_.is_valid(binding.texture)); + auto& tx = *static_cast(&texture_slab_[binding.texture]); + binding_set.textures.insert({sampler_name, tx.texture}); + } + + return binding_set_slab_.insert(std::make_unique(std::move(binding_set))); +} + +rhi::Handle GlCoreRhi::create_renderbuffer(const rhi::RenderbufferDesc& desc) { + SRB2_ASSERT(graphics_context_active_ == false); + + GLuint name = 0; + gl_->GenRenderbuffers(1, &name); + + // Obtain storage up-front. + gl_->BindRenderbuffer(GL_RENDERBUFFER, name); GL_ASSERT + gl_->RenderbufferStorage(GL_RENDERBUFFER, map_pixel_format(desc.format), desc.width, desc.height); GL_ASSERT + + return renderbuffer_slab_.insert(std::make_unique(GlCoreRenderbuffer {name})); +} + +void GlCoreRhi::destroy_renderbuffer(rhi::Handle handle) { + SRB2_ASSERT(graphics_context_active_ == false); + + SRB2_ASSERT(renderbuffer_slab_.is_valid(handle) == true); + std::unique_ptr casted = + static_unique_ptr_cast(renderbuffer_slab_.remove(handle)); + GLuint name = casted->renderbuffer; + disposal_.push_back([this, name] { gl_->DeleteRenderbuffers(1, &name); }); +} + +rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) { + SRB2_ASSERT(graphics_context_active_ == false); + SRB2_ASSERT(platform_ != nullptr); + // TODO assert compatibility of pipeline description with program using ProgramRequirements + + const rhi::ProgramRequirements& reqs = rhi::program_requirements_for_program(desc.program); + + GLuint vertex = 0; + GLuint fragment = 0; + GLuint program = 0; + GlCorePipeline pipeline; + + auto [vert_src, frag_src] = platform_->find_shader_sources(desc.program); + + // TODO make use of multiple source files. + // In Khronos Group's brilliance, #version is required to be the first directive, + // but we need to insert #defines in-between. + std::string vert_src_processed; + std::string::size_type string_i = 0; + do + { + std::string::size_type new_i = vert_src.find('\n', string_i); + if (new_i == std::string::npos) + { + break; + } + std::string_view line_view(vert_src.c_str() + string_i, new_i - string_i + 1); + vert_src_processed.append(line_view); + if (line_view.rfind("#version ", 0) == 0) + { + for (auto& attribute : desc.vertex_input.attr_layouts) + { + for (auto const& require_attr : reqs.vertex_input.attributes) + { + if (require_attr.name == attribute.name && !require_attr.required) + { + vert_src_processed.append("#define "); + vert_src_processed.append(map_vertex_attribute_enable_define(attribute.name)); + vert_src_processed.append("\n"); + } + } + } + } + string_i = new_i + 1; + } while (string_i != std::string::npos); + + const char* vert_src_arr[1] = {vert_src_processed.c_str()}; + const GLint vert_src_arr_lens[1] = {static_cast(vert_src_processed.size())}; + const char* frag_src_arr[1] = {frag_src.c_str()}; + const GLint frag_src_arr_lens[1] = {static_cast(frag_src.size())}; + + vertex = gl_->CreateShader(GL_VERTEX_SHADER); + gl_->ShaderSource(vertex, 1, vert_src_arr, vert_src_arr_lens); + gl_->CompileShader(vertex); + GLint is_compiled = 0; + gl_->GetShaderiv(vertex, GL_COMPILE_STATUS, &is_compiled); + if (is_compiled == GL_FALSE) { + GLint max_length = 0; + gl_->GetShaderiv(vertex, GL_INFO_LOG_LENGTH, &max_length); + std::vector compile_error(max_length); + gl_->GetShaderInfoLog(vertex, max_length, &max_length, compile_error.data()); + + gl_->DeleteShader(vertex); + throw std::runtime_error(fmt::format("Vertex shader compilation failed: {}", std::string(compile_error.data()))); + } + fragment = gl_->CreateShader(GL_FRAGMENT_SHADER); + gl_->ShaderSource(fragment, 1, frag_src_arr, frag_src_arr_lens); + gl_->CompileShader(fragment); + gl_->GetShaderiv(vertex, GL_COMPILE_STATUS, &is_compiled); + if (is_compiled == GL_FALSE) { + GLint max_length = 0; + gl_->GetShaderiv(fragment, GL_INFO_LOG_LENGTH, &max_length); + std::vector compile_error(max_length); + gl_->GetShaderInfoLog(fragment, max_length, &max_length, compile_error.data()); + + gl_->DeleteShader(fragment); + gl_->DeleteShader(vertex); + throw std::runtime_error(fmt::format("Fragment shader compilation failed: {}", std::string(compile_error.data()))); + } + + // Program link + + program = gl_->CreateProgram(); + gl_->AttachShader(program, vertex); + gl_->AttachShader(program, fragment); + gl_->LinkProgram(program); + gl_->GetProgramiv(program, GL_LINK_STATUS, &is_compiled); + if (is_compiled == GL_FALSE) { + GLint max_length = 0; + gl_->GetProgramiv(program, GL_INFO_LOG_LENGTH, &max_length); + std::vector link_error(max_length); + gl_->GetProgramInfoLog(program, max_length, &max_length, link_error.data()); + + gl_->DeleteProgram(program); + gl_->DeleteShader(fragment); + gl_->DeleteShader(vertex); + throw std::runtime_error(fmt::format("Pipeline program link failed: {}", std::string(link_error.data()))); + } + + std::unordered_map active_attributes; + GLint active_attribute_total = -1; + gl_->GetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attribute_total); + if (active_attribute_total < 0) { + gl_->DeleteProgram(program); + gl_->DeleteShader(fragment); + gl_->DeleteShader(vertex); + throw std::runtime_error("Unable to retrieve program active attributes"); + } + if (desc.vertex_input.attr_layouts.size() != static_cast(active_attribute_total)) { + gl_->DeleteProgram(program); + gl_->DeleteShader(fragment); + gl_->DeleteShader(vertex); + throw std::runtime_error( + fmt::format( + "Pipeline's enabled attribute count does not match the linked program's total: {} vs {}", + desc.vertex_input.attr_layouts.size(), + static_cast(active_attribute_total) + ) + ); + } + for (GLint i = 0; i < active_attribute_total; i++) { + GLsizei name_len = 0; + GLint size = 0; + GLenum type = GL_ZERO; + char name[256]; + gl_->GetActiveAttrib(program, i, 255, &name_len, &size, &type, name); GL_ASSERT + GLint location = gl_->GetAttribLocation(program, name); GL_ASSERT + active_attributes.insert({std::string(name), GlCoreActiveUniform {type, static_cast(location)}}); + } + + std::unordered_map active_uniforms; + size_t total_enabled_uniforms = 0; + for (auto g = desc.uniform_input.enabled_uniforms.cbegin() ; g != desc.uniform_input.enabled_uniforms.cend(); g = std::next(g)) + { + total_enabled_uniforms += g->size(); + } + GLint active_uniform_total = -1; + gl_->GetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniform_total); + if (active_uniform_total < 0) { + gl_->DeleteProgram(program); + gl_->DeleteShader(fragment); + gl_->DeleteShader(vertex); + throw std::runtime_error("Unable to retrieve program active uniforms"); + } + if (total_enabled_uniforms + desc.sampler_input.enabled_samplers.size() != static_cast(active_uniform_total)) { + gl_->DeleteProgram(program); + gl_->DeleteShader(fragment); + gl_->DeleteShader(vertex); + throw std::runtime_error( + fmt::format( + "Pipeline's enabled uniform count (uniforms + samplers) does not match the linked program's total: {} vs {}", + total_enabled_uniforms + desc.sampler_input.enabled_samplers.size(), + static_cast(active_uniform_total) + ) + ); + } + for (GLint i = 0; i < active_uniform_total; i++) { + GLsizei name_len = 0; + GLint size = 0; + GLenum type = GL_ZERO; + char name[256]; + gl_->GetActiveUniform(program, i, 255, &name_len, &size, &type, name); GL_ASSERT + GLint location = gl_->GetUniformLocation(program, name); GL_ASSERT + active_uniforms.insert({std::string(name), GlCoreActiveUniform {type, static_cast(location)}}); + } + + for (auto& attr : desc.vertex_input.attr_layouts) { + const char* symbol_name = map_vertex_attribute_symbol_name(attr.name); + SRB2_ASSERT(symbol_name != nullptr); + if (active_attributes.find(symbol_name) == active_attributes.end()) { + gl_->DeleteProgram(program); + gl_->DeleteShader(fragment); + gl_->DeleteShader(vertex); + throw std::runtime_error("Enabled attribute not found in linked program"); + } + auto& active_attr = active_attributes[symbol_name]; + auto expected_format = rhi::vertex_attribute_format(attr.name); + auto expected_gl_type = map_vertex_attribute_format(expected_format); + SRB2_ASSERT(expected_gl_type != GL_ZERO); + if (expected_gl_type != active_attr.type) { + gl_->DeleteProgram(program); + gl_->DeleteShader(fragment); + gl_->DeleteShader(vertex); + throw std::runtime_error("Active attribute type does not match expected type"); + } + + pipeline.attrib_locations.insert({attr.name, active_attr.location}); + } + + for (auto group_itr = desc.uniform_input.enabled_uniforms.cbegin(); group_itr != desc.uniform_input.enabled_uniforms.cend(); group_itr = std::next(group_itr)) + { + auto& group = *group_itr; + for (auto itr = group.cbegin(); itr != group.cend(); itr = std::next(itr)) + { + auto& uniform = *itr; + const char* symbol_name = map_uniform_attribute_symbol_name(uniform); + SRB2_ASSERT(symbol_name != nullptr); + if (active_uniforms.find(symbol_name) == active_uniforms.end()) { + gl_->DeleteProgram(program); + gl_->DeleteShader(fragment); + gl_->DeleteShader(vertex); + throw std::runtime_error("Enabled uniform not found in linked program"); + } + auto& active_uniform = active_uniforms[symbol_name]; + auto expected_format = rhi::uniform_format(uniform); + auto expected_gl_type = map_uniform_format(expected_format); + SRB2_ASSERT(expected_gl_type != GL_ZERO); + if (expected_gl_type != active_uniform.type) { + gl_->DeleteProgram(program); + gl_->DeleteShader(fragment); + gl_->DeleteShader(vertex); + throw std::runtime_error("Active uniform type does not match expected type"); + } + SRB2_ASSERT(pipeline.uniform_locations.find(uniform) == pipeline.uniform_locations.end()); + pipeline.uniform_locations.insert({uniform, active_uniform.location}); + } + } + + for (auto& sampler : desc.sampler_input.enabled_samplers) { + const char* symbol_name = map_sampler_symbol_name(sampler); + SRB2_ASSERT(symbol_name != nullptr); + if (active_uniforms.find(symbol_name) == active_uniforms.end()) { + gl_->DeleteProgram(program); + gl_->DeleteShader(fragment); + gl_->DeleteShader(vertex); + throw std::runtime_error("Enabled sampler not found in linked program"); + } + auto& active_sampler = active_uniforms[symbol_name]; + if (active_sampler.type != GL_SAMPLER_2D) { + gl_->DeleteProgram(program); + gl_->DeleteShader(fragment); + gl_->DeleteShader(vertex); + throw std::runtime_error("Active sampler type does not match expected type"); + } + + pipeline.sampler_locations.insert({sampler, active_sampler.location}); + } + + pipeline.desc = desc; + pipeline.vertex_shader = vertex; + pipeline.fragment_shader = fragment; + pipeline.program = program; + + return pipeline_slab_.insert(std::make_unique(std::move(pipeline))); +} + +void GlCoreRhi::destroy_pipeline(rhi::Handle handle) { + SRB2_ASSERT(graphics_context_active_ == false); + + SRB2_ASSERT(pipeline_slab_.is_valid(handle) == true); + std::unique_ptr casted = static_unique_ptr_cast(pipeline_slab_.remove(handle)); + GLuint vertex_shader = casted->vertex_shader; + GLuint fragment_shader = casted->fragment_shader; + GLuint program = casted->program; + + disposal_.push_back([this, fragment_shader] { gl_->DeleteShader(fragment_shader); }); + disposal_.push_back([this, vertex_shader] { gl_->DeleteShader(vertex_shader); }); + disposal_.push_back([this, program] { gl_->DeleteProgram(program); }); +} + +rhi::Handle GlCoreRhi::begin_graphics() { + SRB2_ASSERT(graphics_context_active_ == false); + graphics_context_active_ = true; + return rhi::Handle(0, graphics_context_generation_); +} + +void GlCoreRhi::end_graphics(rhi::Handle handle) { + SRB2_ASSERT(graphics_context_active_ == true); + SRB2_ASSERT(current_pipeline_.has_value() == false && current_render_pass_.has_value() == false); + graphics_context_generation_ += 1; + graphics_context_active_ = false; + gl_->Flush(); GL_ASSERT +} + +rhi::Handle GlCoreRhi::begin_transfer() +{ + SRB2_ASSERT(graphics_context_active_ == false); + SRB2_ASSERT(transfer_context_active_ == false); + + transfer_context_generation_ += 1; + transfer_context_active_ = true; + + return rhi::Handle(0, transfer_context_generation_); +} + +void GlCoreRhi::end_transfer(rhi::Handle ctx) +{ + SRB2_ASSERT(graphics_context_active_ == false); + SRB2_ASSERT(transfer_context_active_ == true); + + transfer_context_active_ = false; +} + +void GlCoreRhi::present() { + SRB2_ASSERT(platform_ != nullptr); + SRB2_ASSERT(graphics_context_active_ == false); + + platform_->present(); +} + +void GlCoreRhi::begin_default_render_pass(Handle ctx, bool clear) { + SRB2_ASSERT(platform_ != nullptr); + SRB2_ASSERT(graphics_context_active_ == true); + SRB2_ASSERT(current_render_pass_.has_value() == false); + + const Rect fb_rect = platform_->get_default_framebuffer_dimensions(); + + gl_->BindFramebuffer(GL_FRAMEBUFFER, 0); GL_ASSERT + gl_->Disable(GL_SCISSOR_TEST); + gl_->Viewport(0, 0, fb_rect.w, fb_rect.h); GL_ASSERT + + if (clear) + { + gl_->ClearColor(0.0f, 0.0f, 0.0f, 1.0f); GL_ASSERT + gl_->ClearDepth(1.0f); GL_ASSERT + gl_->ClearStencil(0); GL_ASSERT + gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GL_ASSERT + } + + current_render_pass_ = GlCoreRhi::DefaultRenderPassState {}; +} + +void GlCoreRhi::begin_render_pass(Handle ctx, const RenderPassBeginInfo& info) { + SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); + SRB2_ASSERT(current_render_pass_.has_value() == false); + + SRB2_ASSERT(render_pass_slab_.is_valid(info.render_pass) == true); + auto& rp = *static_cast(&render_pass_slab_[info.render_pass]); + SRB2_ASSERT(rp.desc.depth_format.has_value() == info.depth_attachment.has_value()); + + auto fb_itr = framebuffers_.find(GlCoreFramebufferKey {info.color_attachment, info.depth_attachment}); + if (fb_itr == framebuffers_.end()) { + // Create a new framebuffer for this color-depth pair + GLuint fb_name; + gl_->GenFramebuffers(1, &fb_name); + gl_->BindFramebuffer(GL_FRAMEBUFFER, fb_name); + fb_itr = framebuffers_.insert( + {GlCoreFramebufferKey {info.color_attachment, info.depth_attachment}, static_cast(fb_name)}).first; + + // TODO bind buffers correctly + } + auto& fb = *fb_itr; + gl_->BindFramebuffer(GL_FRAMEBUFFER, fb.second); + gl_->Disable(GL_SCISSOR_TEST); + + if (rp.desc.load_op == rhi::AttachmentLoadOp::kClear) { + gl_->ClearColor(info.clear_color.r, info.clear_color.g, info.clear_color.b, info.clear_color.a); + gl_->ClearDepth(1.f); + gl_->ClearStencil(0); + gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + } + + current_render_pass_ = info; +} + +void GlCoreRhi::end_render_pass(Handle ctx) { + SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); + SRB2_ASSERT(current_render_pass_.has_value() == true); + + current_pipeline_ = std::nullopt; + current_render_pass_ = std::nullopt; +} + +void GlCoreRhi::bind_pipeline(Handle ctx, Handle pipeline) { + SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); + SRB2_ASSERT(current_render_pass_.has_value() == true); + + SRB2_ASSERT(pipeline_slab_.is_valid(pipeline) == true); + auto& pl = *static_cast(&pipeline_slab_[pipeline]); + auto& desc = pl.desc; + + gl_->UseProgram(pl.program); GL_ASSERT + + gl_->Disable(GL_SCISSOR_TEST); GL_ASSERT + + if (desc.depth_attachment) { + gl_->Enable(GL_DEPTH_TEST); GL_ASSERT + GLenum depth_func = map_compare_func(desc.depth_attachment->func); + SRB2_ASSERT(depth_func != GL_ZERO); + gl_->DepthFunc(depth_func); GL_ASSERT + gl_->DepthMask(desc.depth_attachment->write ? GL_TRUE : GL_FALSE); GL_ASSERT + } else { + gl_->Disable(GL_DEPTH_TEST); GL_ASSERT + } + + if (desc.color_attachment.blend) { + rhi::BlendDesc& bl = *desc.color_attachment.blend; + gl_->Enable(GL_BLEND); GL_ASSERT + gl_->BlendFuncSeparate(map_blend_factor(bl.source_factor_color), + map_blend_factor(bl.dest_factor_color), + map_blend_factor(bl.source_factor_alpha), + map_blend_factor(bl.dest_factor_alpha)); GL_ASSERT + gl_->BlendEquationSeparate(map_blend_function(bl.color_function), map_blend_function(bl.alpha_function)); GL_ASSERT + gl_->BlendColor(desc.blend_color.r, desc.blend_color.g, desc.blend_color.b, desc.blend_color.a); GL_ASSERT + } else { + gl_->Disable(GL_BLEND); + } + + gl_->ColorMask(desc.color_attachment.color_mask.r ? GL_TRUE : GL_FALSE, + desc.color_attachment.color_mask.g ? GL_TRUE : GL_FALSE, + desc.color_attachment.color_mask.b ? GL_TRUE : GL_FALSE, + desc.color_attachment.color_mask.a ? GL_TRUE : GL_FALSE); GL_ASSERT + + GLenum cull_face = map_cull_mode(desc.cull); + if (cull_face == GL_NONE) { + gl_->Disable(GL_CULL_FACE); GL_ASSERT + } else { + gl_->Enable(GL_CULL_FACE); GL_ASSERT + gl_->CullFace(cull_face); GL_ASSERT + } + gl_->FrontFace(map_winding(desc.winding)); GL_ASSERT + + current_pipeline_ = pipeline; + current_primitive_type_ = desc.primitive; +} + +void GlCoreRhi::bind_uniform_set(Handle ctx, uint32_t slot, Handle set) +{ + SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); + SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); + + SRB2_ASSERT(pipeline_slab_.is_valid(*current_pipeline_)); + auto& pl = *static_cast(&pipeline_slab_[*current_pipeline_]); + + SRB2_ASSERT(uniform_set_slab_.is_valid(set)); + auto& us = *static_cast(&uniform_set_slab_[set]); + + auto& uniform_input = pl.desc.uniform_input; + SRB2_ASSERT(slot < uniform_input.enabled_uniforms.size()); + SRB2_ASSERT(us.uniforms.size() == uniform_input.enabled_uniforms[slot].size()); + + // Assert compatibility of uniform set with pipeline's set slot + for (size_t i = 0; i < us.uniforms.size(); i++) + { + SRB2_ASSERT( + rhi::uniform_format(uniform_input.enabled_uniforms[slot][i]) == rhi::uniform_variant_format(us.uniforms[i]) + ); + } + + // Apply uniforms + // TODO use Uniform Buffer Objects to optimize this. + // We don't really *need* to, though, probably... + // Also, we know that any given uniform name is uniquely present in a single uniform group asserted during pipeline + // compilation. This is an RHI requirement to support backends that don't have UBOs. + for (size_t i = 0; i < us.uniforms.size(); i++) + { + auto& uniform_name = uniform_input.enabled_uniforms[slot][i]; + auto& update_data = us.uniforms[i]; + SRB2_ASSERT(pl.uniform_locations.find(uniform_name) != pl.uniform_locations.end()); + GLuint pipeline_uniform = pl.uniform_locations[uniform_name]; + + struct UniformVariantVisitor { + GladGLContext* gl_; + rhi::UniformName name; + GLuint uniform; + + void operator()(const float& value) const noexcept { + gl_->Uniform1f(uniform, value); GL_ASSERT + } + void operator()(const std::array& value) const noexcept { + gl_->Uniform2f(uniform, value[0], value[1]); GL_ASSERT + } + void operator()(const std::array& value) const noexcept { + gl_->Uniform3f(uniform, value[0], value[1], value[2]); GL_ASSERT + } + void operator()(const std::array& value) const noexcept { + gl_->Uniform4f(uniform, value[0], value[1], value[2], value[3]); GL_ASSERT + } + void operator()(const int32_t& value) const noexcept { + gl_->Uniform1i(uniform, value); GL_ASSERT + } + void operator()(const std::array& value) const noexcept { + gl_->Uniform2i(uniform, value[0], value[1]); GL_ASSERT + } + void operator()(const std::array& value) const noexcept { + gl_->Uniform3i(uniform, value[0], value[1], value[2]); GL_ASSERT + } + void operator()(const std::array& value) const noexcept { + gl_->Uniform4i(uniform, value[0], value[1], value[2], value[3]); GL_ASSERT + } + void operator()(const std::array, 2>& value) const noexcept { + gl_->UniformMatrix2fv(uniform, 1, false, reinterpret_cast(&value)); GL_ASSERT + } + void operator()(const std::array, 3>& value) const noexcept { + gl_->UniformMatrix3fv(uniform, 1, false, reinterpret_cast(&value)); GL_ASSERT + } + void operator()(const std::array, 4>& value) const noexcept { + gl_->UniformMatrix4fv(uniform, 1, false, reinterpret_cast(&value)); GL_ASSERT + } + }; + std::visit(UniformVariantVisitor {gl_.get(), uniform_name, pipeline_uniform}, update_data); + } +} + +void GlCoreRhi::bind_binding_set(Handle ctx, Handle set) +{ + SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); + SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); + + SRB2_ASSERT(pipeline_slab_.is_valid(*current_pipeline_)); + auto& pl = *static_cast(&pipeline_slab_[*current_pipeline_]); + + SRB2_ASSERT(binding_set_slab_.is_valid(set)); + auto& bs = *static_cast(&binding_set_slab_[set]); + + SRB2_ASSERT(bs.textures.size() == pl.desc.sampler_input.enabled_samplers.size()); + + // Bind the vertex array for drawing + // TODO assert compatibility of binding set. The VAO's attributes must match the pipeline. + gl_->BindVertexArray(bs.vao); + + // Index buffer is part of VAO. + gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + // Bind the samplers to the uniforms + for (auto& texture_binding : bs.textures) + { + auto sampler_name = texture_binding.first; + GLuint texture_gl_name = texture_binding.second; + GLuint sampler_uniform_loc = pl.sampler_locations[sampler_name]; + GLenum active_texture = GL_TEXTURE0; + GLuint uniform_value = 0; + switch (sampler_name) { + case rhi::SamplerName::kSampler0: + active_texture = GL_TEXTURE0; + uniform_value = 0; + break; + case rhi::SamplerName::kSampler1: + active_texture = GL_TEXTURE0 + 1; + uniform_value = 1; + break; + case rhi::SamplerName::kSampler2: + active_texture = GL_TEXTURE0 + 2; + uniform_value = 2; + break; + case rhi::SamplerName::kSampler3: + active_texture = GL_TEXTURE0 + 3; + uniform_value = 3; + break; + } + gl_->ActiveTexture(active_texture); GL_ASSERT + gl_->BindTexture(GL_TEXTURE_2D, texture_gl_name); GL_ASSERT + gl_->Uniform1i(sampler_uniform_loc, uniform_value); GL_ASSERT + } +} + +void GlCoreRhi::bind_index_buffer(Handle ctx, Handle buffer) +{ + SRB2_ASSERT(transfer_context_active_ == false); + SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); + SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); + + SRB2_ASSERT(buffer_slab_.is_valid(buffer)); + auto& ib = *static_cast(&buffer_slab_[buffer]); + + SRB2_ASSERT(ib.desc.type == rhi::BufferType::kIndexBuffer); + + gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib.buffer); +} + +void GlCoreRhi::set_scissor(Handle ctx, const Rect& rect) { + SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); + SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); + + gl_->Enable(GL_SCISSOR_TEST); + gl_->Scissor(rect.x, rect.y, rect.w, rect.h); +} + +void GlCoreRhi::set_viewport(Handle ctx, const Rect& rect) { + SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); + SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); + + gl_->Viewport(rect.x, rect.y, rect.w, rect.h); +} + +void GlCoreRhi::draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) { + SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); + SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); + + gl_->DrawArrays(map_primitive_mode(current_primitive_type_), first_vertex, vertex_count); GL_ASSERT +} + +void GlCoreRhi::draw_indexed(Handle ctx, + uint32_t index_count, + uint32_t first_index) { + SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); + gl_->DrawElements(map_primitive_mode(current_primitive_type_), index_count, GL_UNSIGNED_SHORT, reinterpret_cast(first_index * 2 + index_buffer_offset_)); GL_ASSERT +} + + +void GlCoreRhi::read_pixels(Handle ctx, const Rect& rect, tcb::span out) +{ + SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); + SRB2_ASSERT(current_render_pass_.has_value()); + + SRB2_ASSERT(out.size_bytes() == rect.w * rect.h); + gl_->ReadPixels(rect.x, rect.y, rect.w, rect.h, GL_RGBA, GL_UNSIGNED_BYTE, out.data()); +} + +void GlCoreRhi::finish() { + SRB2_ASSERT(graphics_context_active_ == false); + + for (auto it = binding_set_slab_.cbegin(); it != binding_set_slab_.cend(); it++) + { + gl_->BindVertexArray(0); GL_ASSERT + GLuint vao = reinterpret_cast(*it).vao; + gl_->DeleteVertexArrays(1, &vao); GL_ASSERT + } + binding_set_slab_.clear(); + uniform_set_slab_.clear(); + + for (auto it = disposal_.begin(); it != disposal_.end(); it++) + { + (*it)(); + } + + disposal_.clear(); GL_ASSERT +} diff --git a/src/rhi/gl3_core/gl3_core_rhi.hpp b/src/rhi/gl3_core/gl3_core_rhi.hpp new file mode 100644 index 000000000..a11d58d52 --- /dev/null +++ b/src/rhi/gl3_core/gl3_core_rhi.hpp @@ -0,0 +1,148 @@ +#ifndef __SRB2_RHI_GLES2_RHI_HPP__ +#define __SRB2_RHI_GLES2_RHI_HPP__ + +#include +#include +#include +#include +#include +#include +#include + +#include "../rhi.hpp" + +namespace srb2::rhi { + +struct GlCoreFramebufferKey { + TextureOrRenderbuffer color; + std::optional depth; + + bool operator==(const GlCoreFramebufferKey& rhs) const noexcept { + return color == rhs.color && depth == rhs.depth; + } + + bool operator!=(const GlCoreFramebufferKey& rhs) const noexcept { + return !(*this == rhs); + } +}; + +} // namespace srb2::rhi + +// To make sure the compiler selects the struct specialization of std::hash for GlCoreFramebufferKey, +// we need to split the namespace declarations _before_ the instantiation of std::unordered_map. + +template <> +struct std::hash { + std::size_t operator()(const srb2::rhi::GlCoreFramebufferKey& key) const { + struct GetHandleHashVisitor { + uint32_t operator()(const srb2::rhi::Handle& handle) const noexcept { + return std::hash>()(handle); + } + uint32_t operator()(const srb2::rhi::Handle& handle) const noexcept { + return std::hash>()(handle); + } + }; + std::size_t color_hash = std::visit(GetHandleHashVisitor {}, key.color); + std::size_t depth_hash = 0; + if (key.depth) { + depth_hash = std::visit(GetHandleHashVisitor {}, *key.depth); + } + return color_hash ^ (depth_hash << 1); + } +}; + +struct GladGLContext; + +namespace srb2::rhi { + +typedef void (*GlProc)(void); +typedef GlProc (*GlLoadFunc)(const char* name); + +/// @brief Platform-specific implementation details for the GLES2 backend. +struct GlCorePlatform { + virtual ~GlCorePlatform(); + + virtual void present() = 0; + virtual std::tuple find_shader_sources(PipelineProgram program) = 0; + virtual Rect get_default_framebuffer_dimensions() = 0; +}; + +class GlCoreRhi final : public Rhi { + std::unique_ptr platform_; + + std::unique_ptr gl_; + + Slab render_pass_slab_; + Slab texture_slab_; + Slab buffer_slab_; + Slab renderbuffer_slab_; + Slab pipeline_slab_; + Slab uniform_set_slab_; + Slab binding_set_slab_; + + std::unordered_map framebuffers_ {16}; + + struct DefaultRenderPassState {}; + using RenderPassState = std::variant; + std::optional current_render_pass_; + std::optional> current_pipeline_; + PrimitiveType current_primitive_type_ = PrimitiveType::kPoints; + bool graphics_context_active_ = false; + bool transfer_context_active_ = false; + uint32_t graphics_context_generation_ = 0; + uint32_t index_buffer_offset_ = 0; + uint32_t transfer_context_generation_ = 0; + + std::vector> disposal_; + +public: + GlCoreRhi(std::unique_ptr&& platform, GlLoadFunc load_func); + virtual ~GlCoreRhi(); + + virtual Handle create_render_pass(const RenderPassDesc& desc) override; + virtual void destroy_render_pass(Handle handle) override; + virtual Handle create_pipeline(const PipelineDesc& desc) override; + virtual void destroy_pipeline(Handle handle) override; + + virtual Handle create_texture(const TextureDesc& desc) override; + virtual void destroy_texture(Handle handle) override; + virtual Handle create_buffer(const BufferDesc& desc) override; + virtual void destroy_buffer(Handle handle) override; + virtual Handle create_renderbuffer(const RenderbufferDesc& desc) override; + virtual void destroy_renderbuffer(Handle handle) override; + + virtual Handle begin_transfer() override; + virtual void end_transfer(Handle handle) override; + + virtual void update_buffer_contents(Handle ctx, Handle buffer, uint32_t offset, tcb::span data) override; + virtual void update_texture(Handle ctx, Handle texture, Rect region, srb2::rhi::PixelFormat data_format, tcb::span data) override; + virtual Handle create_uniform_set(Handle ctx, const CreateUniformSetInfo& info) override; + virtual Handle create_binding_set(Handle ctx, Handle pipeline, const CreateBindingSetInfo& info) override; + + virtual Handle begin_graphics() override; + virtual void end_graphics(Handle ctx) override; + + // Graphics context functions + virtual void begin_default_render_pass(Handle ctx, bool clear) override; + virtual void begin_render_pass(Handle ctx, const RenderPassBeginInfo& info) override; + virtual void end_render_pass(Handle ctx) override; + virtual void bind_pipeline(Handle ctx, Handle pipeline) override; + virtual void bind_uniform_set(Handle ctx, uint32_t slot, Handle set) override; + virtual void bind_binding_set(Handle ctx, Handle set) override; + virtual void bind_index_buffer(Handle ctx, Handle buffer) override; + virtual void set_scissor(Handle ctx, const Rect& rect) override; + virtual void set_viewport(Handle ctx, const Rect& rect) override; + virtual void draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) override; + virtual void draw_indexed(Handle ctx, + uint32_t index_count, + uint32_t first_index) override; + virtual void read_pixels(Handle ctx, const Rect& rect, tcb::span out) override; + + virtual void present() override; + + virtual void finish() override; +}; + +} // namespace srb2::rhi + +#endif // __SRB2_RHI_GLES2_RHI_HPP__ diff --git a/src/rhi/gles2/CMakeLists.txt b/src/rhi/gles2/CMakeLists.txt new file mode 100644 index 000000000..eaa80c4fa --- /dev/null +++ b/src/rhi/gles2/CMakeLists.txt @@ -0,0 +1 @@ +# Backend not available yet :) diff --git a/src/rhi/gles2/gles2_rhi.cpp b/src/rhi/gles2/gles2_rhi.cpp new file mode 100644 index 000000000..8e9d61f7d --- /dev/null +++ b/src/rhi/gles2/gles2_rhi.cpp @@ -0,0 +1,1122 @@ +#include "gles2_rhi.hpp" + +#include +#include +#include +#include +#include + +#include + +using namespace srb2; + +using srb2::rhi::Gles2Platform; +using srb2::rhi::Gles2Rhi; + +namespace { + +template +std::unique_ptr> static_unique_ptr_cast(std::unique_ptr> ptr) { + D* derived = static_cast(ptr.release()); + return std::unique_ptr>(derived, std::default_delete()); +} + +constexpr GLenum map_pixel_format(rhi::PixelFormat format) { + switch (format) { + case rhi::PixelFormat::kRGBA8: + // requires extension GL_OES_rgb8_rgba8, which is always requested + return GL_RGBA8_OES; + case rhi::PixelFormat::kDepth16: + return GL_DEPTH_COMPONENT16; + case rhi::PixelFormat::kStencil8: + return GL_STENCIL_INDEX8; + default: + return GL_ZERO; + } +} + +constexpr std::tuple map_pixel_data_format(rhi::PixelFormat format) { + GLenum layout = GL_ZERO; + GLenum type = GL_ZERO; + GLuint size = 0; + switch (format) { + case rhi::PixelFormat::kR8: + layout = GL_LUMINANCE; + type = GL_UNSIGNED_BYTE; + size = 1; + break; + case rhi::PixelFormat::kRGBA8: + layout = GL_RGBA; + type = GL_UNSIGNED_BYTE; + size = 4; + break; + default: + break; + } + return std::tuple(layout, type, size); +} + +constexpr GLenum map_texture_format(rhi::TextureFormat format) { + switch (format) { + case rhi::TextureFormat::kRGBA: + return GL_RGBA; + case rhi::TextureFormat::kRGB: + return GL_RGB; + case rhi::TextureFormat::kLuminance: + return GL_LUMINANCE; + default: + return GL_ZERO; + } +} + +constexpr GLenum map_buffer_type(rhi::BufferType type) { + switch (type) { + case rhi::BufferType::kVertexBuffer: + return GL_ARRAY_BUFFER; + case rhi::BufferType::kIndexBuffer: + return GL_ELEMENT_ARRAY_BUFFER; + default: + return GL_ZERO; + } +} + +constexpr GLenum map_buffer_usage(rhi::BufferUsage usage) { + switch (usage) { + case rhi::BufferUsage::kImmutable: + return GL_STATIC_DRAW; + case rhi::BufferUsage::kDynamic: + return GL_DYNAMIC_DRAW; + default: + return GL_ZERO; + } +} + +constexpr GLenum map_compare_func(rhi::CompareFunc func) { + switch (func) { + case rhi::CompareFunc::kNever: + return GL_NEVER; + case rhi::CompareFunc::kLess: + return GL_LESS; + case rhi::CompareFunc::kEqual: + return GL_EQUAL; + case rhi::CompareFunc::kLessEqual: + return GL_LEQUAL; + case rhi::CompareFunc::kGreater: + return GL_GREATER; + case rhi::CompareFunc::kNotEqual: + return GL_NOTEQUAL; + case rhi::CompareFunc::kGreaterEqual: + return GL_GEQUAL; + case rhi::CompareFunc::kAlways: + return GL_ALWAYS; + default: + return GL_ZERO; + } +} + +constexpr GLenum map_blend_factor(rhi::BlendFactor factor) { + switch (factor) { + case rhi::BlendFactor::kZero: + return GL_ZERO; + case rhi::BlendFactor::kOne: + return GL_ONE; + case rhi::BlendFactor::kSource: + return GL_SRC_COLOR; + case rhi::BlendFactor::kOneMinusSource: + return GL_ONE_MINUS_SRC_COLOR; + case rhi::BlendFactor::kSourceAlpha: + return GL_SRC_ALPHA; + case rhi::BlendFactor::kOneMinusSourceAlpha: + return GL_ONE_MINUS_SRC_ALPHA; + case rhi::BlendFactor::kDest: + return GL_DST_COLOR; + case rhi::BlendFactor::kOneMinusDest: + return GL_ONE_MINUS_DST_COLOR; + case rhi::BlendFactor::kDestAlpha: + return GL_DST_ALPHA; + case rhi::BlendFactor::kOneMinusDestAlpha: + return GL_ONE_MINUS_DST_ALPHA; + case rhi::BlendFactor::kConstant: + return GL_CONSTANT_COLOR; + case rhi::BlendFactor::kOneMinusConstant: + return GL_ONE_MINUS_CONSTANT_COLOR; + case rhi::BlendFactor::kConstantAlpha: + return GL_CONSTANT_ALPHA; + case rhi::BlendFactor::kOneMinusConstantAlpha: + return GL_ONE_MINUS_CONSTANT_ALPHA; + case rhi::BlendFactor::kSourceAlphaSaturated: + return GL_SRC_ALPHA_SATURATE; + default: + return GL_ONE; + } +} + +constexpr GLenum map_blend_function(rhi::BlendFunction function) { + switch (function) { + case rhi::BlendFunction::kAdd: + return GL_FUNC_ADD; + case rhi::BlendFunction::kSubtract: + return GL_FUNC_SUBTRACT; + case rhi::BlendFunction::kReverseSubtract: + return GL_FUNC_REVERSE_SUBTRACT; + default: + return GL_FUNC_ADD; + } +} + +constexpr GLenum map_cull_mode(rhi::CullMode mode) { + switch (mode) { + case rhi::CullMode::kNone: + return GL_NONE; + case rhi::CullMode::kFront: + return GL_FRONT; + case rhi::CullMode::kBack: + return GL_BACK; + default: + return GL_NONE; + } +} + +constexpr GLenum map_winding(rhi::FaceWinding winding) { + switch (winding) { + case rhi::FaceWinding::kCounterClockwise: + return GL_CCW; + case rhi::FaceWinding::kClockwise: + return GL_CW; + default: + return GL_CCW; + } +} + +constexpr GLenum map_primitive_mode(rhi::PrimitiveType type) { + switch (type) { + case rhi::PrimitiveType::kPoints: + return GL_POINTS; + case rhi::PrimitiveType::kLines: + return GL_LINES; + case rhi::PrimitiveType::kLineStrip: + return GL_LINE_STRIP; + case rhi::PrimitiveType::kTriangles: + return GL_TRIANGLES; + case rhi::PrimitiveType::kTriangleStrip: + return GL_TRIANGLE_STRIP; + case rhi::PrimitiveType::kTriangleFan: + return GL_TRIANGLE_FAN; + default: + return GL_ZERO; + } +} + +constexpr const char* map_vertex_attribute_symbol_name(rhi::VertexAttributeName name) { + switch (name) { + case rhi::VertexAttributeName::kPosition: + return "a_position"; + case rhi::VertexAttributeName::kNormal: + return "a_normal"; + case rhi::VertexAttributeName::kColor: + return "a_color"; + case rhi::VertexAttributeName::kTexCoord0: + return "a_texcoord0"; + case rhi::VertexAttributeName::kTexCoord1: + return "a_texcoord1"; + default: + return nullptr; + } +} + +/* +constexpr const char* map_vertex_attribute_enable_define(rhi::VertexAttributeName name) { + switch (name) { + case rhi::VertexAttributeName::kPosition: + return "ENABLE_VA_POSITION"; + case rhi::VertexAttributeName::kNormal: + return "ENABLE_VA_NORMAL"; + case rhi::VertexAttributeName::kColor: + return "ENABLE_VA_COLOR"; + case rhi::VertexAttributeName::kTexCoord0: + return "ENABLE_VA_TEXCOORD0"; + case rhi::VertexAttributeName::kTexCoord1: + return "ENABLE_VA_TEXCOORD1"; + default: + return nullptr; + } +} +*/ + +constexpr const char* map_uniform_attribute_symbol_name(rhi::UniformName name) { + switch (name) { + case rhi::UniformName::kTime: + return "u_time"; + case rhi::UniformName::kModelView: + return "u_modelview"; + case rhi::UniformName::kProjection: + return "u_projection"; + default: + return nullptr; + } +} + +/* +constexpr const char* map_uniform_attribute_enable_define(rhi::UniformName name) { + switch (name) { + case rhi::UniformName::kTime: + return "ENABLE_U_TIME"; + case rhi::UniformName::kModelView: + return "ENABLE_U_MODELVIEW"; + case rhi::UniformName::kProjection: + return "ENABLE_U_PROJECTION"; + default: + return nullptr; + } +} +*/ + +constexpr const char* map_sampler_symbol_name(rhi::SamplerName name) { + switch (name) { + case rhi::SamplerName::kSampler0: + return "s_sampler0"; + case rhi::SamplerName::kSampler1: + return "s_sampler1"; + case rhi::SamplerName::kSampler2: + return "s_sampler2"; + case rhi::SamplerName::kSampler3: + return "s_sampler3"; + default: + return nullptr; + } +} + +constexpr GLenum map_vertex_attribute_format(rhi::VertexAttributeFormat format) { + switch (format) { + case rhi::VertexAttributeFormat::kFloat: + return GL_FLOAT; + case rhi::VertexAttributeFormat::kFloat2: + return GL_FLOAT_VEC2; + case rhi::VertexAttributeFormat::kFloat3: + return GL_FLOAT_VEC3; + case rhi::VertexAttributeFormat::kFloat4: + return GL_FLOAT_VEC4; + default: + return GL_ZERO; + } +} + +constexpr GLenum map_vertex_attribute_type(rhi::VertexAttributeFormat format) { + switch (format) { + case rhi::VertexAttributeFormat::kFloat: + return GL_FLOAT; + case rhi::VertexAttributeFormat::kFloat2: + return GL_FLOAT; + case rhi::VertexAttributeFormat::kFloat3: + return GL_FLOAT; + case rhi::VertexAttributeFormat::kFloat4: + return GL_FLOAT; + default: + return GL_ZERO; + } +} + +constexpr GLint map_vertex_attribute_format_size(rhi::VertexAttributeFormat format) { + switch (format) { + case rhi::VertexAttributeFormat::kFloat: + return 1; + case rhi::VertexAttributeFormat::kFloat2: + return 2; + case rhi::VertexAttributeFormat::kFloat3: + return 3; + case rhi::VertexAttributeFormat::kFloat4: + return 4; + default: + return 0; + } +} + +constexpr GLenum map_uniform_format(rhi::UniformFormat format) { + switch (format) { + case rhi::UniformFormat::kFloat: + return GL_FLOAT; + case rhi::UniformFormat::kFloat2: + return GL_FLOAT_VEC2; + case rhi::UniformFormat::kFloat3: + return GL_FLOAT_VEC3; + case rhi::UniformFormat::kFloat4: + return GL_FLOAT_VEC4; + case rhi::UniformFormat::kInt: + return GL_INT; + case rhi::UniformFormat::kInt2: + return GL_INT_VEC2; + case rhi::UniformFormat::kInt3: + return GL_INT_VEC3; + case rhi::UniformFormat::kInt4: + return GL_INT_VEC4; + case rhi::UniformFormat::kMat2: + return GL_FLOAT_MAT2; + case rhi::UniformFormat::kMat3: + return GL_FLOAT_MAT3; + case rhi::UniformFormat::kMat4: + return GL_FLOAT_MAT4; + default: + return GL_ZERO; + } +} + +struct Gles2Texture : public rhi::Texture { + GLuint texture; + rhi::TextureDesc desc; + Gles2Texture(GLuint texture, const rhi::TextureDesc& desc) noexcept : texture(texture), desc(desc) {} +}; + +struct Gles2Buffer : public rhi::Buffer { + GLuint buffer; + rhi::BufferDesc desc; + Gles2Buffer(GLuint buffer, const rhi::BufferDesc& desc) noexcept : buffer(buffer), desc(desc) {} +}; + +struct Gles2RenderPass : public rhi::RenderPass { + rhi::RenderPassDesc desc; + explicit Gles2RenderPass(const rhi::RenderPassDesc& desc) noexcept : desc(desc) {} +}; + +struct Gles2Renderbuffer : public rhi::Renderbuffer { + GLuint renderbuffer; + + explicit Gles2Renderbuffer(GLuint renderbuffer) noexcept : renderbuffer(renderbuffer) {} +}; + +struct Gles2Pipeline : public rhi::Pipeline { + GLuint vertex_shader = 0; + GLuint fragment_shader = 0; + GLuint program = 0; + std::unordered_map attrib_locations {2}; + std::unordered_map uniform_locations {2}; + std::unordered_map sampler_locations {2}; + rhi::PipelineDesc desc; + + Gles2Pipeline() = default; + explicit Gles2Pipeline(GLuint vertex_shader, + GLuint fragment_shader, + GLuint program, + const rhi::PipelineDesc& desc) noexcept + : vertex_shader(vertex_shader), fragment_shader(fragment_shader), program(program), desc(desc) {} +}; + +struct Gles2GraphicsContext : public rhi::GraphicsContext {}; + +struct Gles2ActiveUniform { + GLenum type; + GLuint location; +}; + +} // namespace + +Gles2Platform::~Gles2Platform() = default; + +Gles2Rhi::Gles2Rhi(std::unique_ptr&& platform) + : platform_(std::move(platform)) { +} + +Gles2Rhi::~Gles2Rhi() = default; + +rhi::Handle Gles2Rhi::create_render_pass(const rhi::RenderPassDesc& desc) { + SRB2_ASSERT(graphics_context_active_ == false); + + // GL has no formal render pass object + return render_pass_slab_.insert(std::make_unique(desc)); +} + +void Gles2Rhi::destroy_render_pass(rhi::Handle&& handle) { + SRB2_ASSERT(graphics_context_active_ == false); + + std::unique_ptr buffer = render_pass_slab_.remove(handle); + std::unique_ptr casted(static_cast(buffer.release())); +} + +rhi::Handle Gles2Rhi::create_texture(const rhi::TextureDesc& desc, srb2::rhi::PixelFormat data_format, tcb::span data) { + SRB2_ASSERT(graphics_context_active_ == false); + + GLint internal_format = map_texture_format(desc.format); + SRB2_ASSERT(internal_format != GL_ZERO); + + GLuint name = 0; + glGenTextures(1, &name); + + glBindTexture(GL_TEXTURE_2D, name); + + // if no data is provided, the initial texture is undefined + GLenum format = GL_RGBA; + GLenum type = GL_UNSIGNED_BYTE; + GLuint size = 0; + + const void* raw_data = nullptr; + std::tie(format, type, size) = map_pixel_data_format(data_format); + SRB2_ASSERT(format != GL_ZERO && type != GL_ZERO); + SRB2_ASSERT(internal_format == format); + if (!data.empty()) { + SRB2_ASSERT(size * desc.width * desc.height == data.size_bytes()); + raw_data = static_cast(data.data()); + } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexImage2D(GL_TEXTURE_2D, 0, internal_format, desc.width, desc.height, 0, format, type, raw_data); + + return texture_slab_.insert(std::make_unique(name, desc)); +} + +void Gles2Rhi::destroy_texture(rhi::Handle&& handle) { + SRB2_ASSERT(graphics_context_active_ == false); + + SRB2_ASSERT(texture_slab_.is_valid(handle) == true); + std::unique_ptr casted = static_unique_ptr_cast(texture_slab_.remove(handle)); + GLuint name = casted->texture; + disposal_.push_back([name] { glDeleteTextures(1, &name); }); +} + +void Gles2Rhi::update_texture(Handle texture, Rect region, srb2::rhi::PixelFormat data_format, tcb::span data) { + SRB2_ASSERT(graphics_context_active_ == false); + + SRB2_ASSERT(texture_slab_.is_valid(texture) == true); + auto& t = *static_cast(&texture_slab_[texture]); + + GLenum format = GL_RGBA; + GLenum type = GL_UNSIGNED_BYTE; + GLuint size = 0; + std::tie(format, type, size) = map_pixel_data_format(data_format); + SRB2_ASSERT(format != GL_ZERO && type != GL_ZERO); + SRB2_ASSERT(map_texture_format(t.desc.format) == format); + SRB2_ASSERT(region.w * region.h * size == data.size_bytes()); + SRB2_ASSERT(region.x + region.w < t.desc.width && region.y + region.h < t.desc.height); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, t.texture); + glTexSubImage2D(GL_TEXTURE_2D, 0, region.x, region.y, region.w, region.h, format, type, reinterpret_cast(data.data())); +} + +rhi::Handle Gles2Rhi::create_buffer(const rhi::BufferDesc& desc, tcb::span data) { + SRB2_ASSERT(graphics_context_active_ == false); + + // If data is provided, it must match the buffer description size exactly + SRB2_ASSERT(data.size() != 0 ? data.size() == desc.size : true); + + GLenum target = map_buffer_type(desc.type); + SRB2_ASSERT(target != GL_ZERO); + + GLenum usage = map_buffer_usage(desc.usage); + SRB2_ASSERT(usage != GL_ZERO); + + GLuint name = 0; + glGenBuffers(1, &name); + + glBindBuffer(target, name); + + // if no data is provided, the initial buffer data is undefined + const void* raw_data = nullptr; + if (!data.empty()) { + raw_data = static_cast(data.data()); + } + glBufferData(target, desc.size, raw_data, usage); + + return buffer_slab_.insert(std::make_unique(name, desc)); +} + +void Gles2Rhi::destroy_buffer(rhi::Handle&& handle) { + SRB2_ASSERT(graphics_context_active_ == false); + + SRB2_ASSERT(buffer_slab_.is_valid(handle) == true); + SRB2_ASSERT(graphics_context_active_ == false); + std::unique_ptr casted = static_unique_ptr_cast(buffer_slab_.remove(handle)); + GLuint name = casted->buffer; + + disposal_.push_back([name] { glDeleteBuffers(1, &name); }); +} + +void Gles2Rhi::update_buffer_contents(rhi::Handle handle, uint32_t offset, tcb::span data) { + SRB2_ASSERT(graphics_context_active_ == false); + + SRB2_ASSERT(buffer_slab_.is_valid(handle) == true); + auto& b = *static_cast(&buffer_slab_[handle]); + + if (data.size() == 0) + return; + + SRB2_ASSERT(offset < b.desc.size && offset + data.size() < b.desc.size); + + switch (b.desc.type) { + case rhi::BufferType::kVertexBuffer: + glBindBuffer(GL_ARRAY_BUFFER, b.buffer); + glBufferSubData(GL_ARRAY_BUFFER, offset, data.size(), data.data()); + break; + case rhi::BufferType::kIndexBuffer: + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, b.buffer); + glBufferSubData(GL_ARRAY_BUFFER, offset, data.size(), data.data()); + break; + } +} + +rhi::Handle Gles2Rhi::create_renderbuffer(const rhi::RenderbufferDesc& desc) { + SRB2_ASSERT(graphics_context_active_ == false); + + GLuint name = 0; + glGenRenderbuffers(1, &name); + + // Obtain storage up-front. + glBindRenderbuffer(GL_RENDERBUFFER, name); + glRenderbufferStorage(GL_RENDERBUFFER, map_pixel_format(desc.format), desc.width, desc.height); + + return renderbuffer_slab_.insert(std::make_unique(Gles2Renderbuffer {name})); +} + +void Gles2Rhi::destroy_renderbuffer(rhi::Handle&& handle) { + SRB2_ASSERT(graphics_context_active_ == false); + + SRB2_ASSERT(renderbuffer_slab_.is_valid(handle) == true); + std::unique_ptr casted = + static_unique_ptr_cast(renderbuffer_slab_.remove(handle)); + GLuint name = casted->renderbuffer; + disposal_.push_back([name] { glDeleteRenderbuffers(1, &name); }); +} + +rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { + SRB2_ASSERT(platform_ != nullptr); + // TODO assert compatibility of pipeline description with program using ProgramRequirements + + GLuint vertex = 0; + GLuint fragment = 0; + GLuint program = 0; + Gles2Pipeline pipeline; + + auto [vert_src, frag_src] = platform_->find_shader_sources(desc.program); + + // TODO preprocess shader code with specialization defines based on pipeline configuration + + const char* vert_src_arr[1] = {vert_src.c_str()}; + const GLint vert_src_arr_lens[1] = {static_cast(vert_src.size())}; + const char* frag_src_arr[1] = {frag_src.c_str()}; + const GLint frag_src_arr_lens[1] = {static_cast(frag_src.size())}; + + vertex = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertex, 1, vert_src_arr, vert_src_arr_lens); + glCompileShader(vertex); + GLint is_compiled = 0; + glGetShaderiv(vertex, GL_COMPILE_STATUS, &is_compiled); + if (is_compiled == GL_FALSE) { + GLint max_length = 0; + glGetShaderiv(vertex, GL_INFO_LOG_LENGTH, &max_length); + std::vector compile_error(max_length); + glGetShaderInfoLog(vertex, max_length, &max_length, compile_error.data()); + + glDeleteShader(vertex); + throw std::runtime_error(std::string("Vertex shader compilation failed: ") + std::string(compile_error.data())); + } + fragment = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragment, 1, frag_src_arr, frag_src_arr_lens); + glCompileShader(fragment); + glGetShaderiv(vertex, GL_COMPILE_STATUS, &is_compiled); + if (is_compiled == GL_FALSE) { + GLint max_length = 0; + glGetShaderiv(fragment, GL_INFO_LOG_LENGTH, &max_length); + std::vector compile_error(max_length); + glGetShaderInfoLog(fragment, max_length, &max_length, compile_error.data()); + + glDeleteShader(fragment); + glDeleteShader(vertex); + throw std::runtime_error(std::string("Fragment shader compilation failed: ") + std::string(compile_error.data())); + } + program = glCreateProgram(); + glAttachShader(program, vertex); + glAttachShader(program, fragment); + glLinkProgram(program); + glGetProgramiv(program, GL_LINK_STATUS, &is_compiled); + if (is_compiled == GL_FALSE) { + GLint max_length = 0; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &max_length); + std::vector link_error(max_length); + glGetProgramInfoLog(program, max_length, &max_length, link_error.data()); + + glDeleteProgram(program); + glDeleteShader(fragment); + glDeleteShader(vertex); + throw std::runtime_error(std::string("Pipeline program link failed: ") + std::string(link_error.data())); + } + + std::unordered_map active_attributes; + GLint active_attribute_total = -1; + glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attribute_total); + if (active_attribute_total < 0) { + glDeleteProgram(program); + glDeleteShader(fragment); + glDeleteShader(vertex); + throw std::runtime_error("Unable to retrieve program active attributes"); + } + if (desc.vertex_input.attr_layouts.size() != static_cast(active_attribute_total)) { + glDeleteProgram(program); + glDeleteShader(fragment); + glDeleteShader(vertex); + std::string ex_msg("Pipeline's enabled attribute count does not match the linked program's total: "); + ex_msg.append(std::to_string(desc.vertex_input.attr_layouts.size())); + ex_msg.append(" vs "); + ex_msg.append(std::to_string(static_cast(active_attribute_total))); + throw std::runtime_error(std::move(ex_msg)); + } + for (GLint i = 0; i < active_attribute_total; i++) { + GLsizei name_len = 0; + GLint size = 0; + GLenum type = GL_ZERO; + char name[256]; + glGetActiveAttrib(program, i, 255, &name_len, &size, &type, name); + active_attributes.insert({std::string(name), Gles2ActiveUniform {type, static_cast(i)}}); + } + + std::unordered_map active_uniforms; + GLint active_uniform_total = -1; + glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniform_total); + if (active_uniform_total < 0) { + glDeleteProgram(program); + glDeleteShader(fragment); + glDeleteShader(vertex); + throw std::runtime_error("Unable to retrieve program active uniforms"); + } + if (desc.uniform_input.enabled_uniforms.size() + desc.sampler_input.enabled_samplers.size() != static_cast(active_uniform_total)) { + glDeleteProgram(program); + glDeleteShader(fragment); + glDeleteShader(vertex); + std::string ex_msg("Pipeline's enabled uniform count (uniforms + samplers) does not match the linked program's total: "); + ex_msg.append(std::to_string(desc.uniform_input.enabled_uniforms.size())); + ex_msg.append(" vs "); + ex_msg.append(std::to_string(static_cast(active_uniform_total))); + throw std::runtime_error(std::move(ex_msg)); + } + for (GLint i = 0; i < active_uniform_total; i++) { + GLsizei name_len = 0; + GLint size = 0; + GLenum type = GL_ZERO; + char name[256]; + glGetActiveUniform(program, i, 255, &name_len, &size, &type, name); + active_uniforms.insert({std::string(name), Gles2ActiveUniform {type, static_cast(i)}}); + } + + for (auto& attr : desc.vertex_input.attr_layouts) { + const char* symbol_name = map_vertex_attribute_symbol_name(attr.name); + SRB2_ASSERT(symbol_name != nullptr); + if (active_attributes.find(symbol_name) == active_attributes.end()) { + glDeleteProgram(program); + glDeleteShader(fragment); + glDeleteShader(vertex); + throw std::runtime_error("Enabled attribute not found in linked program"); + } + auto& active_attr = active_attributes[symbol_name]; + auto expected_format = rhi::vertex_attribute_format(attr.name); + auto expected_gl_type = map_vertex_attribute_format(expected_format); + SRB2_ASSERT(expected_gl_type != GL_ZERO); + if (expected_gl_type != active_attr.type) { + glDeleteProgram(program); + glDeleteShader(fragment); + glDeleteShader(vertex); + throw std::runtime_error("Active attribute type does not match expected type"); + } + + pipeline.attrib_locations.insert({attr.name, active_attr.location}); + } + for (auto& uniform : desc.uniform_input.enabled_uniforms) { + const char* symbol_name = map_uniform_attribute_symbol_name(uniform); + SRB2_ASSERT(symbol_name != nullptr); + if (active_uniforms.find(symbol_name) == active_uniforms.end()) { + glDeleteProgram(program); + glDeleteShader(fragment); + glDeleteShader(vertex); + throw std::runtime_error("Enabled uniform not found in linked program"); + } + auto& active_uniform = active_uniforms[symbol_name]; + auto expected_format = rhi::uniform_format(uniform); + auto expected_gl_type = map_uniform_format(expected_format); + SRB2_ASSERT(expected_gl_type != GL_ZERO); + if (expected_gl_type != active_uniform.type) { + glDeleteProgram(program); + glDeleteShader(fragment); + glDeleteShader(vertex); + throw std::runtime_error("Active uniform type does not match expected type"); + } + + pipeline.uniform_locations.insert({uniform, active_uniform.location}); + } + for (auto& sampler : desc.sampler_input.enabled_samplers) { + const char* symbol_name = map_sampler_symbol_name(sampler); + SRB2_ASSERT(symbol_name != nullptr); + if (active_uniforms.find(symbol_name) == active_uniforms.end()) { + glDeleteProgram(program); + glDeleteShader(fragment); + glDeleteShader(vertex); + throw std::runtime_error("Enabled sampler not found in linked program"); + } + auto& active_sampler = active_uniforms[symbol_name]; + if (active_sampler.type != GL_SAMPLER_2D) { + glDeleteProgram(program); + glDeleteShader(fragment); + glDeleteShader(vertex); + throw std::runtime_error("Active sampler type does not match expected type"); + } + + pipeline.sampler_locations.insert({sampler, active_sampler.location}); + } + + pipeline.desc = desc; + pipeline.vertex_shader = vertex; + pipeline.fragment_shader = fragment; + pipeline.program = program; + + return pipeline_slab_.insert(std::make_unique(std::move(pipeline))); +} + +void Gles2Rhi::destroy_pipeline(rhi::Handle&& handle) { + SRB2_ASSERT(graphics_context_active_ == false); + + SRB2_ASSERT(pipeline_slab_.is_valid(handle) == true); + std::unique_ptr casted = static_unique_ptr_cast(pipeline_slab_.remove(handle)); + GLuint vertex_shader = casted->vertex_shader; + GLuint fragment_shader = casted->fragment_shader; + GLuint program = casted->program; + + disposal_.push_back([=] { glDeleteShader(fragment_shader); }); + disposal_.push_back([=] { glDeleteShader(vertex_shader); }); + disposal_.push_back([=] { glDeleteProgram(program); }); +} + +rhi::Handle Gles2Rhi::begin_graphics() { + SRB2_ASSERT(graphics_context_active_ == false); + graphics_context_active_ = true; + return rhi::Handle(0, graphics_context_generation_); +} + +void Gles2Rhi::end_graphics(rhi::Handle&& handle) { + SRB2_ASSERT(graphics_context_active_ == true); + SRB2_ASSERT(current_pipeline_.has_value() == false && current_render_pass_.has_value() == false); + graphics_context_generation_ += 1; + graphics_context_active_ = false; + glFlush(); +} + +void Gles2Rhi::present() { + SRB2_ASSERT(platform_ != nullptr); + SRB2_ASSERT(graphics_context_active_ == false); + + platform_->present(); +} + +void Gles2Rhi::begin_default_render_pass(Handle ctx) { + SRB2_ASSERT(platform_ != nullptr); + SRB2_ASSERT(graphics_context_active_ == true); + SRB2_ASSERT(current_render_pass_.has_value() == false); + + const Rect fb_rect = platform_->get_default_framebuffer_dimensions(); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glViewport(0, 0, fb_rect.w, fb_rect.h); + + glClearColor(0.5f, 0.5f, 0.5f, 1.0f); + glClearDepthf(1.0f); + glClearStencil(0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + current_render_pass_ = Gles2Rhi::DefaultRenderPassState {}; +} + +void Gles2Rhi::begin_render_pass(Handle ctx, const RenderPassBeginInfo& info) { + SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); + SRB2_ASSERT(current_render_pass_.has_value() == false); + + SRB2_ASSERT(render_pass_slab_.is_valid(info.render_pass) == true); + auto& rp = *static_cast(&render_pass_slab_[info.render_pass]); + SRB2_ASSERT(rp.desc.depth_format.has_value() == info.depth_attachment.has_value()); + + auto fb_itr = framebuffers_.find(Gles2FramebufferKey {info.color_attachment, info.depth_attachment}); + if (fb_itr == framebuffers_.end()) { + // Create a new framebuffer for this color-depth pair + GLuint fb_name; + glGenFramebuffers(1, &fb_name); + glBindFramebuffer(GL_FRAMEBUFFER, fb_name); + fb_itr = framebuffers_.insert( + {Gles2FramebufferKey {info.color_attachment, info.depth_attachment}, static_cast(fb_name)}).first; + + // TODO bind buffers correctly + } + auto& fb = *fb_itr; + glBindFramebuffer(GL_FRAMEBUFFER, fb.second); + + if (rp.desc.load_op == rhi::AttachmentLoadOp::kClear) { + glClearColor(info.clear_color.r, info.clear_color.g, info.clear_color.b, info.clear_color.a); + glClearDepthf(1.f); + glClearStencil(0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + } + + current_render_pass_ = info; +} + +void Gles2Rhi::end_render_pass(Handle ctx) { + SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); + SRB2_ASSERT(current_render_pass_.has_value() == true); + + current_pipeline_ = std::nullopt; + current_render_pass_ = std::nullopt; +} + +void Gles2Rhi::bind_pipeline(Handle ctx, Handle pipeline) { + SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); + SRB2_ASSERT(current_render_pass_.has_value() == true); + + SRB2_ASSERT(pipeline_slab_.is_valid(pipeline) == true); + auto& pl = *static_cast(&pipeline_slab_[pipeline]); + auto& desc = pl.desc; + + glUseProgram(pl.program); + + glDisable(GL_SCISSOR_TEST); + + if (desc.depth_attachment) { + glEnable(GL_DEPTH_TEST); + GLenum depth_func = map_compare_func(desc.depth_attachment->func); + SRB2_ASSERT(depth_func != GL_ZERO); + glDepthFunc(depth_func); + glDepthMask(desc.depth_attachment->write ? GL_TRUE : GL_FALSE); + } else { + glDisable(GL_DEPTH_TEST); + } + + if (desc.color_attachment.blend) { + rhi::BlendDesc& bl = *desc.color_attachment.blend; + glEnable(GL_BLEND); + glBlendFuncSeparate(map_blend_factor(bl.source_factor_color), + map_blend_factor(bl.dest_factor_color), + map_blend_factor(bl.source_factor_alpha), + map_blend_factor(bl.dest_factor_alpha)); + glBlendEquationSeparate(map_blend_function(bl.color_function), map_blend_function(bl.alpha_function)); + glBlendColor(desc.blend_color.r, desc.blend_color.g, desc.blend_color.b, desc.blend_color.a); + } else { + glDisable(GL_BLEND); + } + + glColorMask(desc.color_attachment.color_mask.r ? GL_TRUE : GL_FALSE, + desc.color_attachment.color_mask.g ? GL_TRUE : GL_FALSE, + desc.color_attachment.color_mask.b ? GL_TRUE : GL_FALSE, + desc.color_attachment.color_mask.a ? GL_TRUE : GL_FALSE); + + GLenum cull_face = map_cull_mode(desc.cull); + if (cull_face == GL_NONE) { + glDisable(GL_CULL_FACE); + } else { + glEnable(GL_CULL_FACE); + glCullFace(cull_face); + } + glFrontFace(map_winding(desc.winding)); + + current_pipeline_ = pipeline; + current_primitive_type_ = desc.primitive; +} + +void Gles2Rhi::update_bindings(Handle ctx, const UpdateBindingsInfo& info) { + SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); + SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); + + SRB2_ASSERT(pipeline_slab_.is_valid(*current_pipeline_)); + auto& pl = *static_cast(&pipeline_slab_[*current_pipeline_]); + + // TODO assert compatibility of binding data with pipeline + SRB2_ASSERT(info.vertex_buffers.size() == pl.desc.vertex_input.buffer_layouts.size()); + SRB2_ASSERT(info.sampler_textures.size() == pl.desc.sampler_input.enabled_samplers.size()); + + // TODO only disable the vertex attributes of the previously bound pipeline (performance) + for (GLuint i = 0; i < kMaxVertexAttributes; i++) { + glDisableVertexAttribArray(i); + } + + // Update the vertex attributes with the new vertex buffer bindings. + + // OpenGL ES does not require binding buffers to the pipeline the same way Vulkan does. + // Instead, we need to find the pipeline vertex attributes which would be affected by + // the changing set of vertex buffers, and reassign their Vertex Attribute Pointers. + for (size_t i = 0; i < pl.desc.vertex_input.attr_layouts.size(); i++) { + auto& attr_layout = pl.desc.vertex_input.attr_layouts[i]; + uint32_t attr_buffer_index = attr_layout.buffer_index; + VertexAttributeName attr_name = attr_layout.name; + + auto& buffer_layout = pl.desc.vertex_input.buffer_layouts[attr_buffer_index]; + + SRB2_ASSERT(pl.attrib_locations.find(attr_name) != pl.attrib_locations.end()); + auto gl_attr_location = pl.attrib_locations[pl.desc.vertex_input.attr_layouts[i].name]; + + VertexAttributeFormat vert_attr_format = rhi::vertex_attribute_format(attr_name); + GLenum vertex_attr_type = map_vertex_attribute_type(vert_attr_format); + SRB2_ASSERT(vertex_attr_type != GL_ZERO); + GLint vertex_attr_size = map_vertex_attribute_format_size(vert_attr_format); + SRB2_ASSERT(vertex_attr_size != 0); + + rhi::Handle vertex_buffer_handle; + uint32_t vertex_buffer_offset; + std::tie(vertex_buffer_handle, vertex_buffer_offset) = info.vertex_buffers[attr_layout.buffer_index]; + SRB2_ASSERT(buffer_slab_.is_valid(vertex_buffer_handle) == true); + auto& buffer = *static_cast(&buffer_slab_[vertex_buffer_handle]); + SRB2_ASSERT(buffer.desc.type == rhi::BufferType::kVertexBuffer); + + glBindBuffer(GL_ARRAY_BUFFER, buffer.buffer); + glEnableVertexAttribArray(gl_attr_location); + glVertexAttribPointer(gl_attr_location, vertex_attr_size, vertex_attr_type, GL_FALSE, buffer_layout.stride, reinterpret_cast(vertex_buffer_offset + attr_layout.offset)); + } + + rhi::Handle index_buffer_handle; + std::tie(index_buffer_handle, index_buffer_offset_) = info.index_buffer; + if (index_buffer_handle == rhi::kNullHandle) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } else { + SRB2_ASSERT(buffer_slab_.is_valid(index_buffer_handle)); + auto& ib = *static_cast(&buffer_slab_[index_buffer_handle]); + SRB2_ASSERT(ib.desc.type == rhi::BufferType::kIndexBuffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib.buffer); + } + + for (size_t i = 0; i < info.sampler_textures.size(); i++) { + auto& sampler_name = pl.desc.sampler_input.enabled_samplers[i]; + rhi::Handle texture_handle = info.sampler_textures[i]; + SRB2_ASSERT(texture_slab_.is_valid(texture_handle)); + auto& t = *static_cast(&texture_slab_[texture_handle]); + SRB2_ASSERT(pl.sampler_locations.find(sampler_name) != pl.sampler_locations.end()); + GLuint sampler_uniform_loc = pl.sampler_locations[sampler_name]; + + GLenum active_texture = GL_TEXTURE0; + GLuint uniform_value = 0; + + switch (sampler_name) { + case rhi::SamplerName::kSampler0: + active_texture = GL_TEXTURE0; + uniform_value = 0; + break; + case rhi::SamplerName::kSampler1: + active_texture = GL_TEXTURE0 + 1; + uniform_value = 1; + break; + case rhi::SamplerName::kSampler2: + active_texture = GL_TEXTURE0 + 2; + uniform_value = 2; + break; + case rhi::SamplerName::kSampler3: + active_texture = GL_TEXTURE0 + 3; + uniform_value = 3; + break; + } + glActiveTexture(active_texture); + glBindTexture(GL_TEXTURE_2D, t.texture); + glUniform1i(sampler_uniform_loc, uniform_value); + } +} + +void Gles2Rhi::update_uniforms(Handle ctx, tcb::span uniforms) { + SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); + SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); + + SRB2_ASSERT(pipeline_slab_.is_valid(*current_pipeline_)); + auto& pl = *static_cast(&pipeline_slab_[*current_pipeline_]); + + // TODO assert compatibility of uniform data with pipeline + // The uniforms need to be the same size, names and value types as the pipeline. + // RHI doesn't support updating selectively; the whole set must be updated at once altogether. + SRB2_ASSERT(uniforms.size() == pl.desc.uniform_input.enabled_uniforms.size()); + + for (size_t i = 0; i < uniforms.size(); i++) { + auto& update_data = uniforms[i]; + + SRB2_ASSERT(pl.uniform_locations.find(update_data.name) != pl.uniform_locations.end()); + SRB2_ASSERT(pl.desc.uniform_input.enabled_uniforms[i] == update_data.name); + GLuint pipeline_uniform = pl.uniform_locations[update_data.name]; + + struct UniformVariantVisitor { + rhi::UniformName name; + GLuint uniform; + + void operator()(const float& value) const noexcept { + SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kFloat); + glUniform1f(uniform, value); + } + void operator()(const std::array& value) const noexcept { + SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kFloat2); + glUniform2f(uniform, value[0], value[1]); + } + void operator()(const std::array& value) const noexcept { + SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kFloat3); + glUniform3f(uniform, value[0], value[1], value[2]); + } + void operator()(const std::array& value) const noexcept { + SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kFloat4); + glUniform4f(uniform, value[0], value[1], value[2], value[3]); + } + void operator()(const int32_t& value) const noexcept { + SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kInt); + glUniform1i(uniform, value); + } + void operator()(const std::array& value) const noexcept { + SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kInt2); + glUniform2i(uniform, value[0], value[1]); + } + void operator()(const std::array& value) const noexcept { + SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kInt3); + glUniform3i(uniform, value[0], value[1], value[2]); + } + void operator()(const std::array& value) const noexcept { + SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kInt4); + glUniform4i(uniform, value[0], value[1], value[2], value[3]); + } + void operator()(const std::array, 2>& value) const noexcept { + SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kMat2); + glUniformMatrix2fv(uniform, 1, false, reinterpret_cast(&value)); + } + void operator()(const std::array, 3>& value) const noexcept { + SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kMat3); + glUniformMatrix3fv(uniform, 1, false, reinterpret_cast(&value)); + } + void operator()(const std::array, 4>& value) const noexcept { + SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kMat4); + glUniformMatrix4fv(uniform, 1, false, reinterpret_cast(&value)); + } + }; + std::visit(UniformVariantVisitor {update_data.name, pipeline_uniform}, update_data.value); + } +} + +void Gles2Rhi::set_scissor(Handle ctx, const Rect& rect) { + SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); + SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); + // TODO handle scissor pipeline state +} + +void Gles2Rhi::set_viewport(Handle ctx, const Rect& rect) { + SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); + SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); + // TODO handle viewport pipeline state +} + +void Gles2Rhi::draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) { + SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); + SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); + + glDrawArrays(map_primitive_mode(current_primitive_type_), first_vertex, vertex_count); +} + +void Gles2Rhi::draw_indexed(Handle ctx, + uint32_t index_count, + uint32_t first_index, + uint32_t vertex_offset) { + SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); + glDrawElements(map_primitive_mode(current_primitive_type_), first_index, GL_UNSIGNED_SHORT, reinterpret_cast(index_buffer_offset_)); +} + +void Gles2Rhi::finish() { + SRB2_ASSERT(graphics_context_active_ == false); + + for (auto it = disposal_.begin(); it != disposal_.end(); it++) { + (*it)(); + } + disposal_.clear(); +} + +void rhi::load_gles2(Gles2LoadFunc func) { + gladLoadGLES2(static_cast(func)); +} diff --git a/src/rhi/gles2/gles2_rhi.hpp b/src/rhi/gles2/gles2_rhi.hpp new file mode 100644 index 000000000..4f19aa7c5 --- /dev/null +++ b/src/rhi/gles2/gles2_rhi.hpp @@ -0,0 +1,135 @@ +#ifndef __SRB2_RHI_GLES2_RHI_HPP__ +#define __SRB2_RHI_GLES2_RHI_HPP__ + +#include +#include +#include +#include +#include +#include +#include + +#include "../rhi.hpp" + +namespace srb2::rhi { + +struct Gles2FramebufferKey { + TextureOrRenderbuffer color; + std::optional depth; + + bool operator==(const Gles2FramebufferKey& rhs) const noexcept { + return color == rhs.color && depth == rhs.depth; + } + + bool operator!=(const Gles2FramebufferKey& rhs) const noexcept { + return !(*this == rhs); + } +}; + +} // namespace srb2::rhi + +// To make sure the compiler selects the struct specialization of std::hash for Gles2FramebufferKey, +// we need to split the namespace declarations _before_ the instantiation of std::unordered_map. + +template <> +struct std::hash { + std::size_t operator()(const srb2::rhi::Gles2FramebufferKey& key) const { + struct GetHandleHashVisitor { + uint32_t operator()(const srb2::rhi::Handle& handle) const noexcept { + return std::hash>()(handle); + } + uint32_t operator()(const srb2::rhi::Handle& handle) const noexcept { + return std::hash>()(handle); + } + }; + std::size_t color_hash = std::visit(GetHandleHashVisitor {}, key.color); + std::size_t depth_hash = 0; + if (key.depth) { + depth_hash = std::visit(GetHandleHashVisitor {}, *key.depth); + } + return color_hash ^ (depth_hash << 1); + } +}; + +namespace srb2::rhi { + +/// @brief Platform-specific implementation details for the GLES2 backend. +struct Gles2Platform { + virtual ~Gles2Platform(); + + virtual void present() = 0; + virtual std::tuple find_shader_sources(PipelineProgram program) = 0; + virtual Rect get_default_framebuffer_dimensions() = 0; +}; + +class Gles2Rhi final : public Rhi { + std::unique_ptr platform_; + + Slab render_pass_slab_; + Slab texture_slab_; + Slab buffer_slab_; + Slab renderbuffer_slab_; + Slab pipeline_slab_; + + std::unordered_map framebuffers_ {16}; + + struct DefaultRenderPassState {}; + using RenderPassState = std::variant; + std::optional current_render_pass_; + std::optional> current_pipeline_; + PrimitiveType current_primitive_type_ = PrimitiveType::kPoints; + bool graphics_context_active_ = false; + uint32_t graphics_context_generation_ = 0; + uint32_t index_buffer_offset_ = 0; + + std::vector> disposal_; + +public: + Gles2Rhi(std::unique_ptr&& platform); + virtual ~Gles2Rhi(); + + virtual Handle create_render_pass(const RenderPassDesc& desc) override; + virtual void destroy_render_pass(Handle&& handle) override; + virtual Handle create_texture(const TextureDesc& desc, srb2::rhi::PixelFormat data_format, tcb::span data) override; + virtual void destroy_texture(Handle&& handle) override; + virtual Handle create_buffer(const BufferDesc& desc, tcb::span data) override; + virtual void destroy_buffer(Handle&& handle) override; + virtual Handle create_renderbuffer(const RenderbufferDesc& desc) override; + virtual void destroy_renderbuffer(Handle&& handle) override; + virtual Handle create_pipeline(const PipelineDesc& desc) override; + virtual void destroy_pipeline(Handle&& handle) override; + + virtual void update_buffer_contents(Handle buffer, uint32_t offset, tcb::span data) override; + virtual void update_texture(Handle texture, Rect region, srb2::rhi::PixelFormat data_format, tcb::span data) override; + + virtual Handle begin_graphics() override; + virtual void end_graphics(Handle&& ctx) override; + + // Graphics context functions + virtual void begin_default_render_pass(Handle ctx) override; + virtual void begin_render_pass(Handle ctx, const RenderPassBeginInfo& info) override; + virtual void end_render_pass(Handle ctx) override; + virtual void bind_pipeline(Handle ctx, Handle pipeline) override; + virtual void update_bindings(Handle ctx, const UpdateBindingsInfo& info) override; + virtual void update_uniforms(Handle ctx, tcb::span uniforms) override; + virtual void set_scissor(Handle ctx, const Rect& rect) override; + virtual void set_viewport(Handle ctx, const Rect& rect) override; + virtual void draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) override; + virtual void draw_indexed(Handle ctx, + uint32_t index_count, + uint32_t first_index, + uint32_t vertex_offset) override; + + virtual void present() override; + + virtual void finish() override; +}; + +typedef void (*Gles2Proc)(void); +typedef Gles2Proc (*Gles2LoadFunc)(const char* name); + +void load_gles2(Gles2LoadFunc func); + +} // namespace srb2::rhi + +#endif // __SRB2_RHI_GLES2_RHI_HPP__ diff --git a/src/rhi/handle.hpp b/src/rhi/handle.hpp new file mode 100644 index 000000000..7a780d8ca --- /dev/null +++ b/src/rhi/handle.hpp @@ -0,0 +1,317 @@ +#ifndef __SRB2_RHI_HANDLE_HPP__ +#define __SRB2_RHI_HANDLE_HPP__ + +#include +#include +#include +#include +#include +#include + +#include "../cxxutil.hpp" + +namespace srb2::rhi { + +struct NullHandleType {}; + +constexpr const NullHandleType kNullHandle = NullHandleType {}; + +template +class Handle { + uint32_t id_; + uint32_t generation_; + +public: + Handle(uint32_t id, uint32_t generation) noexcept : id_(id), generation_(generation) {} + Handle(uint64_t combined) noexcept + : id_(combined & 0xFFFFFFFF) + , generation_((combined & 0xFFFFFFFF00000000) >> 32) + {} + Handle() noexcept : Handle(0, 0) {} + + Handle(NullHandleType) noexcept : Handle() {} + + Handle(const Handle&) = default; + Handle(Handle&& rhs) noexcept { + id_ = std::exchange(rhs.id_, 0); + generation_ = std::exchange(rhs.generation_, 0); + }; + + Handle& operator=(const Handle&) = default; + Handle& operator=(Handle&& rhs) noexcept { + id_ = std::exchange(rhs.id_, 0); + generation_ = std::exchange(rhs.generation_, 0); + return *this; + } + + // Conversions from Handles of derived type U to base type T + + template , bool> = true> + Handle(const Handle& rhs) noexcept : id_(rhs.id_), generation_(rhs.generation_) {} + + template , bool> = true> + Handle(Handle&& rhs) noexcept { + id_ = std::exchange(rhs.id_, 0); + generation_ = std::exchange(rhs.generation_, 0); + } + + template , bool> = true> + Handle& operator=(const Handle& rhs) noexcept { + id_ = rhs.id_; + generation_ = rhs.generation_; + } + + template , bool> = true> + Handle& operator=(Handle&& rhs) noexcept { + id_ = std::exchange(rhs.id_, 0); + generation_ = std::exchange(rhs.generation_, 0); + return *this; + } + + uint32_t id() const noexcept { return id_; } + uint32_t generation() const noexcept { return generation_; } + + /// @return true if this Handle is valid (belonging to a generation > 0); false otherwise + bool valid() const noexcept { return generation_ != 0; } + + bool operator==(const Handle& handle) const noexcept { + return handle.generation_ == generation_ && handle.id_ == id_; + } + bool operator!=(const Handle& handle) const noexcept { return !(handle == *this); } + bool operator==(const NullHandleType&) const noexcept { return generation_ == 0; } + bool operator!=(const NullHandleType&) const noexcept { return generation_ != 0; } + + operator bool() const { return id_ != 0 || generation_ != 0; } + operator uint64_t() const { return static_cast(id_) + (static_cast(generation_) << 32); } +}; + +template +inline bool operator==(const Handle& lhs, const NullHandleType&) noexcept +{ + return lhs.generation() == 0 || lhs.id() == 0; +} + +template +inline bool operator==(const Handle& lhs, const std::nullptr_t&) noexcept +{ + return lhs.generation() == 0 || lhs.id() == 0; +} + +// Non-member equality of base Handle to derived Handle + +template , bool> = true> +inline bool operator==(const Handle& lhs, const Handle& rhs) noexcept { + return lhs.generation() == rhs.generation() && lhs.id() == rhs.id(); +} + +template , bool> = true> +inline bool operator!=(const Handle& lhs, const Handle& rhs) noexcept { + return !(lhs == rhs); +} + +template +class HandlePool { + std::atomic_uint32_t current_id_ {0}; + std::atomic_uint32_t current_gen_ {1}; + +public: + HandlePool() = default; + HandlePool(const HandlePool& rhs) = delete; + HandlePool(HandlePool&& rhs) = default; + + HandlePool& operator=(const HandlePool& rhs) = delete; + HandlePool& operator=(HandlePool&& rhs) = default; + + /// @brief Create a new unique Handle in the current generation. + /// @return the new Handle. + Handle create() noexcept { + const uint32_t id = current_id_.fetch_add(1); + SRB2_ASSERT(id != UINT32_MAX); + const uint32_t gen = current_gen_.load(); + return Handle(id, gen); + } + + /// @brief Increment the generation. All handles created after this will belong to a new generation. + void generation() noexcept { + const uint32_t old_gen = current_gen_.fetch_add(1); + SRB2_ASSERT(old_gen != UINT32_MAX); + } +}; + +template +class Slab; + +template +class SlabIterator +{ + size_t index_ = 0; + const Slab>* slab_ = nullptr; + + SlabIterator(size_t index, const Slab>* slab) : index_(index), slab_(slab) {} + + friend Slab>; +public: + SlabIterator() = default; + SlabIterator(const SlabIterator&) = default; + SlabIterator(SlabIterator&&) = default; + + SlabIterator& operator=(const SlabIterator&) = default; + SlabIterator& operator=(SlabIterator&&) = default; + + T& operator*() const noexcept + { + return *slab_->vec_[index_].item.get(); + } + + SlabIterator& operator++() noexcept + { + index_++; + return *this; + } + + SlabIterator& operator--() noexcept + { + index_--; + return *this; + } + + SlabIterator operator++(int) noexcept + { + index_++; + return SlabIterator {index_ - 1, slab_}; + } + + SlabIterator operator--(int) noexcept + { + index_--; + return SlabIterator {index_ + 1, slab_}; + } + + bool operator==(const SlabIterator& rhs) const noexcept + { + return slab_ == rhs.slab_ && index_ == rhs.index_; + } + + bool operator!=(const SlabIterator& rhs) const noexcept + { + return !(*this == rhs); + } +}; + +template +class Slab { + struct SlabStorage { + std::unique_ptr item; + uint32_t gen; + }; + std::vector vec_; + std::vector free_list_; + uint32_t gen_ = 1; + + friend SlabIterator; + friend SlabIterator; +public: + Slab() = default; + Slab(const Slab&) = delete; + Slab& operator=(const Slab&) = delete; + + Handle insert(std::unique_ptr&& value) { + uint32_t ret_id = 0; + if (!free_list_.empty()) { + ret_id = free_list_.back(); + free_list_.pop_back(); + SlabStorage& storage = vec_[ret_id]; + storage.item = std::move(value); + storage.gen = gen_; + } else { + ret_id = vec_.size(); + vec_.push_back(SlabStorage {std::move(value), gen_}); + } + return Handle(ret_id, gen_); + } + + std::unique_ptr remove(Handle handle) { + uint32_t handle_id = handle.id(); + uint32_t handle_gen = handle.generation(); + if (handle_id >= vec_.size()) { + return nullptr; + } + SlabStorage& storage = vec_[handle_id]; + if (storage.gen > handle_gen) { + return nullptr; + } + std::unique_ptr ret = std::move(storage.item); + storage.item = nullptr; + free_list_.push_back(handle_id); + gen_ += 1; + if (gen_ == 0) + { + gen_ = 1; + } + return ret; + } + + bool is_valid(Handle handle) { + uint32_t handle_id = handle.id(); + uint32_t handle_gen = handle.generation(); + if (handle_id >= vec_.size()) { + return false; + } + SlabStorage& storage = vec_[handle_id]; + if (storage.gen > handle_gen) { + return false; + } + return true; + } + + void clear() + { + vec_.clear(); + free_list_.clear(); + gen_ += 1; + if (gen_ == 0) + { + gen_ = 1; + } + } + + T& operator[](Handle handle) { + SRB2_ASSERT(is_valid(handle)); + return *vec_[handle.id()].item; + } + + SlabIterator begin() + { + return SlabIterator {0, this}; + } + + SlabIterator end() + { + return SlabIterator {vec_.size(), this}; + } + + SlabIterator cbegin() const + { + return SlabIterator {0, this}; + } + + SlabIterator cend() const + { + return SlabIterator {vec_.size(), this}; + } +}; + +} // namespace srb2::rhi + +namespace std { + +template +struct hash> { + std::size_t operator()(const srb2::rhi::Handle& e) const { + return std::hash()(e.generation()) ^ (std::hash()(e.id()) << 1); + } +}; + +} // namespace std + +#endif // __SRB2_RHI_HANDLE_HPP__ diff --git a/src/rhi/rhi.cpp b/src/rhi/rhi.cpp new file mode 100644 index 000000000..c5fd0b973 --- /dev/null +++ b/src/rhi/rhi.cpp @@ -0,0 +1,51 @@ +#include "rhi.hpp" + +#include +#include + +using namespace srb2; +using namespace srb2::rhi; + +Rhi::~Rhi() = default; + +const ProgramRequirements srb2::rhi::kProgramRequirementsUnshaded = { + ProgramVertexInputRequirements {{ + ProgramVertexInput {VertexAttributeName::kPosition, VertexAttributeFormat::kFloat3, true}, + ProgramVertexInput {VertexAttributeName::kTexCoord0, VertexAttributeFormat::kFloat2, false}, + ProgramVertexInput {VertexAttributeName::kColor, VertexAttributeFormat::kFloat4, false} + }}, + ProgramUniformRequirements {{ + {{UniformName::kProjection}}, + {{UniformName::kModelView, UniformName::kTexCoord0Transform}} + }}, + ProgramSamplerRequirements {{ + ProgramSamplerInput {SamplerName::kSampler0, true} + }} +}; + +const ProgramRequirements srb2::rhi::kProgramRequirementsUnshadedPaletted = { + ProgramVertexInputRequirements {{ + ProgramVertexInput {VertexAttributeName::kPosition, VertexAttributeFormat::kFloat3, true}, + ProgramVertexInput {VertexAttributeName::kTexCoord0, VertexAttributeFormat::kFloat2, false}, + ProgramVertexInput {VertexAttributeName::kColor, VertexAttributeFormat::kFloat4, false} + }}, + ProgramUniformRequirements {{ + {{UniformName::kProjection}}, + {{UniformName::kModelView, UniformName::kTexCoord0Transform}} + }}, + ProgramSamplerRequirements {{ + ProgramSamplerInput {SamplerName::kSampler0, true}, + ProgramSamplerInput {SamplerName::kSampler1, true} + }} +}; + +const ProgramRequirements& rhi::program_requirements_for_program(PipelineProgram program) noexcept { + switch (program) { + case PipelineProgram::kUnshaded: + return kProgramRequirementsUnshaded; + case PipelineProgram::kUnshadedPaletted: + return kProgramRequirementsUnshadedPaletted; + default: + std::terminate(); + } +} diff --git a/src/rhi/rhi.hpp b/src/rhi/rhi.hpp new file mode 100644 index 000000000..1da54fbf0 --- /dev/null +++ b/src/rhi/rhi.hpp @@ -0,0 +1,466 @@ +#ifndef __SRB2_RHI_RHI_HPP__ +#define __SRB2_RHI_RHI_HPP__ + +#include +#include +#include +#include +#include + +#include + +#include "../core/static_vec.hpp" +#include "handle.hpp" + +namespace srb2::rhi { + +struct Buffer {}; + +struct Texture {}; + +struct Pipeline {}; + +struct RenderPass {}; + +struct Renderbuffer {}; + +using TextureOrRenderbuffer = std::variant, Handle>; + +enum class VertexAttributeFormat { + kFloat, + kFloat2, + kFloat3, + kFloat4 +}; + +enum class UniformFormat { + kFloat, + kFloat2, + kFloat3, + kFloat4, + kInt, + kInt2, + kInt3, + kInt4, + kMat2, + kMat3, + kMat4 +}; + +enum class PixelFormat { + kR8, + kRGBA8, + kDepth16, + kStencil8 +}; + +enum class TextureFormat { + kLuminance, + kRGB, + kRGBA +}; + +enum class CompareFunc { + kNever, + kLess, + kEqual, + kLessEqual, + kGreater, + kNotEqual, + kGreaterEqual, + kAlways +}; + +enum class BlendFactor { + kZero, + kOne, + kSource, + kOneMinusSource, + kSourceAlpha, + kOneMinusSourceAlpha, + kDest, + kOneMinusDest, + kDestAlpha, + kOneMinusDestAlpha, + kConstant, + kOneMinusConstant, + kConstantAlpha, + kOneMinusConstantAlpha, + kSourceAlphaSaturated +}; + +enum class BlendFunction { + kAdd, + kSubtract, + kReverseSubtract +}; + +enum class PrimitiveType { + kPoints, + kLines, + kLineStrip, + kTriangles, + kTriangleStrip, + kTriangleFan +}; + +enum class CullMode { + kNone, + kFront, + kBack +}; + +enum class FaceWinding { + kCounterClockwise, + kClockwise +}; + +enum class AttachmentLoadOp { + kLoad, + kClear, + kDontCare +}; + +enum class AttachmentStoreOp { + kStore, + kDontCare +}; + +enum class PipelineProgram { + kUnshaded, + kUnshadedPaletted +}; + +enum class BufferType { + kVertexBuffer, + kIndexBuffer +}; + +enum class BufferUsage { + kImmutable, + kDynamic +}; + +enum class VertexAttributeName { + kPosition, + kNormal, + kTexCoord0, + kTexCoord1, + kColor +}; + +enum class UniformName { + kTime, + kModelView, + kProjection, + kTexCoord0Transform +}; + +enum class SamplerName { + kSampler0, + kSampler1, + kSampler2, + kSampler3 +}; + +struct Color { + float r; + float g; + float b; + float a; +}; + +struct Rect { + int32_t x; + int32_t y; + uint32_t w; + uint32_t h; +}; + +constexpr const size_t kMaxVertexAttributes = 8; +constexpr const size_t kMaxSamplers = 4; + +struct ProgramVertexInput { + VertexAttributeName name; + VertexAttributeFormat type; + bool required; +}; + +struct ProgramUniformInput { + UniformName name; + bool required; +}; + +struct ProgramSamplerInput { + SamplerName name; + bool required; +}; + +struct ProgramVertexInputRequirements { + srb2::StaticVec attributes; +}; + +struct ProgramUniformRequirements { + srb2::StaticVec, 4> uniform_groups; +}; + +struct ProgramSamplerRequirements { + std::array, kMaxSamplers> samplers; +}; + +struct ProgramRequirements { + ProgramVertexInputRequirements vertex_input; + ProgramUniformRequirements uniforms; + ProgramSamplerRequirements samplers; +}; + +extern const ProgramRequirements kProgramRequirementsUnshaded; +extern const ProgramRequirements kProgramRequirementsUnshadedPaletted; + +const ProgramRequirements& program_requirements_for_program(PipelineProgram program) noexcept; + +inline constexpr const VertexAttributeFormat vertex_attribute_format(VertexAttributeName name) noexcept +{ + switch (name) { + case VertexAttributeName::kPosition: + return VertexAttributeFormat::kFloat3; + case VertexAttributeName::kNormal: + return VertexAttributeFormat::kFloat3; + case VertexAttributeName::kTexCoord0: + return VertexAttributeFormat::kFloat2; + case VertexAttributeName::kTexCoord1: + return VertexAttributeFormat::kFloat2; + case VertexAttributeName::kColor: + return VertexAttributeFormat::kFloat4; + default: + return VertexAttributeFormat::kFloat; + }; +} + +inline constexpr const UniformFormat uniform_format(UniformName name) noexcept +{ + switch (name) { + case UniformName::kTime: + return UniformFormat::kFloat; + case UniformName::kModelView: + return UniformFormat::kMat4; + case UniformName::kProjection: + return UniformFormat::kMat4; + case UniformName::kTexCoord0Transform: + return UniformFormat::kMat3; + default: + return UniformFormat::kFloat; + } +} + +struct VertexBufferLayoutDesc { + uint32_t stride; +}; + +struct VertexAttributeLayoutDesc { + VertexAttributeName name; + uint32_t buffer_index; + uint32_t offset; +}; + +// constexpr const size_t kMaxVertexBufferBindings = 4; + +struct VertexInputDesc { + std::vector buffer_layouts; + std::vector attr_layouts; +}; + +struct UniformInputDesc { + srb2::StaticVec, 4> enabled_uniforms; +}; + +struct SamplerInputDesc { + std::vector enabled_samplers; +}; + +struct ColorMask { + bool r; + bool g; + bool b; + bool a; +}; + +struct BlendDesc { + BlendFactor source_factor_color; + BlendFactor dest_factor_color; + BlendFunction color_function; + BlendFactor source_factor_alpha; + BlendFactor dest_factor_alpha; + BlendFunction alpha_function; +}; + +struct PipelineDepthAttachmentDesc { + PixelFormat format; + CompareFunc func; + bool write; +}; + +struct PipelineColorAttachmentDesc { + PixelFormat format; + std::optional blend; + ColorMask color_mask; +}; + +struct PipelineDesc { + PipelineProgram program; + VertexInputDesc vertex_input; + UniformInputDesc uniform_input; + SamplerInputDesc sampler_input; + std::optional depth_attachment; + // std::optional stencil_attachment; + PipelineColorAttachmentDesc color_attachment; + PrimitiveType primitive; + CullMode cull; + FaceWinding winding; + Color blend_color; +}; + +struct RenderPassDesc { + std::optional depth_format; + PixelFormat color_format; + AttachmentLoadOp load_op; + AttachmentStoreOp store_op; +}; + +struct RenderbufferDesc { + PixelFormat format; + uint32_t width; + uint32_t height; +}; + +struct TextureDesc { + TextureFormat format; + uint32_t width; + uint32_t height; +}; + +struct BufferDesc { + uint32_t size; + BufferType type; + BufferUsage usage; +}; + +struct RenderPassBeginInfo { + Handle render_pass; + TextureOrRenderbuffer color_attachment; + std::optional depth_attachment; + Color clear_color; +}; + +using UniformVariant = std::variant< + float, + std::array, + std::array, + std::array, + + int32_t, + std::array, + std::array, + std::array, + + // The indexing order of matrices is [row][column]. + + std::array, 2>, + std::array, 3>, + std::array, 4> +>; + +inline constexpr UniformFormat uniform_variant_format(const UniformVariant& variant) +{ + struct Visitor + { + UniformFormat operator()(const float&) const noexcept { return UniformFormat::kFloat; } + UniformFormat operator()(const std::array&) const noexcept { return UniformFormat::kFloat2; } + UniformFormat operator()(const std::array&) const noexcept { return UniformFormat::kFloat3; } + UniformFormat operator()(const std::array&) const noexcept { return UniformFormat::kFloat4; } + UniformFormat operator()(const int32_t&) const noexcept { return UniformFormat::kInt; } + UniformFormat operator()(const std::array&) const noexcept { return UniformFormat::kInt2; } + UniformFormat operator()(const std::array&) const noexcept { return UniformFormat::kInt3; } + UniformFormat operator()(const std::array&) const noexcept { return UniformFormat::kInt4; } + UniformFormat operator()(const std::array, 2>&) const noexcept { return UniformFormat::kMat2; } + UniformFormat operator()(const std::array, 3>&) const noexcept { return UniformFormat::kMat3; } + UniformFormat operator()(const std::array, 4>&) const noexcept { return UniformFormat::kMat4; } + }; + return std::visit(Visitor{}, variant); +} + +struct VertexAttributeBufferBinding { + uint32_t attribute_index; + Handle vertex_buffer; +}; + +struct TextureBinding { + SamplerName name; + Handle texture; +}; + +struct CreateUniformSetInfo { + tcb::span uniforms; +}; + +struct CreateBindingSetInfo { + tcb::span vertex_buffers; + tcb::span sampler_textures; +}; + +struct UniformSet {}; +struct BindingSet {}; + +struct TransferContext {}; +struct GraphicsContext {}; + +/// @brief An active handle to a rendering device. +struct Rhi { + virtual ~Rhi(); + + virtual Handle create_render_pass(const RenderPassDesc& desc) = 0; + virtual void destroy_render_pass(Handle handle) = 0; + virtual Handle create_pipeline(const PipelineDesc& desc) = 0; + virtual void destroy_pipeline(Handle handle) = 0; + + virtual Handle create_texture(const TextureDesc& desc) = 0; + virtual void destroy_texture(Handle handle) = 0; + virtual Handle create_buffer(const BufferDesc& desc) = 0; + virtual void destroy_buffer(Handle handle) = 0; + virtual Handle create_renderbuffer(const RenderbufferDesc& desc) = 0; + virtual void destroy_renderbuffer(Handle handle) = 0; + + virtual Handle begin_transfer() = 0; + virtual void end_transfer(Handle handle) = 0; + + // Transfer Context functions + virtual void update_buffer_contents(Handle ctx, Handle buffer, uint32_t offset, tcb::span data) = 0; + virtual void update_texture(Handle ctx, Handle texture, Rect region, srb2::rhi::PixelFormat data_format, tcb::span data) = 0; + virtual Handle create_uniform_set(Handle ctx, const CreateUniformSetInfo& info) = 0; + virtual Handle create_binding_set(Handle ctx, Handle pipeline, const CreateBindingSetInfo& info) = 0; + + virtual Handle begin_graphics() = 0; + virtual void end_graphics(Handle ctx) = 0; + + // Graphics context functions + virtual void begin_default_render_pass(Handle ctx, bool clear) = 0; + virtual void begin_render_pass(Handle ctx, const RenderPassBeginInfo& info) = 0; + virtual void end_render_pass(Handle ctx) = 0; + virtual void bind_pipeline(Handle ctx, Handle pipeline) = 0; + virtual void bind_uniform_set(Handle ctx, uint32_t slot, Handle set) = 0; + virtual void bind_binding_set(Handle ctx, Handle set) = 0; + virtual void bind_index_buffer(Handle ctx, Handle buffer) = 0; + virtual void set_scissor(Handle ctx, const Rect& rect) = 0; + virtual void set_viewport(Handle ctx, const Rect& rect) = 0; + virtual void draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) = 0; + virtual void draw_indexed(Handle ctx, uint32_t index_count, uint32_t first_index) = 0; + virtual void read_pixels(Handle ctx, const Rect& rect, tcb::span out) = 0; + + virtual void present() = 0; + + virtual void finish() = 0; +}; + +} // namespace srb2::rhi + +#endif // __SRB2_RHI_RHI_HPP__ diff --git a/src/screen.h b/src/screen.h index 23498de59..f76fe05a3 100644 --- a/src/screen.h +++ b/src/screen.h @@ -57,6 +57,8 @@ struct viddef_t size_t rowbytes; // bytes per scanline of the VIDEO mode INT32 width; // PIXELS per scanline INT32 height; + UINT32 realwidth; // real pixel width of window/screen + UINT32 realheight; // real pixel height of window/screen union { // don't need numpages for OpenGL, so we can use it for fullscreen/windowed mode INT32 numpages; // always 1, page flipping todo INT32 windowed; // windowed or fullscren mode? diff --git a/src/sdl/CMakeLists.txt b/src/sdl/CMakeLists.txt index 2994ba2e3..e77b40910 100644 --- a/src/sdl/CMakeLists.txt +++ b/src/sdl/CMakeLists.txt @@ -3,6 +3,8 @@ target_sources(SRB2SDL2 PRIVATE new_sound.cpp ogl_sdl.c + rhi_gl3_core_platform.cpp + rhi_gl3_core_platform.hpp i_threads.c i_net.c i_system.c diff --git a/src/sdl/i_video.cpp b/src/sdl/i_video.cpp index 715c9ebf9..dd5003fba 100644 --- a/src/sdl/i_video.cpp +++ b/src/sdl/i_video.cpp @@ -21,9 +21,16 @@ #include #include +#include #include +#include + +#include "../rhi/rhi.hpp" +#include "../rhi/gl3_core/gl3_core_rhi.hpp" +#include "rhi_gl3_core_platform.hpp" + #ifdef _MSC_VER #pragma warning(disable : 4214 4244) #endif @@ -93,6 +100,8 @@ // maximum number of windowed modes (see windowedModes[][]) #define MAXWINMODES (18) +using namespace srb2; + /** \brief */ static INT32 numVidModes = -1; @@ -104,9 +113,6 @@ static char vidModeName[33][32]; // allow 33 different modes rendermode_t rendermode = render_soft; rendermode_t chosenrendermode = render_none; // set by command line arguments -boolean highcolor = false; - - // synchronize page flipping with screen refresh consvar_t cv_vidwait = CVAR_INIT ("vid_wait", "Off", CV_SAVE, CV_OnOff, NULL); static consvar_t cv_stretch = CVAR_INIT ("stretch", "Off", CV_SAVE|CV_NOSHOWHELP, CV_OnOff, NULL); @@ -134,27 +140,30 @@ static SDL_Surface *vidSurface = NULL; static SDL_Surface *bufSurface = NULL; static SDL_Surface *icoSurface = NULL; static SDL_Color localPalette[256]; -#if 0 -static SDL_Rect **modeList = NULL; -static Uint8 BitsPerPixel = 16; -#endif Uint16 realwidth = BASEVIDWIDTH; Uint16 realheight = BASEVIDHEIGHT; static SDL_bool mousegrabok = SDL_TRUE; static SDL_bool wrapmouseok = SDL_FALSE; -#define HalfWarpMouse(x,y) if (wrapmouseok) SDL_WarpMouseInWindow(window, (Uint16)(x/2),(Uint16)(y/2)) -static SDL_bool videoblitok = SDL_FALSE; static SDL_bool exposevideo = SDL_FALSE; -static SDL_bool usesdl2soft = SDL_FALSE; static SDL_bool borderlesswindow = SDL_FALSE; // SDL2 vars SDL_Window *window; -SDL_Renderer *renderer; -static SDL_Texture *texture; static SDL_bool havefocus = SDL_TRUE; static const char *fallback_resolution_name = "Fallback"; +struct RhiSwState { + rhi::Handle g_sw_palette_pipeline; + rhi::Handle g_sw_screen_texture; + rhi::Handle g_palette_texture; + rhi::Handle g_quad_vb; + rhi::Handle g_quad_ib; +}; + +static std::unique_ptr g_rhi; +static uint32_t g_rhi_generation = 0; +static RhiSwState g_rhi_sw_state; + // windowed video modes from which to choose from. static INT32 windowedModes[MAXWINMODES][2] = { @@ -178,35 +187,14 @@ static INT32 windowedModes[MAXWINMODES][2] = { 320, 200}, // 1.60,1.00 }; -static void Impl_VideoSetupSDLBuffer(void); static void Impl_VideoSetupBuffer(void); static SDL_bool Impl_CreateWindow(SDL_bool fullscreen); //static void Impl_SetWindowName(const char *title); static void Impl_SetWindowIcon(void); -static void Impl_SetSoftwareVsync(int vsync) -{ -#if SDL_VERSION_ATLEAST(2,0,18) - static int oldvsync = 0; - if (oldvsync != vsync) - { - SDL_RenderSetVSync(renderer, vsync); - } - oldvsync = vsync; -#else - (void)vsync; -#endif -} - static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_bool reposition) { static SDL_bool wasfullscreen = SDL_FALSE; - Uint32 rmask; - Uint32 gmask; - Uint32 bmask; - Uint32 amask; - int bpp = 16; - int sw_texture_format = SDL_PIXELFORMAT_ABGR8888; realwidth = vid.width; realheight = vid.height; @@ -247,51 +235,9 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_bool } } -#ifdef HWRENDER - if (rendermode == render_opengl) - { - OglSdlSurface(vid.width, vid.height); - } -#endif - - if (rendermode == render_soft) - { - SDL_RenderClear(renderer); - SDL_RenderSetLogicalSize(renderer, width, height); - // Set up Texture - realwidth = width; - realheight = height; - if (texture != NULL) - { - SDL_DestroyTexture(texture); - } - - if (!usesdl2soft) - { - sw_texture_format = SDL_PIXELFORMAT_RGB565; - } - else - { - bpp = 32; - sw_texture_format = SDL_PIXELFORMAT_RGBA8888; - } - - texture = SDL_CreateTexture(renderer, sw_texture_format, SDL_TEXTUREACCESS_STREAMING, width, height); - - // Set up SW surface - if (vidSurface != NULL) - { - SDL_FreeSurface(vidSurface); - } - if (vid.buffer) - { - free(vid.buffer); - vid.buffer = NULL; - } - SDL_PixelFormatEnumToMasks(sw_texture_format, &bpp, &rmask, &gmask, &bmask, &amask); - vidSurface = SDL_CreateRGBSurface(0, width, height, bpp, rmask, gmask, bmask, amask); - Impl_SetSoftwareVsync(cv_vidwait.value); - } + SDL_GetWindowSize(window, &width, &height); + vid.realwidth = static_cast(width); + vid.realheight = static_cast(height); } static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code) @@ -458,51 +404,8 @@ static void SurfaceInfo(const SDL_Surface *infoSurface, const char *SurfaceText) static void VID_Command_Info_f (void) { -#if 0 - SDL2STUB(); -#else -#if 0 - const SDL_VideoInfo *videoInfo; - videoInfo = SDL_GetVideoInfo(); //Alam: Double-Check - if (videoInfo) - { - CONS_Printf("%s", M_GetText("Video Interface Capabilities:\n")); - if (videoInfo->hw_available) - CONS_Printf("%s", M_GetText(" Hardware surfaces\n")); - if (videoInfo->wm_available) - CONS_Printf("%s", M_GetText(" Window manager\n")); - //UnusedBits1 :6 - //UnusedBits2 :1 - if (videoInfo->blit_hw) - CONS_Printf("%s", M_GetText(" Accelerated blits HW-2-HW\n")); - if (videoInfo->blit_hw_CC) - CONS_Printf("%s", M_GetText(" Accelerated blits HW-2-HW with Colorkey\n")); - if (videoInfo->wm_available) - CONS_Printf("%s", M_GetText(" Accelerated blits HW-2-HW with Alpha\n")); - if (videoInfo->blit_sw) - { - CONS_Printf("%s", M_GetText(" Accelerated blits SW-2-HW\n")); - if (!M_CheckParm("-noblit")) videoblitok = SDL_TRUE; - } - if (videoInfo->blit_sw_CC) - CONS_Printf("%s", M_GetText(" Accelerated blits SW-2-HW with Colorkey\n")); - if (videoInfo->blit_sw_A) - CONS_Printf("%s", M_GetText(" Accelerated blits SW-2-HW with Alpha\n")); - if (videoInfo->blit_fill) - CONS_Printf("%s", M_GetText(" Accelerated Color filling\n")); - //UnusedBits3 :16 - if (videoInfo->video_mem) - CONS_Printf(M_GetText(" There is %i KB of video memory\n"), videoInfo->video_mem); - else - CONS_Printf("%s", M_GetText(" There no video memory for SDL\n")); - //*vfmt - } -#else - if (!M_CheckParm("-noblit")) videoblitok = SDL_TRUE; -#endif SurfaceInfo(bufSurface, M_GetText("Current Engine Mode")); SurfaceInfo(vidSurface, M_GetText("Current Video Mode")); -#endif } static void VID_Command_ModeList_f(void) @@ -875,6 +778,204 @@ static void Impl_HandleControllerButtonEvent(SDL_ControllerButtonEvent evt, Uint } } +static ImGuiKey ImGui_ImplSDL2_KeycodeToImGuiKey(int keycode) +{ + switch (keycode) + { + case SDLK_TAB: return ImGuiKey_Tab; + case SDLK_LEFT: return ImGuiKey_LeftArrow; + case SDLK_RIGHT: return ImGuiKey_RightArrow; + case SDLK_UP: return ImGuiKey_UpArrow; + case SDLK_DOWN: return ImGuiKey_DownArrow; + case SDLK_PAGEUP: return ImGuiKey_PageUp; + case SDLK_PAGEDOWN: return ImGuiKey_PageDown; + case SDLK_HOME: return ImGuiKey_Home; + case SDLK_END: return ImGuiKey_End; + case SDLK_INSERT: return ImGuiKey_Insert; + case SDLK_DELETE: return ImGuiKey_Delete; + case SDLK_BACKSPACE: return ImGuiKey_Backspace; + case SDLK_SPACE: return ImGuiKey_Space; + case SDLK_RETURN: return ImGuiKey_Enter; + case SDLK_ESCAPE: return ImGuiKey_Escape; + case SDLK_QUOTE: return ImGuiKey_Apostrophe; + case SDLK_COMMA: return ImGuiKey_Comma; + case SDLK_MINUS: return ImGuiKey_Minus; + case SDLK_PERIOD: return ImGuiKey_Period; + case SDLK_SLASH: return ImGuiKey_Slash; + case SDLK_SEMICOLON: return ImGuiKey_Semicolon; + case SDLK_EQUALS: return ImGuiKey_Equal; + case SDLK_LEFTBRACKET: return ImGuiKey_LeftBracket; + case SDLK_BACKSLASH: return ImGuiKey_Backslash; + case SDLK_RIGHTBRACKET: return ImGuiKey_RightBracket; + case SDLK_BACKQUOTE: return ImGuiKey_GraveAccent; + case SDLK_CAPSLOCK: return ImGuiKey_CapsLock; + case SDLK_SCROLLLOCK: return ImGuiKey_ScrollLock; + case SDLK_NUMLOCKCLEAR: return ImGuiKey_NumLock; + case SDLK_PRINTSCREEN: return ImGuiKey_PrintScreen; + case SDLK_PAUSE: return ImGuiKey_Pause; + case SDLK_KP_0: return ImGuiKey_Keypad0; + case SDLK_KP_1: return ImGuiKey_Keypad1; + case SDLK_KP_2: return ImGuiKey_Keypad2; + case SDLK_KP_3: return ImGuiKey_Keypad3; + case SDLK_KP_4: return ImGuiKey_Keypad4; + case SDLK_KP_5: return ImGuiKey_Keypad5; + case SDLK_KP_6: return ImGuiKey_Keypad6; + case SDLK_KP_7: return ImGuiKey_Keypad7; + case SDLK_KP_8: return ImGuiKey_Keypad8; + case SDLK_KP_9: return ImGuiKey_Keypad9; + case SDLK_KP_PERIOD: return ImGuiKey_KeypadDecimal; + case SDLK_KP_DIVIDE: return ImGuiKey_KeypadDivide; + case SDLK_KP_MULTIPLY: return ImGuiKey_KeypadMultiply; + case SDLK_KP_MINUS: return ImGuiKey_KeypadSubtract; + case SDLK_KP_PLUS: return ImGuiKey_KeypadAdd; + case SDLK_KP_ENTER: return ImGuiKey_KeypadEnter; + case SDLK_KP_EQUALS: return ImGuiKey_KeypadEqual; + case SDLK_LCTRL: return ImGuiKey_LeftCtrl; + case SDLK_LSHIFT: return ImGuiKey_LeftShift; + case SDLK_LALT: return ImGuiKey_LeftAlt; + case SDLK_LGUI: return ImGuiKey_LeftSuper; + case SDLK_RCTRL: return ImGuiKey_RightCtrl; + case SDLK_RSHIFT: return ImGuiKey_RightShift; + case SDLK_RALT: return ImGuiKey_RightAlt; + case SDLK_RGUI: return ImGuiKey_RightSuper; + case SDLK_APPLICATION: return ImGuiKey_Menu; + case SDLK_0: return ImGuiKey_0; + case SDLK_1: return ImGuiKey_1; + case SDLK_2: return ImGuiKey_2; + case SDLK_3: return ImGuiKey_3; + case SDLK_4: return ImGuiKey_4; + case SDLK_5: return ImGuiKey_5; + case SDLK_6: return ImGuiKey_6; + case SDLK_7: return ImGuiKey_7; + case SDLK_8: return ImGuiKey_8; + case SDLK_9: return ImGuiKey_9; + case SDLK_a: return ImGuiKey_A; + case SDLK_b: return ImGuiKey_B; + case SDLK_c: return ImGuiKey_C; + case SDLK_d: return ImGuiKey_D; + case SDLK_e: return ImGuiKey_E; + case SDLK_f: return ImGuiKey_F; + case SDLK_g: return ImGuiKey_G; + case SDLK_h: return ImGuiKey_H; + case SDLK_i: return ImGuiKey_I; + case SDLK_j: return ImGuiKey_J; + case SDLK_k: return ImGuiKey_K; + case SDLK_l: return ImGuiKey_L; + case SDLK_m: return ImGuiKey_M; + case SDLK_n: return ImGuiKey_N; + case SDLK_o: return ImGuiKey_O; + case SDLK_p: return ImGuiKey_P; + case SDLK_q: return ImGuiKey_Q; + case SDLK_r: return ImGuiKey_R; + case SDLK_s: return ImGuiKey_S; + case SDLK_t: return ImGuiKey_T; + case SDLK_u: return ImGuiKey_U; + case SDLK_v: return ImGuiKey_V; + case SDLK_w: return ImGuiKey_W; + case SDLK_x: return ImGuiKey_X; + case SDLK_y: return ImGuiKey_Y; + case SDLK_z: return ImGuiKey_Z; + case SDLK_F1: return ImGuiKey_F1; + case SDLK_F2: return ImGuiKey_F2; + case SDLK_F3: return ImGuiKey_F3; + case SDLK_F4: return ImGuiKey_F4; + case SDLK_F5: return ImGuiKey_F5; + case SDLK_F6: return ImGuiKey_F6; + case SDLK_F7: return ImGuiKey_F7; + case SDLK_F8: return ImGuiKey_F8; + case SDLK_F9: return ImGuiKey_F9; + case SDLK_F10: return ImGuiKey_F10; + case SDLK_F11: return ImGuiKey_F11; + case SDLK_F12: return ImGuiKey_F12; + } + return ImGuiKey_None; +} + +static void ImGui_ImplSDL2_UpdateKeyModifiers(SDL_Keymod sdl_key_mods) +{ + ImGuiIO& io = ImGui::GetIO(); + io.AddKeyEvent(ImGuiMod_Ctrl, (sdl_key_mods & KMOD_CTRL) != 0); + io.AddKeyEvent(ImGuiMod_Shift, (sdl_key_mods & KMOD_SHIFT) != 0); + io.AddKeyEvent(ImGuiMod_Alt, (sdl_key_mods & KMOD_ALT) != 0); + io.AddKeyEvent(ImGuiMod_Super, (sdl_key_mods & KMOD_GUI) != 0); +} + +// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. +// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. +// If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field. +bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) +{ + ImGuiIO& io = ImGui::GetIO(); + + switch (event->type) + { + case SDL_MOUSEMOTION: + { + io.AddMousePosEvent((float)event->motion.x, (float)event->motion.y); + return true; + } + case SDL_MOUSEWHEEL: + { + float wheel_x = (event->wheel.x > 0) ? 1.0f : (event->wheel.x < 0) ? -1.0f : 0.0f; + float wheel_y = (event->wheel.y > 0) ? 1.0f : (event->wheel.y < 0) ? -1.0f : 0.0f; + io.AddMouseWheelEvent(wheel_x, wheel_y); + return true; + } + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + { + int mouse_button = -1; + if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; } + if (event->button.button == SDL_BUTTON_RIGHT) { mouse_button = 1; } + if (event->button.button == SDL_BUTTON_MIDDLE) { mouse_button = 2; } + if (event->button.button == SDL_BUTTON_X1) { mouse_button = 3; } + if (event->button.button == SDL_BUTTON_X2) { mouse_button = 4; } + if (mouse_button == -1) + break; + io.AddMouseButtonEvent(mouse_button, (event->type == SDL_MOUSEBUTTONDOWN)); + // bd->MouseButtonsDown = (event->type == SDL_MOUSEBUTTONDOWN) ? (bd->MouseButtonsDown | (1 << mouse_button)) : (bd->MouseButtonsDown & ~(1 << mouse_button)); + return true; + } + case SDL_TEXTINPUT: + { + io.AddInputCharactersUTF8(event->text.text); + return true; + } + case SDL_KEYDOWN: + case SDL_KEYUP: + { + ImGui_ImplSDL2_UpdateKeyModifiers((SDL_Keymod)event->key.keysym.mod); + ImGuiKey key = ImGui_ImplSDL2_KeycodeToImGuiKey(event->key.keysym.sym); + io.AddKeyEvent(key, (event->type == SDL_KEYDOWN)); + io.SetKeyEventNativeData(key, event->key.keysym.sym, event->key.keysym.scancode, event->key.keysym.scancode); // To support legacy indexing (<1.87 user code). Legacy backend uses SDLK_*** as indices to IsKeyXXX() functions. + return true; + } + case SDL_WINDOWEVENT: + { + // - When capturing mouse, SDL will send a bunch of conflicting LEAVE/ENTER event on every mouse move, but the final ENTER tends to be right. + // - However we won't get a correct LEAVE event for a captured window. + // - In some cases, when detaching a window from main viewport SDL may send SDL_WINDOWEVENT_ENTER one frame too late, + // causing SDL_WINDOWEVENT_LEAVE on previous frame to interrupt drag operation by clear mouse position. This is why + // we delay process the SDL_WINDOWEVENT_LEAVE events by one frame. See issue #5012 for details. + Uint8 window_event = event->window.event; + if (window_event == SDL_WINDOWEVENT_ENTER) + (void)0; + // bd->PendingMouseLeaveFrame = 0; + if (window_event == SDL_WINDOWEVENT_LEAVE) + (void)0; + // bd->PendingMouseLeaveFrame = ImGui::GetFrameCount() + 1; + if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED) + io.AddFocusEvent(true); + else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST) + io.AddFocusEvent(false); + return true; + } + } + return false; +} + void I_GetEvent(void) { SDL_Event evt; @@ -892,8 +993,16 @@ void I_GetEvent(void) mousemovex = mousemovey = 0; + ImGuiIO& io = ImGui::GetIO(); + while (SDL_PollEvent(&evt)) { + ImGui_ImplSDL2_ProcessEvent(&evt); + if (io.WantCaptureMouse || io.WantCaptureKeyboard) + { + continue; + } + switch (evt.type) { case SDL_WINDOWEVENT: @@ -1093,6 +1202,13 @@ void I_GetEvent(void) } } +static void half_warp_mouse(uint16_t x, uint16_t y) { + if (wrapmouseok) + { + SDL_WarpMouseInWindow(window, (Uint16)(x/2),(Uint16)(y/2)); + } +} + void I_StartupMouse(void) { static SDL_bool firsttimeonmouse = SDL_TRUE; @@ -1102,7 +1218,7 @@ void I_StartupMouse(void) if (!firsttimeonmouse) { - HalfWarpMouse(realwidth, realheight); // warp to center + half_warp_mouse(realwidth, realheight); // warp to center } else firsttimeonmouse = SDL_FALSE; @@ -1149,145 +1265,15 @@ void I_UpdateNoBlit(void) return; if (exposevideo) { -#ifdef HWRENDER - if (rendermode == render_opengl) - { - OglSdlFinishUpdate(cv_vidwait.value); - } - else -#endif - if (rendermode == render_soft) - { - SDL_RenderCopy(renderer, texture, NULL, NULL); - SDL_RenderPresent(renderer); - } } exposevideo = SDL_FALSE; } -// I_SkipFrame -// -// Returns true if it thinks we can afford to skip this frame -// from PrBoom's src/SDL/i_video.c -static inline boolean I_SkipFrame(void) -{ -#if 1 - // While I fixed the FPS counter bugging out with this, - // I actually really like being able to pause and - // use perfstats to measure rendering performance - // without game logic changes. - return false; -#else - static boolean skip = false; - - skip = !skip; - - switch (gamestate) - { - case GS_LEVEL: - if (!paused) - return false; - /* FALLTHRU */ - case GS_WAITINGPLAYERS: - return skip; // Skip odd frames - default: - return false; - } -#endif -} - // // I_FinishUpdate // static SDL_Rect src_rect = { 0, 0, 0, 0 }; -void I_FinishUpdate(void) -{ - int player; - - if (rendermode == render_none) - return; //Alam: No software or OpenGl surface - - SCR_CalculateFPS(); - - if (I_SkipFrame()) - return; - - if (st_overlay) - { - if (cv_ticrate.value) - SCR_DisplayTicRate(); - - if (cv_showping.value && netgame && - ( consoleplayer != serverplayer || ! server_lagless )) - { - if (server_lagless) - { - if (consoleplayer != serverplayer) - SCR_DisplayLocalPing(); - } - else - { - for ( - player = 1; - player < MAXPLAYERS; - player++ - ){ - if (D_IsPlayerHumanAndGaming(player)) - { - SCR_DisplayLocalPing(); - break; - } - } - } - } - if (cv_mindelay.value && consoleplayer == serverplayer && Playing()) - SCR_DisplayLocalPing(); - } - - if (marathonmode) - SCR_DisplayMarathonInfo(); - - // draw captions if enabled - if (cv_closedcaptioning.value) - SCR_ClosedCaptions(); - -#ifdef HAVE_DISCORDRPC - if (discordRequestList != NULL) - ST_AskToJoinEnvelope(); -#endif - - if (rendermode == render_soft && screens[0]) - { - if (!bufSurface) //Double-Check - { - Impl_VideoSetupSDLBuffer(); - } - - if (bufSurface) - { - SDL_BlitSurface(bufSurface, &src_rect, vidSurface, &src_rect); - // Fury -- there's no way around UpdateTexture, the GL backend uses it anyway - SDL_LockSurface(vidSurface); - SDL_UpdateTexture(texture, &src_rect, vidSurface->pixels, vidSurface->pitch); - SDL_UnlockSurface(vidSurface); - } - - SDL_RenderClear(renderer); - SDL_RenderCopy(renderer, texture, &src_rect, NULL); - SDL_RenderPresent(renderer); - Impl_SetSoftwareVsync(cv_vidwait.value); - } -#ifdef HWRENDER - else if (rendermode == render_opengl) - { - OglSdlFinishUpdate(cv_vidwait.value); - } -#endif - - exposevideo = SDL_FALSE; -} - // // I_UpdateNoVsync // @@ -1324,9 +1310,6 @@ void I_SetPalette(RGBA_t *palette) localPalette[i].g = palette[i].s.green; localPalette[i].b = palette[i].s.blue; } - //if (vidSurface) SDL_SetPaletteColors(vidSurface->format->palette, localPalette, 0, 256); - // Fury -- SDL2 vidSurface is a 32-bit surface buffer copied to the texture. It's not palletized, like bufSurface. - if (bufSurface) SDL_SetPaletteColors(bufSurface->format->palette, localPalette, 0, 256); } // return number of fullscreen + X11 modes @@ -1480,44 +1463,40 @@ void VID_PrepareModeList(void) static SDL_bool Impl_CreateContext(void) { - // Renderer-specific stuff -#ifdef HWRENDER - if ((rendermode == render_opengl) - && (vid.glstate != VID_GL_LIBRARY_ERROR)) + // RHI always uses OpenGL 3.2 Core (for now) + if (!sdlglcontext) { - if (!sdlglcontext) - sdlglcontext = SDL_GL_CreateContext(window); - if (sdlglcontext == NULL) - { - SDL_DestroyWindow(window); - I_Error("Failed to create a GL context: %s\n", SDL_GetError()); - } - SDL_GL_MakeCurrent(window, sdlglcontext); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); + sdlglcontext = SDL_GL_CreateContext(window); } - else -#endif - if (rendermode == render_soft) + if (sdlglcontext == NULL) { - int flags = 0; // Use this to set SDL_RENDERER_* flags now - if (usesdl2soft) - flags |= SDL_RENDERER_SOFTWARE; - - // 3 August 2022 - // Possibly a Windows 11 issue; the default - // "direct3d" driver (D3D9) causes Drmingw exchndl - // to not write RPT files. Every other driver - // seems fine. - SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"); - - if (!renderer) - renderer = SDL_CreateRenderer(window, -1, flags); - if (renderer == NULL) - { - CONS_Printf(M_GetText("Couldn't create rendering context: %s\n"), SDL_GetError()); - return SDL_FALSE; - } - SDL_RenderSetLogicalSize(renderer, BASEVIDWIDTH, BASEVIDHEIGHT); + SDL_DestroyWindow(window); + I_Error("Failed to create a GL context: %s\n", SDL_GetError()); } + SDL_GL_MakeCurrent(window, sdlglcontext); + + std::unique_ptr platform = std::make_unique(); + platform->window = window; + g_rhi = std::make_unique(std::move(platform), reinterpret_cast(SDL_GL_GetProcAddress)); + g_rhi_generation += 1; + + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); (void)io; + io.IniFilename = NULL; + io.BackendFlags = 0; + io.BackendRendererName = "SRB2 SDL 2 RHI"; + io.Fonts->AddFontDefault(); + { + unsigned char* pixels; + int width; + int height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + } + ImGui::StyleColorsDark(); + return SDL_TRUE; } @@ -1544,9 +1523,6 @@ boolean VID_CheckRenderer(void) { boolean rendererchanged = false; boolean contextcreated = false; -#ifdef HWRENDER - rendermode_t oldrenderer = rendermode; -#endif if (dedicated) return false; @@ -1556,46 +1532,6 @@ boolean VID_CheckRenderer(void) rendermode = static_cast(setrenderneeded); rendererchanged = true; -#ifdef HWRENDER - if (rendermode == render_opengl) - { - VID_CheckGLLoaded(oldrenderer); - - // Initialise OpenGL before calling SDLSetMode!!! - // This is because SDLSetMode calls OglSdlSurface. - if (vid.glstate == VID_GL_LIBRARY_NOTLOADED) - { - VID_StartupOpenGL(); - - // Loaded successfully! - if (vid.glstate == VID_GL_LIBRARY_LOADED) - { - // Destroy the current window, if it exists. - if (window) - { - SDL_DestroyWindow(window); - window = NULL; - } - - // Destroy the current window rendering context, if that also exists. - if (renderer) - { - SDL_DestroyRenderer(renderer); - renderer = NULL; - } - - // Create a new window. - Impl_CreateWindow(static_cast(USE_FULLSCREEN)); - - // From there, the OpenGL context was already created. - contextcreated = true; - } - } - else if (vid.glstate == VID_GL_LIBRARY_ERROR) - rendererchanged = false; - } -#endif - if (!contextcreated) Impl_CreateContext(); @@ -1607,21 +1543,8 @@ boolean VID_CheckRenderer(void) if (rendermode == render_soft) { - if (bufSurface) - { - SDL_FreeSurface(bufSurface); - bufSurface = NULL; - } - SCR_SetDrawFuncs(); } -#ifdef HWRENDER - else if (rendermode == render_opengl && rendererchanged) - { - HWR_Switch(); - V_SetPalette(0); - } -#endif return rendererchanged; } @@ -1661,6 +1584,8 @@ INT32 VID_SetMode(INT32 modeNum) vid.width = windowedModes[modeNum][0]; vid.height = windowedModes[modeNum][1]; + vid.realwidth = vid.width; + vid.realheight = vid.height; vid.modenum = modeNum; src_rect.w = vid.width; @@ -1668,7 +1593,6 @@ INT32 VID_SetMode(INT32 modeNum) refresh_rate = VID_GetRefreshRate(); - //Impl_SetWindowName("Dr. Robotnik's Ring Racers "VERSIONSTRING); VID_CheckRenderer(); return SDL_TRUE; } @@ -1689,16 +1613,13 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) if (borderlesswindow) flags |= SDL_WINDOW_BORDERLESS; -#ifdef HWRENDER - if (vid.glstate == VID_GL_LIBRARY_LOADED) - flags |= SDL_WINDOW_OPENGL; -#endif + // RHI: always create window as OPENGL + flags |= SDL_WINDOW_OPENGL; // Create a window window = SDL_CreateWindow("Dr. Robotnik's Ring Racers " VERSIONSTRING, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, realwidth, realheight, flags); - if (window == NULL) { CONS_Printf(M_GetText("Couldn't create window: %s\n"), SDL_GetError()); @@ -1710,51 +1631,12 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) return Impl_CreateContext(); } -/* -static void Impl_SetWindowName(const char *title) -{ - if (window == NULL) - { - return; - } - SDL_SetWindowTitle(window, title); -} -*/ - static void Impl_SetWindowIcon(void) { if (window && icoSurface) SDL_SetWindowIcon(window, icoSurface); } -static void Impl_VideoSetupSDLBuffer(void) -{ - if (bufSurface != NULL) - { - SDL_FreeSurface(bufSurface); - bufSurface = NULL; - } - // Set up the SDL palletized buffer (copied to vidbuffer before being rendered to texture) - if (vid.bpp == 1) - { - bufSurface = SDL_CreateRGBSurfaceFrom(screens[0],vid.width,vid.height,8, - (int)vid.rowbytes,0x00000000,0x00000000,0x00000000,0x00000000); // 256 mode - } - else if (vid.bpp == 2) // Fury -- don't think this is used at all anymore - { - bufSurface = SDL_CreateRGBSurfaceFrom(screens[0],vid.width,vid.height,15, - (int)vid.rowbytes,0x00007C00,0x000003E0,0x0000001F,0x00000000); // 555 mode - } - if (bufSurface) - { - SDL_SetPaletteColors(bufSurface->format->palette, localPalette, 0, 256); - } - else - { - I_Error("%s", M_GetText("No system memory for SDL buffer surface\n")); - } -} - static void Impl_VideoSetupBuffer(void) { // Set up game's software render buffer @@ -1791,87 +1673,14 @@ void I_StartupGraphics(void) keyboard_started = true; -#if !defined(HAVE_TTF) - // Previously audio was init here for questionable reasons? - if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) - { - CONS_Printf(M_GetText("Couldn't initialize SDL's Video System: %s\n"), SDL_GetError()); - return; - } -#endif - { - const char *vd = SDL_GetCurrentVideoDriver(); - //CONS_Printf(M_GetText("Starting up with video driver: %s\n"), vd); - if (vd && ( - strncasecmp(vd, "gcvideo", 8) == 0 || - strncasecmp(vd, "fbcon", 6) == 0 || - strncasecmp(vd, "wii", 4) == 0 || - strncasecmp(vd, "psl1ght", 8) == 0 - )) - framebuffer = SDL_TRUE; - } + // TEMPORARY OVERRIDES FOR RHI - SOFTWARE ONLY + chosenrendermode = render_soft; + rendermode = render_soft; - // Renderer choices - // Takes priority over the config. - if (M_CheckParm("-renderer")) - { - INT32 i = 0; - CV_PossibleValue_t *renderer_list = cv_renderer_t; - const char *modeparm = M_GetNextParm(); - while (renderer_list[i].strvalue) - { - if (!stricmp(modeparm, renderer_list[i].strvalue)) - { - chosenrendermode = static_cast(renderer_list[i].value); - break; - } - i++; - } - } - - // Choose Software renderer - else if (M_CheckParm("-software")) - chosenrendermode = render_soft; - -#ifdef HWRENDER - // Choose OpenGL renderer - else if (M_CheckParm("-opengl")) - chosenrendermode = render_opengl; - - // Don't startup OpenGL - if (M_CheckParm("-nogl")) - { - vid.glstate = VID_GL_LIBRARY_ERROR; - if (chosenrendermode == render_opengl) - chosenrendermode = render_none; - } -#endif - - if (chosenrendermode != render_none) - rendermode = chosenrendermode; - - usesdl2soft = M_CheckParm("-softblit") ? SDL_TRUE : SDL_FALSE; borderlesswindow = M_CheckParm("-borderless") ? SDL_TRUE : SDL_FALSE; - //SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY>>1,SDL_DEFAULT_REPEAT_INTERVAL<<2); VID_Command_ModeList_f(); -#ifdef HWRENDER - if (rendermode == render_opengl) - VID_StartupOpenGL(); -#endif - - // Window icon -#ifdef HAVE_IMAGE - icoSurface = IMG_ReadXPMFromArray(SDL_icon_xpm); -#endif - - // Fury: we do window initialization after GL setup to allow - // SDL_GL_LoadLibrary to work well on Windows - - // Create window - //Impl_CreateWindow(USE_FULLSCREEN); - //Impl_SetWindowName("Dr. Robotnik's Ring Racers "VERSIONSTRING); VID_SetMode(VID_GetModeForSize(BASEVIDWIDTH, BASEVIDHEIGHT)); vid.width = BASEVIDWIDTH; // Default size for startup @@ -1881,24 +1690,10 @@ void I_StartupGraphics(void) vid.bpp = 1; // This is the game engine's Bpp vid.WndParent = NULL; //For the window? -#ifdef HAVE_TTF - I_ShutdownTTF(); -#endif - VID_SetMode(VID_GetModeForSize(BASEVIDWIDTH, BASEVIDHEIGHT)); if (M_CheckParm("-nomousegrab")) mousegrabok = SDL_FALSE; -#if 0 // defined (_DEBUG) - else - { - char videodriver[4] = {'S','D','L',0}; - if (!M_CheckParm("-mousegrab") && - *strncpy(videodriver, SDL_GetCurrentVideoDriver(), 4) != '\0' && - strncasecmp("x11",videodriver,4) == 0) - mousegrabok = SDL_FALSE; //X11's XGrabPointer not good - } -#endif realwidth = (Uint16)vid.width; realheight = (Uint16)vid.height; @@ -1915,100 +1710,36 @@ void I_StartupGraphics(void) void VID_StartupOpenGL(void) { -#ifdef HWRENDER - static boolean glstartup = false; - if (!glstartup) - { - CONS_Printf("VID_StartupOpenGL()...\n"); - *(void**)&HWD.pfnInit = hwSym("Init",NULL); - *(void**)&HWD.pfnFinishUpdate = NULL; - *(void**)&HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL); - *(void**)&HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL); - *(void**)&HWD.pfnDrawIndexedTriangles = hwSym("DrawIndexedTriangles",NULL); - *(void**)&HWD.pfnRenderSkyDome = hwSym("RenderSkyDome",NULL); - *(void**)&HWD.pfnSetBlend = hwSym("SetBlend",NULL); - *(void**)&HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); - *(void**)&HWD.pfnSetTexture = hwSym("SetTexture",NULL); - *(void**)&HWD.pfnUpdateTexture = hwSym("UpdateTexture",NULL); - *(void**)&HWD.pfnDeleteTexture = hwSym("DeleteTexture",NULL); - *(void**)&HWD.pfnReadRect = hwSym("ReadRect",NULL); - *(void**)&HWD.pfnGClipRect = hwSym("GClipRect",NULL); - *(void**)&HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); - *(void**)&HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL); - *(void**)&HWD.pfnSetPalette = hwSym("SetPalette",NULL); - *(void**)&HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL); - *(void**)&HWD.pfnDrawModel = hwSym("DrawModel",NULL); - *(void**)&HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL); - *(void**)&HWD.pfnSetTransform = hwSym("SetTransform",NULL); - *(void**)&HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); - *(void**)&HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL); - *(void**)&HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL); - *(void**)&HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL); - *(void**)&HWD.pfnDoScreenWipe = hwSym("DoScreenWipe",NULL); - *(void**)&HWD.pfnDrawIntermissionBG=hwSym("DrawIntermissionBG",NULL); - *(void**)&HWD.pfnMakeScreenTexture= hwSym("MakeScreenTexture",NULL); - *(void**)&HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL); - *(void**)&HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL); - - *(void**)&HWD.pfnCompileShaders = hwSym("CompileShaders",NULL); - *(void**)&HWD.pfnCleanShaders = hwSym("CleanShaders",NULL); - *(void**)&HWD.pfnSetShader = hwSym("SetShader",NULL); - *(void**)&HWD.pfnUnSetShader = hwSym("UnSetShader",NULL); - - *(void**)&HWD.pfnSetShaderInfo = hwSym("SetShaderInfo",NULL); - *(void**)&HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL); - - vid.glstate = HWD.pfnInit() ? VID_GL_LIBRARY_LOADED : VID_GL_LIBRARY_ERROR; // let load the OpenGL library - - if (vid.glstate == VID_GL_LIBRARY_ERROR) - { - rendermode = render_soft; - setrenderneeded = 0; - } - glstartup = true; - } -#endif + CONS_Alert(CONS_WARNING, "VID_StartupOpenGL called (no longer going to use)"); + rendermode = render_soft; + setrenderneeded = 0; } void I_ShutdownGraphics(void) { - const rendermode_t oldrendermode = rendermode; - rendermode = render_none; if (icoSurface) SDL_FreeSurface(icoSurface); icoSurface = NULL; - if (oldrendermode == render_soft) - { - if (vidSurface) SDL_FreeSurface(vidSurface); - vidSurface = NULL; - if (vid.buffer) free(vid.buffer); - vid.buffer = NULL; - if (bufSurface) SDL_FreeSurface(bufSurface); - bufSurface = NULL; - } I_OutputMsg("I_ShutdownGraphics(): "); // was graphics initialized anyway? if (!graphics_started) { - I_OutputMsg("graphics never started\n"); return; } graphics_started = false; - I_OutputMsg("shut down\n"); -#ifdef HWRENDER - if (GLUhandle) - hwClose(GLUhandle); - if (sdlglcontext) - { - SDL_GL_DeleteContext(sdlglcontext); - } -#endif SDL_QuitSubSystem(SDL_INIT_VIDEO); framebuffer = SDL_FALSE; } + +rhi::Rhi* srb2::sys::get_rhi(rhi::Handle handle) +{ + // TODO actually use handle... + return g_rhi.get(); +} + #endif UINT32 I_GetRefreshRate(void) diff --git a/src/sdl/new_sound.cpp b/src/sdl/new_sound.cpp index 1a2d25b1c..5a3dc824d 100644 --- a/src/sdl/new_sound.cpp +++ b/src/sdl/new_sound.cpp @@ -359,7 +359,8 @@ void I_InitMusic(void) SdlAudioLockHandle _; - *music_player = audio::MusicPlayer(); + if (music_player != nullptr) + *music_player = audio::MusicPlayer(); } void I_ShutdownMusic(void) diff --git a/src/sdl/ogl_sdl.h b/src/sdl/ogl_sdl.h index 00697074a..8b60b6242 100644 --- a/src/sdl/ogl_sdl.h +++ b/src/sdl/ogl_sdl.h @@ -32,7 +32,6 @@ boolean OglSdlSurface(INT32 w, INT32 h); void OglSdlFinishUpdate(boolean vidwait); -extern SDL_Renderer *renderer; extern SDL_GLContext sdlglcontext; extern Uint16 realwidth; extern Uint16 realheight; diff --git a/src/sdl/rhi_gl3_core_platform.cpp b/src/sdl/rhi_gl3_core_platform.cpp new file mode 100644 index 000000000..e6971873d --- /dev/null +++ b/src/sdl/rhi_gl3_core_platform.cpp @@ -0,0 +1,56 @@ +#include "rhi_gl3_core_platform.hpp" + +#include + +#include "../cxxutil.hpp" +#include "../w_wad.h" +#include "../z_zone.h" + +using namespace srb2; +using namespace srb2::rhi; + +SdlGlCorePlatform::~SdlGlCorePlatform() = default; + +void SdlGlCorePlatform::present() { + SRB2_ASSERT(window != nullptr); + SRB2_ASSERT(SDL_GetWindowID(window) != 0); + + SDL_GL_SwapWindow(window); +} + +std::tuple SdlGlCorePlatform::find_shader_sources(rhi::PipelineProgram program) { + const char* vertex_lump_name = nullptr; + const char* fragment_lump_name = nullptr; + switch (program) { + case rhi::PipelineProgram::kUnshaded: + vertex_lump_name = "rhi_glcore_vertex_unshaded"; + fragment_lump_name = "rhi_glcore_fragment_unshaded"; + break; + case rhi::PipelineProgram::kUnshadedPaletted: + vertex_lump_name = "rhi_glcore_vertex_unshadedpaletted"; + fragment_lump_name = "rhi_glcore_fragment_unshadedpaletted"; + break; + default: + std::terminate(); + } + + lumpnum_t vertex_lump_num = W_GetNumForLongName(vertex_lump_name); + lumpnum_t fragment_lump_num = W_GetNumForLongName(fragment_lump_name); + size_t vertex_lump_length = W_LumpLength(vertex_lump_num); + size_t fragment_lump_length = W_LumpLength(fragment_lump_num); + void* vertex_lump = W_CacheLumpNum(vertex_lump_num, PU_CACHE); + void* fragment_lump = W_CacheLumpNum(fragment_lump_num, PU_CACHE); + + std::string vertex_shader(static_cast(vertex_lump), vertex_lump_length); + std::string fragment_shader(static_cast(fragment_lump), fragment_lump_length); + + return std::make_tuple(std::move(vertex_shader), std::move(fragment_shader)); +} + +rhi::Rect SdlGlCorePlatform::get_default_framebuffer_dimensions() { + SRB2_ASSERT(window != nullptr); + int w; + int h; + SDL_GL_GetDrawableSize(window, &w, &h); + return {0, 0, static_cast(w), static_cast(h)}; +} diff --git a/src/sdl/rhi_gl3_core_platform.hpp b/src/sdl/rhi_gl3_core_platform.hpp new file mode 100644 index 000000000..0683a428b --- /dev/null +++ b/src/sdl/rhi_gl3_core_platform.hpp @@ -0,0 +1,23 @@ +#ifndef __SRB2_SDL_RHI_GLES2_PLATFORM_HPP__ +#define __SRB2_SDL_RHI_GLES2_PLATFORM_HPP__ + +#include "../rhi/rhi.hpp" +#include "../rhi/gl3_core/gl3_core_rhi.hpp" + +#include + +namespace srb2::rhi { + +struct SdlGlCorePlatform final : public GlCorePlatform { + SDL_Window* window = nullptr; + + virtual ~SdlGlCorePlatform(); + + virtual void present() override; + virtual std::tuple find_shader_sources(PipelineProgram program) override; + virtual Rect get_default_framebuffer_dimensions() override; +}; + +} // namespace srb2::rhi + +#endif // __SRB2_SDL_RHI_GLES2_PLATFORM_HPP__ diff --git a/src/sdl/rhi_gles2_platform.cpp b/src/sdl/rhi_gles2_platform.cpp new file mode 100644 index 000000000..d9d8546e5 --- /dev/null +++ b/src/sdl/rhi_gles2_platform.cpp @@ -0,0 +1,56 @@ +#include "rhi_gles2_platform.hpp" + +#include + +#include "../cxxutil.hpp" +#include "../w_wad.h" +#include "../z_zone.h" + +using namespace srb2; +using namespace srb2::rhi; + +SdlGles2Platform::~SdlGles2Platform() = default; + +void SdlGles2Platform::present() { + SRB2_ASSERT(window != nullptr); + SRB2_ASSERT(SDL_GetWindowID(window) != 0); + + SDL_GL_SwapWindow(window); +} + +std::tuple SdlGles2Platform::find_shader_sources(rhi::PipelineProgram program) { + const char* vertex_lump_name = nullptr; + const char* fragment_lump_name = nullptr; + switch (program) { + case rhi::PipelineProgram::kUnshaded: + vertex_lump_name = "rhi_glsles_vertex_unshaded"; + fragment_lump_name = "rhi_glsles_fragment_unshaded"; + break; + case rhi::PipelineProgram::kUnshadedPaletted: + vertex_lump_name = "rhi_glsles_vertex_unshadedpaletted"; + fragment_lump_name = "rhi_glsles_fragment_unshadedpaletted"; + break; + default: + std::terminate(); + } + + lumpnum_t vertex_lump_num = W_GetNumForLongName(vertex_lump_name); + lumpnum_t fragment_lump_num = W_GetNumForLongName(fragment_lump_name); + size_t vertex_lump_length = W_LumpLength(vertex_lump_num); + size_t fragment_lump_length = W_LumpLength(fragment_lump_num); + void* vertex_lump = W_CacheLumpNum(vertex_lump_num, PU_CACHE); + void* fragment_lump = W_CacheLumpNum(fragment_lump_num, PU_CACHE); + + std::string vertex_shader(static_cast(vertex_lump), vertex_lump_length); + std::string fragment_shader(static_cast(fragment_lump), fragment_lump_length); + + return std::make_tuple(std::move(vertex_shader), std::move(fragment_shader)); +} + +rhi::Rect SdlGles2Platform::get_default_framebuffer_dimensions() { + SRB2_ASSERT(window != nullptr); + int w; + int h; + SDL_GL_GetDrawableSize(window, &w, &h); + return {0, 0, static_cast(w), static_cast(h)}; +} diff --git a/src/sdl/rhi_gles2_platform.hpp b/src/sdl/rhi_gles2_platform.hpp new file mode 100644 index 000000000..0476931d0 --- /dev/null +++ b/src/sdl/rhi_gles2_platform.hpp @@ -0,0 +1,23 @@ +#ifndef __SRB2_SDL_RHI_GLES2_PLATFORM_HPP__ +#define __SRB2_SDL_RHI_GLES2_PLATFORM_HPP__ + +#include "../rhi/rhi.hpp" +#include "../rhi/gles2/gles2_rhi.hpp" + +#include + +namespace srb2::rhi { + +struct SdlGles2Platform final : public Gles2Platform { + SDL_Window* window = nullptr; + + virtual ~SdlGles2Platform(); + + virtual void present() override; + virtual std::tuple find_shader_sources(PipelineProgram program) override; + virtual Rect get_default_framebuffer_dimensions() override; +}; + +} // namespace srb2::rhi + +#endif // __SRB2_SDL_RHI_GLES2_PLATFORM_HPP__ diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index 86a090b07..cb6c7bc4e 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -20,6 +20,9 @@ endif() include("cpm-rapidjson.cmake") include("cpm-discordrpc.cmake") include("cpm-xmp-lite.cmake") +include("cpm-fmt.cmake") +include("cpm-imgui.cmake") add_subdirectory(tcbrindle_span) add_subdirectory(stb_vorbis) +add_subdirectory(glad) diff --git a/thirdparty/cpm-fmt.cmake b/thirdparty/cpm-fmt.cmake new file mode 100644 index 000000000..888d105b5 --- /dev/null +++ b/thirdparty/cpm-fmt.cmake @@ -0,0 +1,6 @@ +CPMAddPackage( + NAME fmt + VERSION 9.1.0 + URL "https://github.com/fmtlib/fmt/releases/download/9.1.0/fmt-9.1.0.zip" + EXCLUDE_FROM_ALL ON +) diff --git a/thirdparty/cpm-imgui.cmake b/thirdparty/cpm-imgui.cmake new file mode 100644 index 000000000..d4cffc7d3 --- /dev/null +++ b/thirdparty/cpm-imgui.cmake @@ -0,0 +1,34 @@ +CPMAddPackage( + NAME imgui + VERSION 1.89.2 + URL "https://github.com/ocornut/imgui/archive/refs/tags/v1.89.2.zip" + EXCLUDE_FROM_ALL ON +) +if(imgui_ADDED) + set(imgui_SOURCES + imgui.cpp + imgui.h + imgui_demo.cpp + imgui_draw.cpp + imgui_internal.h + imgui_tables.cpp + imgui_widgets.cpp + imstb_rectpack.h + imstb_textedit.h + imstb_truetype.h + ) + list(TRANSFORM imgui_SOURCES PREPEND "${imgui_SOURCE_DIR}/") + + add_custom_command( + OUTPUT "${imgui_BINARY_DIR}/include/imgui.h" "${imgui_BINARY_DIR}/include/imconfig.h" + COMMAND ${CMAKE_COMMAND} -E copy "${imgui_SOURCE_DIR}/imgui.h" "${imgui_SOURCE_DIR}/imconfig.h" "${imgui_BINARY_DIR}/include" + DEPENDS "${imgui_SOURCE_DIR}/imgui.h" "${imgui_SOURCE_DIR}/imconfig.h" + VERBATIM + ) + list(APPEND imgui_SOURCES "${imgui_BINARY_DIR}/include/imgui.h" "${imgui_BINARY_DIR}/include/imconfig.h" "${CMAKE_CURRENT_SOURCE_DIR}/imgui_config/srb2_imconfig.h") + add_library(imgui STATIC ${imgui_SOURCES}) + target_include_directories(imgui PUBLIC "${imgui_BINARY_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/imgui_config") + target_compile_definitions(imgui PUBLIC IMGUI_USER_CONFIG="srb2_imconfig.h") + target_compile_features(imgui PUBLIC cxx_std_11) + add_library(imgui::imgui ALIAS imgui) +endif() diff --git a/thirdparty/glad/CMakeLists.txt b/thirdparty/glad/CMakeLists.txt new file mode 100644 index 000000000..7100a98cb --- /dev/null +++ b/thirdparty/glad/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(glad STATIC src/gles2.c src/gl.c include/glad/gles2.h include/glad/gl.h include/KHR/khrplatform.h) +add_library(glad::glad ALIAS glad) +target_include_directories(glad PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") diff --git a/thirdparty/glad/include/KHR/khrplatform.h b/thirdparty/glad/include/KHR/khrplatform.h new file mode 100644 index 000000000..01646449c --- /dev/null +++ b/thirdparty/glad/include/KHR/khrplatform.h @@ -0,0 +1,311 @@ +#ifndef __khrplatform_h_ +#define __khrplatform_h_ + +/* +** Copyright (c) 2008-2018 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +/* Khronos platform-specific types and definitions. + * + * The master copy of khrplatform.h is maintained in the Khronos EGL + * Registry repository at https://github.com/KhronosGroup/EGL-Registry + * The last semantic modification to khrplatform.h was at commit ID: + * 67a3e0864c2d75ea5287b9f3d2eb74a745936692 + * + * Adopters may modify this file to suit their platform. Adopters are + * encouraged to submit platform specific modifications to the Khronos + * group so that they can be included in future versions of this file. + * Please submit changes by filing pull requests or issues on + * the EGL Registry repository linked above. + * + * + * See the Implementer's Guidelines for information about where this file + * should be located on your system and for more details of its use: + * http://www.khronos.org/registry/implementers_guide.pdf + * + * This file should be included as + * #include + * by Khronos client API header files that use its types and defines. + * + * The types in khrplatform.h should only be used to define API-specific types. + * + * Types defined in khrplatform.h: + * khronos_int8_t signed 8 bit + * khronos_uint8_t unsigned 8 bit + * khronos_int16_t signed 16 bit + * khronos_uint16_t unsigned 16 bit + * khronos_int32_t signed 32 bit + * khronos_uint32_t unsigned 32 bit + * khronos_int64_t signed 64 bit + * khronos_uint64_t unsigned 64 bit + * khronos_intptr_t signed same number of bits as a pointer + * khronos_uintptr_t unsigned same number of bits as a pointer + * khronos_ssize_t signed size + * khronos_usize_t unsigned size + * khronos_float_t signed 32 bit floating point + * khronos_time_ns_t unsigned 64 bit time in nanoseconds + * khronos_utime_nanoseconds_t unsigned time interval or absolute time in + * nanoseconds + * khronos_stime_nanoseconds_t signed time interval in nanoseconds + * khronos_boolean_enum_t enumerated boolean type. This should + * only be used as a base type when a client API's boolean type is + * an enum. Client APIs which use an integer or other type for + * booleans cannot use this as the base type for their boolean. + * + * Tokens defined in khrplatform.h: + * + * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. + * + * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. + * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. + * + * Calling convention macros defined in this file: + * KHRONOS_APICALL + * KHRONOS_APIENTRY + * KHRONOS_APIATTRIBUTES + * + * These may be used in function prototypes as: + * + * KHRONOS_APICALL void KHRONOS_APIENTRY funcname( + * int arg1, + * int arg2) KHRONOS_APIATTRIBUTES; + */ + +#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC) +# define KHRONOS_STATIC 1 +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APICALL + *------------------------------------------------------------------------- + * This precedes the return type of the function in the function prototype. + */ +#if defined(KHRONOS_STATIC) + /* If the preprocessor constant KHRONOS_STATIC is defined, make the + * header compatible with static linking. */ +# define KHRONOS_APICALL +#elif defined(_WIN32) +# define KHRONOS_APICALL __declspec(dllimport) +#elif defined (__SYMBIAN32__) +# define KHRONOS_APICALL IMPORT_C +#elif defined(__ANDROID__) +# define KHRONOS_APICALL __attribute__((visibility("default"))) +#else +# define KHRONOS_APICALL +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIENTRY + *------------------------------------------------------------------------- + * This follows the return type of the function and precedes the function + * name in the function prototype. + */ +#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) + /* Win32 but not WinCE */ +# define KHRONOS_APIENTRY __stdcall +#else +# define KHRONOS_APIENTRY +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIATTRIBUTES + *------------------------------------------------------------------------- + * This follows the closing parenthesis of the function prototype arguments. + */ +#if defined (__ARMCC_2__) +#define KHRONOS_APIATTRIBUTES __softfp +#else +#define KHRONOS_APIATTRIBUTES +#endif + +/*------------------------------------------------------------------------- + * basic type definitions + *-----------------------------------------------------------------------*/ +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) + + +/* + * Using + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 +/* + * To support platform where unsigned long cannot be used interchangeably with + * inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t. + * Ideally, we could just use (u)intptr_t everywhere, but this could result in + * ABI breakage if khronos_uintptr_t is changed from unsigned long to + * unsigned long long or similar (this results in different C++ name mangling). + * To avoid changes for existing platforms, we restrict usage of intptr_t to + * platforms where the size of a pointer is larger than the size of long. + */ +#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__) +#if __SIZEOF_POINTER__ > __SIZEOF_LONG__ +#define KHRONOS_USE_INTPTR_T +#endif +#endif + +#elif defined(__VMS ) || defined(__sgi) + +/* + * Using + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(_WIN32) && !defined(__SCITECH_SNAP__) + +/* + * Win32 + */ +typedef __int32 khronos_int32_t; +typedef unsigned __int32 khronos_uint32_t; +typedef __int64 khronos_int64_t; +typedef unsigned __int64 khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(__sun__) || defined(__digital__) + +/* + * Sun or Digital + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#if defined(__arch64__) || defined(_LP64) +typedef long int khronos_int64_t; +typedef unsigned long int khronos_uint64_t; +#else +typedef long long int khronos_int64_t; +typedef unsigned long long int khronos_uint64_t; +#endif /* __arch64__ */ +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif 0 + +/* + * Hypothetical platform with no float or int64 support + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#define KHRONOS_SUPPORT_INT64 0 +#define KHRONOS_SUPPORT_FLOAT 0 + +#else + +/* + * Generic fallback + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#endif + + +/* + * Types that are (so far) the same on all platforms + */ +typedef signed char khronos_int8_t; +typedef unsigned char khronos_uint8_t; +typedef signed short int khronos_int16_t; +typedef unsigned short int khronos_uint16_t; + +/* + * Types that differ between LLP64 and LP64 architectures - in LLP64, + * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears + * to be the only LLP64 architecture in current use. + */ +#ifdef KHRONOS_USE_INTPTR_T +typedef intptr_t khronos_intptr_t; +typedef uintptr_t khronos_uintptr_t; +#elif defined(_WIN64) +typedef signed long long int khronos_intptr_t; +typedef unsigned long long int khronos_uintptr_t; +#else +typedef signed long int khronos_intptr_t; +typedef unsigned long int khronos_uintptr_t; +#endif + +#if defined(_WIN64) +typedef signed long long int khronos_ssize_t; +typedef unsigned long long int khronos_usize_t; +#else +typedef signed long int khronos_ssize_t; +typedef unsigned long int khronos_usize_t; +#endif + +#if KHRONOS_SUPPORT_FLOAT +/* + * Float type + */ +typedef float khronos_float_t; +#endif + +#if KHRONOS_SUPPORT_INT64 +/* Time types + * + * These types can be used to represent a time interval in nanoseconds or + * an absolute Unadjusted System Time. Unadjusted System Time is the number + * of nanoseconds since some arbitrary system event (e.g. since the last + * time the system booted). The Unadjusted System Time is an unsigned + * 64 bit value that wraps back to 0 every 584 years. Time intervals + * may be either signed or unsigned. + */ +typedef khronos_uint64_t khronos_utime_nanoseconds_t; +typedef khronos_int64_t khronos_stime_nanoseconds_t; +#endif + +/* + * Dummy value used to pad enum types to 32 bits. + */ +#ifndef KHRONOS_MAX_ENUM +#define KHRONOS_MAX_ENUM 0x7FFFFFFF +#endif + +/* + * Enumerated boolean type + * + * Values other than zero should be considered to be true. Therefore + * comparisons should not be made against KHRONOS_TRUE. + */ +typedef enum { + KHRONOS_FALSE = 0, + KHRONOS_TRUE = 1, + KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM +} khronos_boolean_enum_t; + +#endif /* __khrplatform_h_ */ diff --git a/thirdparty/glad/include/glad/gl.h b/thirdparty/glad/include/glad/gl.h new file mode 100644 index 000000000..4f1348196 --- /dev/null +++ b/thirdparty/glad/include/glad/gl.h @@ -0,0 +1,3795 @@ +/** + * Loader generated by glad 2.0.2 on Sun Jan 8 22:32:41 2023 + * + * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0 + * + * Generator: C/C++ + * Specification: gl + * Extensions: 62 + * + * APIs: + * - gl:core=3.2 + * + * Options: + * - ALIAS = True + * - DEBUG = False + * - HEADER_ONLY = False + * - LOADER = False + * - MX = True + * - ON_DEMAND = False + * + * Commandline: + * --api='gl:core=3.2' --extensions='GL_APPLE_flush_buffer_range,GL_APPLE_vertex_array_object,GL_ARB_color_buffer_float,GL_ARB_copy_buffer,GL_ARB_draw_buffers,GL_ARB_draw_elements_base_vertex,GL_ARB_draw_instanced,GL_ARB_framebuffer_object,GL_ARB_geometry_shader4,GL_ARB_imaging,GL_ARB_map_buffer_range,GL_ARB_multisample,GL_ARB_multitexture,GL_ARB_occlusion_query,GL_ARB_point_parameters,GL_ARB_provoking_vertex,GL_ARB_shader_objects,GL_ARB_sync,GL_ARB_texture_buffer_object,GL_ARB_texture_compression,GL_ARB_texture_multisample,GL_ARB_uniform_buffer_object,GL_ARB_vertex_array_object,GL_ARB_vertex_buffer_object,GL_ARB_vertex_program,GL_ARB_vertex_shader,GL_ATI_draw_buffers,GL_ATI_separate_stencil,GL_EXT_blend_color,GL_EXT_blend_equation_separate,GL_EXT_blend_func_separate,GL_EXT_blend_minmax,GL_EXT_copy_texture,GL_EXT_direct_state_access,GL_EXT_draw_buffers2,GL_EXT_draw_instanced,GL_EXT_draw_range_elements,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_object,GL_EXT_gpu_shader4,GL_EXT_multi_draw_arrays,GL_EXT_point_parameters,GL_EXT_provoking_vertex,GL_EXT_subtexture,GL_EXT_texture3D,GL_EXT_texture_array,GL_EXT_texture_buffer_object,GL_EXT_texture_integer,GL_EXT_texture_object,GL_EXT_transform_feedback,GL_EXT_vertex_array,GL_INGR_blend_func_separate,GL_NVX_conditional_render,GL_NV_conditional_render,GL_NV_explicit_multisample,GL_NV_geometry_program4,GL_NV_point_sprite,GL_NV_transform_feedback,GL_NV_vertex_program,GL_NV_vertex_program4,GL_SGIS_point_parameters' c --alias --mx + * + * Online: + * http://glad.sh/#api=gl%3Acore%3D3.2&extensions=GL_APPLE_flush_buffer_range%2CGL_APPLE_vertex_array_object%2CGL_ARB_color_buffer_float%2CGL_ARB_copy_buffer%2CGL_ARB_draw_buffers%2CGL_ARB_draw_elements_base_vertex%2CGL_ARB_draw_instanced%2CGL_ARB_framebuffer_object%2CGL_ARB_geometry_shader4%2CGL_ARB_imaging%2CGL_ARB_map_buffer_range%2CGL_ARB_multisample%2CGL_ARB_multitexture%2CGL_ARB_occlusion_query%2CGL_ARB_point_parameters%2CGL_ARB_provoking_vertex%2CGL_ARB_shader_objects%2CGL_ARB_sync%2CGL_ARB_texture_buffer_object%2CGL_ARB_texture_compression%2CGL_ARB_texture_multisample%2CGL_ARB_uniform_buffer_object%2CGL_ARB_vertex_array_object%2CGL_ARB_vertex_buffer_object%2CGL_ARB_vertex_program%2CGL_ARB_vertex_shader%2CGL_ATI_draw_buffers%2CGL_ATI_separate_stencil%2CGL_EXT_blend_color%2CGL_EXT_blend_equation_separate%2CGL_EXT_blend_func_separate%2CGL_EXT_blend_minmax%2CGL_EXT_copy_texture%2CGL_EXT_direct_state_access%2CGL_EXT_draw_buffers2%2CGL_EXT_draw_instanced%2CGL_EXT_draw_range_elements%2CGL_EXT_framebuffer_blit%2CGL_EXT_framebuffer_multisample%2CGL_EXT_framebuffer_object%2CGL_EXT_gpu_shader4%2CGL_EXT_multi_draw_arrays%2CGL_EXT_point_parameters%2CGL_EXT_provoking_vertex%2CGL_EXT_subtexture%2CGL_EXT_texture3D%2CGL_EXT_texture_array%2CGL_EXT_texture_buffer_object%2CGL_EXT_texture_integer%2CGL_EXT_texture_object%2CGL_EXT_transform_feedback%2CGL_EXT_vertex_array%2CGL_INGR_blend_func_separate%2CGL_NVX_conditional_render%2CGL_NV_conditional_render%2CGL_NV_explicit_multisample%2CGL_NV_geometry_program4%2CGL_NV_point_sprite%2CGL_NV_transform_feedback%2CGL_NV_vertex_program%2CGL_NV_vertex_program4%2CGL_SGIS_point_parameters&generator=c&options=ALIAS%2CMX + * + */ + +#ifndef GLAD_GL_H_ +#define GLAD_GL_H_ + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreserved-id-macro" +#endif +#ifdef __gl_h_ + #error OpenGL (gl.h) header already included (API: gl), remove previous include! +#endif +#define __gl_h_ 1 +#ifdef __gl3_h_ + #error OpenGL (gl3.h) header already included (API: gl), remove previous include! +#endif +#define __gl3_h_ 1 +#ifdef __glext_h_ + #error OpenGL (glext.h) header already included (API: gl), remove previous include! +#endif +#define __glext_h_ 1 +#ifdef __gl3ext_h_ + #error OpenGL (gl3ext.h) header already included (API: gl), remove previous include! +#endif +#define __gl3ext_h_ 1 +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#define GLAD_GL +#define GLAD_OPTION_GL_ALIAS +#define GLAD_OPTION_GL_MX + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef GLAD_PLATFORM_H_ +#define GLAD_PLATFORM_H_ + +#ifndef GLAD_PLATFORM_WIN32 + #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__) + #define GLAD_PLATFORM_WIN32 1 + #else + #define GLAD_PLATFORM_WIN32 0 + #endif +#endif + +#ifndef GLAD_PLATFORM_APPLE + #ifdef __APPLE__ + #define GLAD_PLATFORM_APPLE 1 + #else + #define GLAD_PLATFORM_APPLE 0 + #endif +#endif + +#ifndef GLAD_PLATFORM_EMSCRIPTEN + #ifdef __EMSCRIPTEN__ + #define GLAD_PLATFORM_EMSCRIPTEN 1 + #else + #define GLAD_PLATFORM_EMSCRIPTEN 0 + #endif +#endif + +#ifndef GLAD_PLATFORM_UWP + #if defined(_MSC_VER) && !defined(GLAD_INTERNAL_HAVE_WINAPIFAMILY) + #ifdef __has_include + #if __has_include() + #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1 + #endif + #elif _MSC_VER >= 1700 && !_USING_V110_SDK71_ + #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1 + #endif + #endif + + #ifdef GLAD_INTERNAL_HAVE_WINAPIFAMILY + #include + #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) + #define GLAD_PLATFORM_UWP 1 + #endif + #endif + + #ifndef GLAD_PLATFORM_UWP + #define GLAD_PLATFORM_UWP 0 + #endif +#endif + +#ifdef __GNUC__ + #define GLAD_GNUC_EXTENSION __extension__ +#else + #define GLAD_GNUC_EXTENSION +#endif + +#define GLAD_UNUSED(x) (void)(x) + +#ifndef GLAD_API_CALL + #if defined(GLAD_API_CALL_EXPORT) + #if GLAD_PLATFORM_WIN32 || defined(__CYGWIN__) + #if defined(GLAD_API_CALL_EXPORT_BUILD) + #if defined(__GNUC__) + #define GLAD_API_CALL __attribute__ ((dllexport)) extern + #else + #define GLAD_API_CALL __declspec(dllexport) extern + #endif + #else + #if defined(__GNUC__) + #define GLAD_API_CALL __attribute__ ((dllimport)) extern + #else + #define GLAD_API_CALL __declspec(dllimport) extern + #endif + #endif + #elif defined(__GNUC__) && defined(GLAD_API_CALL_EXPORT_BUILD) + #define GLAD_API_CALL __attribute__ ((visibility ("default"))) extern + #else + #define GLAD_API_CALL extern + #endif + #else + #define GLAD_API_CALL extern + #endif +#endif + +#ifdef APIENTRY + #define GLAD_API_PTR APIENTRY +#elif GLAD_PLATFORM_WIN32 + #define GLAD_API_PTR __stdcall +#else + #define GLAD_API_PTR +#endif + +#ifndef GLAPI +#define GLAPI GLAD_API_CALL +#endif + +#ifndef GLAPIENTRY +#define GLAPIENTRY GLAD_API_PTR +#endif + +#define GLAD_MAKE_VERSION(major, minor) (major * 10000 + minor) +#define GLAD_VERSION_MAJOR(version) (version / 10000) +#define GLAD_VERSION_MINOR(version) (version % 10000) + +#define GLAD_GENERATOR_VERSION "2.0.2" + +typedef void (*GLADapiproc)(void); + +typedef GLADapiproc (*GLADloadfunc)(const char *name); +typedef GLADapiproc (*GLADuserptrloadfunc)(void *userptr, const char *name); + +typedef void (*GLADprecallback)(const char *name, GLADapiproc apiproc, int len_args, ...); +typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apiproc, int len_args, ...); + +#endif /* GLAD_PLATFORM_H_ */ + +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_ACTIVE_TEXTURE_ARB 0x84E0 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_ACTIVE_VARYINGS_NV 0x8C81 +#define GL_ACTIVE_VARYING_MAX_LENGTH_NV 0x8C82 +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_ALPHA 0x1906 +#define GL_ALPHA16I_EXT 0x8D8A +#define GL_ALPHA16UI_EXT 0x8D78 +#define GL_ALPHA32I_EXT 0x8D84 +#define GL_ALPHA32UI_EXT 0x8D72 +#define GL_ALPHA8I_EXT 0x8D90 +#define GL_ALPHA8UI_EXT 0x8D7E +#define GL_ALPHA_INTEGER_EXT 0x8D97 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_ALWAYS 0x0207 +#define GL_AND 0x1501 +#define GL_AND_INVERTED 0x1504 +#define GL_AND_REVERSE 0x1502 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ARRAY_BUFFER_ARB 0x8892 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645 +#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623 +#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624 +#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625 +#define GL_BACK 0x0405 +#define GL_BACK_LEFT 0x0402 +#define GL_BACK_PRIMARY_COLOR_NV 0x8C77 +#define GL_BACK_RIGHT 0x0403 +#define GL_BACK_SECONDARY_COLOR_NV 0x8C78 +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_BGRA_INTEGER 0x8D9B +#define GL_BGRA_INTEGER_EXT 0x8D9B +#define GL_BGR_INTEGER 0x8D9A +#define GL_BGR_INTEGER_EXT 0x8D9A +#define GL_BLEND 0x0BE2 +#define GL_BLEND_COLOR 0x8005 +#define GL_BLEND_COLOR_EXT 0x8005 +#define GL_BLEND_DST 0x0BE0 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_DST_ALPHA_EXT 0x80CA +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_DST_RGB_EXT 0x80C8 +#define GL_BLEND_EQUATION 0x8009 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_BLEND_EQUATION_ALPHA_EXT 0x883D +#define GL_BLEND_EQUATION_EXT 0x8009 +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_BLEND_EQUATION_RGB_EXT 0x8009 +#define GL_BLEND_SRC 0x0BE1 +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_BLEND_SRC_ALPHA_EXT 0x80CB +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_SRC_RGB_EXT 0x80C9 +#define GL_BLUE 0x1905 +#define GL_BLUE_INTEGER 0x8D96 +#define GL_BLUE_INTEGER_EXT 0x8D96 +#define GL_BOOL 0x8B56 +#define GL_BOOL_ARB 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC2_ARB 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC3_ARB 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_BOOL_VEC4_ARB 0x8B59 +#define GL_BUFFER_ACCESS 0x88BB +#define GL_BUFFER_ACCESS_ARB 0x88BB +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_FLUSHING_UNMAP_APPLE 0x8A13 +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAPPED_ARB 0x88BC +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_BUFFER_MAP_POINTER_ARB 0x88BD +#define GL_BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12 +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_SIZE_ARB 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_BUFFER_USAGE_ARB 0x8765 +#define GL_BYTE 0x1400 +#define GL_CCW 0x0901 +#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B +#define GL_CLAMP_READ_COLOR 0x891C +#define GL_CLAMP_READ_COLOR_ARB 0x891C +#define GL_CLAMP_TO_BORDER 0x812D +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A +#define GL_CLEAR 0x1500 +#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 +#define GL_CLIP_DISTANCE0 0x3000 +#define GL_CLIP_DISTANCE1 0x3001 +#define GL_CLIP_DISTANCE2 0x3002 +#define GL_CLIP_DISTANCE3 0x3003 +#define GL_CLIP_DISTANCE4 0x3004 +#define GL_CLIP_DISTANCE5 0x3005 +#define GL_CLIP_DISTANCE6 0x3006 +#define GL_CLIP_DISTANCE7 0x3007 +#define GL_CLIP_DISTANCE_NV 0x8C7A +#define GL_COLOR 0x1800 +#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898 +#define GL_COLOR_ARRAY_COUNT_EXT 0x8084 +#define GL_COLOR_ARRAY_EXT 0x8076 +#define GL_COLOR_ARRAY_POINTER_EXT 0x8090 +#define GL_COLOR_ARRAY_SIZE_EXT 0x8081 +#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083 +#define GL_COLOR_ARRAY_TYPE_EXT 0x8082 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT13_EXT 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF +#define GL_COLOR_ATTACHMENT16 0x8CF0 +#define GL_COLOR_ATTACHMENT17 0x8CF1 +#define GL_COLOR_ATTACHMENT18 0x8CF2 +#define GL_COLOR_ATTACHMENT19 0x8CF3 +#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT20 0x8CF4 +#define GL_COLOR_ATTACHMENT21 0x8CF5 +#define GL_COLOR_ATTACHMENT22 0x8CF6 +#define GL_COLOR_ATTACHMENT23 0x8CF7 +#define GL_COLOR_ATTACHMENT24 0x8CF8 +#define GL_COLOR_ATTACHMENT25 0x8CF9 +#define GL_COLOR_ATTACHMENT26 0x8CFA +#define GL_COLOR_ATTACHMENT27 0x8CFB +#define GL_COLOR_ATTACHMENT28 0x8CFC +#define GL_COLOR_ATTACHMENT29 0x8CFD +#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT30 0x8CFE +#define GL_COLOR_ATTACHMENT31 0x8CFF +#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_LOGIC_OP 0x0BF2 +#define GL_COLOR_SUM_ARB 0x8458 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_COMPILE_STATUS 0x8B81 +#define GL_COMPRESSED_ALPHA_ARB 0x84E9 +#define GL_COMPRESSED_INTENSITY_ARB 0x84EC +#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB +#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA +#define GL_COMPRESSED_RED 0x8225 +#define GL_COMPRESSED_RED_RGTC1 0x8DBB +#define GL_COMPRESSED_RG 0x8226 +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_COMPRESSED_RGBA_ARB 0x84EE +#define GL_COMPRESSED_RGB_ARB 0x84ED +#define GL_COMPRESSED_RG_RGTC2 0x8DBD +#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC +#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE +#define GL_COMPRESSED_SRGB 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA 0x8C49 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 +#define GL_CONDITION_SATISFIED 0x911C +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_CONSTANT_ALPHA_EXT 0x8003 +#define GL_CONSTANT_COLOR 0x8001 +#define GL_CONSTANT_COLOR_EXT 0x8001 +#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 +#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001 +#define GL_CONTEXT_FLAGS 0x821E +#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001 +#define GL_CONTEXT_PROFILE_MASK 0x9126 +#define GL_COORD_REPLACE_NV 0x8862 +#define GL_COPY 0x1503 +#define GL_COPY_INVERTED 0x150C +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_CULL_FACE 0x0B44 +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_CURRENT_ATTRIB_NV 0x8626 +#define GL_CURRENT_MATRIX_ARB 0x8641 +#define GL_CURRENT_MATRIX_NV 0x8641 +#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640 +#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640 +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_CURRENT_QUERY 0x8865 +#define GL_CURRENT_QUERY_ARB 0x8865 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626 +#define GL_CW 0x0900 +#define GL_DECR 0x1E03 +#define GL_DECR_WRAP 0x8508 +#define GL_DELETE_STATUS 0x8B80 +#define GL_DEPTH 0x1801 +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_DEPTH_ATTACHMENT_EXT 0x8D00 +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_DEPTH_CLAMP 0x864F +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_DEPTH_COMPONENT32 0x81A7 +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH_FUNC 0x0B74 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_DEPTH_TEST 0x0B71 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DISTANCE_ATTENUATION_EXT 0x8129 +#define GL_DISTANCE_ATTENUATION_SGIS 0x8129 +#define GL_DITHER 0x0BD0 +#define GL_DONT_CARE 0x1100 +#define GL_DOUBLE 0x140A +#define GL_DOUBLEBUFFER 0x0C32 +#define GL_DRAW_BUFFER 0x0C01 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER0_ARB 0x8825 +#define GL_DRAW_BUFFER0_ATI 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER10_ARB 0x882F +#define GL_DRAW_BUFFER10_ATI 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER11_ARB 0x8830 +#define GL_DRAW_BUFFER11_ATI 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER12_ARB 0x8831 +#define GL_DRAW_BUFFER12_ATI 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER13_ARB 0x8832 +#define GL_DRAW_BUFFER13_ATI 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER14_ARB 0x8833 +#define GL_DRAW_BUFFER14_ATI 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_DRAW_BUFFER15_ARB 0x8834 +#define GL_DRAW_BUFFER15_ATI 0x8834 +#define GL_DRAW_BUFFER1_ARB 0x8826 +#define GL_DRAW_BUFFER1_ATI 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER2_ARB 0x8827 +#define GL_DRAW_BUFFER2_ATI 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER3_ARB 0x8828 +#define GL_DRAW_BUFFER3_ATI 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER4_ARB 0x8829 +#define GL_DRAW_BUFFER4_ATI 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER5_ARB 0x882A +#define GL_DRAW_BUFFER5_ATI 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER6_ARB 0x882B +#define GL_DRAW_BUFFER6_ATI 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER7_ARB 0x882C +#define GL_DRAW_BUFFER7_ATI 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER8_ARB 0x882D +#define GL_DRAW_BUFFER8_ATI 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER9_ARB 0x882E +#define GL_DRAW_BUFFER9_ATI 0x882E +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6 +#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9 +#define GL_DST_ALPHA 0x0304 +#define GL_DST_COLOR 0x0306 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_DYNAMIC_COPY_ARB 0x88EA +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_DRAW_ARB 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_READ_ARB 0x88E9 +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B +#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D +#define GL_EDGE_FLAG_ARRAY_EXT 0x8079 +#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093 +#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895 +#define GL_EQUAL 0x0202 +#define GL_EQUIV 0x1509 +#define GL_EXTENSIONS 0x1F03 +#define GL_FALSE 0 +#define GL_FASTEST 0x1101 +#define GL_FILL 0x1B02 +#define GL_FIRST_VERTEX_CONVENTION 0x8E4D +#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D +#define GL_FIXED_ONLY 0x891D +#define GL_FIXED_ONLY_ARB 0x891D +#define GL_FLOAT 0x1406 +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT2_ARB 0x8B5A +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT3_ARB 0x8B5B +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4 0x8B5C +#define GL_FLOAT_MAT4_ARB 0x8B5C +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC2_ARB 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC3_ARB 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_FLOAT_VEC4_ARB 0x8B52 +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_FRAMEBUFFER 0x8D40 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2 +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_EXT 0x8D40 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9 +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC +#define GL_FRAMEBUFFER_SRGB 0x8DB9 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD +#define GL_FRONT 0x0404 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_FRONT_FACE 0x0B46 +#define GL_FRONT_LEFT 0x0400 +#define GL_FRONT_RIGHT 0x0401 +#define GL_FUNC_ADD 0x8006 +#define GL_FUNC_ADD_EXT 0x8006 +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_FUNC_SUBTRACT 0x800A +#define GL_GENERIC_ATTRIB_NV 0x8C7D +#define GL_GEOMETRY_INPUT_TYPE 0x8917 +#define GL_GEOMETRY_INPUT_TYPE_ARB 0x8DDB +#define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB +#define GL_GEOMETRY_OUTPUT_TYPE 0x8918 +#define GL_GEOMETRY_OUTPUT_TYPE_ARB 0x8DDC +#define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC +#define GL_GEOMETRY_PROGRAM_NV 0x8C26 +#define GL_GEOMETRY_SHADER 0x8DD9 +#define GL_GEOMETRY_SHADER_ARB 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT 0x8916 +#define GL_GEOMETRY_VERTICES_OUT_ARB 0x8DDA +#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA +#define GL_GEQUAL 0x0206 +#define GL_GREATER 0x0204 +#define GL_GREEN 0x1904 +#define GL_GREEN_INTEGER 0x8D95 +#define GL_GREEN_INTEGER_EXT 0x8D95 +#define GL_HALF_FLOAT 0x140B +#define GL_IDENTITY_NV 0x862A +#define GL_INCR 0x1E02 +#define GL_INCR_WRAP 0x8507 +#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899 +#define GL_INDEX_ARRAY_COUNT_EXT 0x8087 +#define GL_INDEX_ARRAY_EXT 0x8077 +#define GL_INDEX_ARRAY_POINTER_EXT 0x8091 +#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086 +#define GL_INDEX_ARRAY_TYPE_EXT 0x8085 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_INT 0x1404 +#define GL_INTENSITY16I_EXT 0x8D8B +#define GL_INTENSITY16UI_EXT 0x8D79 +#define GL_INTENSITY32I_EXT 0x8D85 +#define GL_INTENSITY32UI_EXT 0x8D73 +#define GL_INTENSITY8I_EXT 0x8D91 +#define GL_INTENSITY8UI_EXT 0x8D7F +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_INTERLEAVED_ATTRIBS_EXT 0x8C8C +#define GL_INTERLEAVED_ATTRIBS_NV 0x8C8C +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_1D_ARRAY_EXT 0x8DCE +#define GL_INT_SAMPLER_1D_EXT 0x8DC9 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_INT_SAMPLER_2D_ARRAY_EXT 0x8DCF +#define GL_INT_SAMPLER_2D_EXT 0x8DCA +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_INT_SAMPLER_2D_RECT 0x8DCD +#define GL_INT_SAMPLER_2D_RECT_EXT 0x8DCD +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_3D_EXT 0x8DCB +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0 +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_CUBE_EXT 0x8DCC +#define GL_INT_SAMPLER_RENDERBUFFER_NV 0x8E57 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC2_ARB 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC3_ARB 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_INT_VEC4_ARB 0x8B55 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 +#define GL_INVALID_INDEX 0xFFFFFFFF +#define GL_INVALID_OPERATION 0x0502 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVERSE_NV 0x862B +#define GL_INVERSE_TRANSPOSE_NV 0x862D +#define GL_INVERT 0x150A +#define GL_KEEP 0x1E00 +#define GL_LAST_VERTEX_CONVENTION 0x8E4E +#define GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E +#define GL_LAYER_NV 0x8DAA +#define GL_LEFT 0x0406 +#define GL_LEQUAL 0x0203 +#define GL_LESS 0x0201 +#define GL_LINE 0x1B01 +#define GL_LINEAR 0x2601 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_LINES 0x0001 +#define GL_LINES_ADJACENCY 0x000A +#define GL_LINES_ADJACENCY_ARB 0x000A +#define GL_LINES_ADJACENCY_EXT 0x000A +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_SMOOTH 0x0B20 +#define GL_LINE_SMOOTH_HINT 0x0C52 +#define GL_LINE_STRIP 0x0003 +#define GL_LINE_STRIP_ADJACENCY 0x000B +#define GL_LINE_STRIP_ADJACENCY_ARB 0x000B +#define GL_LINE_STRIP_ADJACENCY_EXT 0x000B +#define GL_LINE_WIDTH 0x0B21 +#define GL_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_LINE_WIDTH_RANGE 0x0B22 +#define GL_LINK_STATUS 0x8B82 +#define GL_LOGIC_OP_MODE 0x0BF0 +#define GL_LOWER_LEFT 0x8CA1 +#define GL_LUMINANCE16I_EXT 0x8D8C +#define GL_LUMINANCE16UI_EXT 0x8D7A +#define GL_LUMINANCE32I_EXT 0x8D86 +#define GL_LUMINANCE32UI_EXT 0x8D74 +#define GL_LUMINANCE8I_EXT 0x8D92 +#define GL_LUMINANCE8UI_EXT 0x8D80 +#define GL_LUMINANCE_ALPHA16I_EXT 0x8D8D +#define GL_LUMINANCE_ALPHA16UI_EXT 0x8D7B +#define GL_LUMINANCE_ALPHA32I_EXT 0x8D87 +#define GL_LUMINANCE_ALPHA32UI_EXT 0x8D75 +#define GL_LUMINANCE_ALPHA8I_EXT 0x8D93 +#define GL_LUMINANCE_ALPHA8UI_EXT 0x8D81 +#define GL_LUMINANCE_ALPHA_INTEGER_EXT 0x8D9D +#define GL_LUMINANCE_INTEGER_EXT 0x8D9C +#define GL_MAJOR_VERSION 0x821B +#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660 +#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A +#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B +#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C +#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D +#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E +#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F +#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661 +#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662 +#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663 +#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664 +#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665 +#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666 +#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667 +#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668 +#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669 +#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670 +#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A +#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B +#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C +#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D +#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E +#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F +#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671 +#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672 +#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673 +#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674 +#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675 +#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676 +#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677 +#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678 +#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MATRIX0_ARB 0x88C0 +#define GL_MATRIX0_NV 0x8630 +#define GL_MATRIX10_ARB 0x88CA +#define GL_MATRIX11_ARB 0x88CB +#define GL_MATRIX12_ARB 0x88CC +#define GL_MATRIX13_ARB 0x88CD +#define GL_MATRIX14_ARB 0x88CE +#define GL_MATRIX15_ARB 0x88CF +#define GL_MATRIX16_ARB 0x88D0 +#define GL_MATRIX17_ARB 0x88D1 +#define GL_MATRIX18_ARB 0x88D2 +#define GL_MATRIX19_ARB 0x88D3 +#define GL_MATRIX1_ARB 0x88C1 +#define GL_MATRIX1_NV 0x8631 +#define GL_MATRIX20_ARB 0x88D4 +#define GL_MATRIX21_ARB 0x88D5 +#define GL_MATRIX22_ARB 0x88D6 +#define GL_MATRIX23_ARB 0x88D7 +#define GL_MATRIX24_ARB 0x88D8 +#define GL_MATRIX25_ARB 0x88D9 +#define GL_MATRIX26_ARB 0x88DA +#define GL_MATRIX27_ARB 0x88DB +#define GL_MATRIX28_ARB 0x88DC +#define GL_MATRIX29_ARB 0x88DD +#define GL_MATRIX2_ARB 0x88C2 +#define GL_MATRIX2_NV 0x8632 +#define GL_MATRIX30_ARB 0x88DE +#define GL_MATRIX31_ARB 0x88DF +#define GL_MATRIX3_ARB 0x88C3 +#define GL_MATRIX3_NV 0x8633 +#define GL_MATRIX4_ARB 0x88C4 +#define GL_MATRIX4_NV 0x8634 +#define GL_MATRIX5_ARB 0x88C5 +#define GL_MATRIX5_NV 0x8635 +#define GL_MATRIX6_ARB 0x88C6 +#define GL_MATRIX6_NV 0x8636 +#define GL_MATRIX7_ARB 0x88C7 +#define GL_MATRIX7_NV 0x8637 +#define GL_MATRIX8_ARB 0x88C8 +#define GL_MATRIX9_ARB 0x88C9 +#define GL_MAX 0x8008 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073 +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT 0x88FF +#define GL_MAX_CLIP_DISTANCES 0x0D32 +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF +#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32 +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_MAX_DRAW_BUFFERS_ARB 0x8824 +#define GL_MAX_DRAW_BUFFERS_ATI 0x8824 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8 +#define GL_MAX_EXT 0x8008 +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123 +#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124 +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0 +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1 +#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF +#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD +#define GL_MAX_INTEGER_SAMPLES 0x9110 +#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1 +#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD +#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5 +#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1 +#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4 +#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F +#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E +#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3 +#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF +#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3 +#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB +#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7 +#define GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27 +#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9 +#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_MAX_PROGRAM_TEXEL_OFFSET_EXT 0x8905 +#define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_MAX_SAMPLES_EXT 0x8D57 +#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 +#define GL_MAX_SAMPLE_MASK_WORDS_NV 0x8E59 +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B +#define GL_MAX_TEXTURE_BUFFER_SIZE_ARB 0x8C2B +#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B +#define GL_MAX_TEXTURE_COORDS_ARB 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 +#define GL_MAX_TRACK_MATRICES_NV 0x862F +#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80 +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80 +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869 +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A +#define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_MIN 0x8007 +#define GL_MINOR_VERSION 0x821C +#define GL_MIN_EXT 0x8007 +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MIN_PROGRAM_TEXEL_OFFSET_EXT 0x8904 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_MODELVIEW_PROJECTION_NV 0x8629 +#define GL_MULTISAMPLE 0x809D +#define GL_MULTISAMPLE_ARB 0x809D +#define GL_MULTISAMPLE_BIT_ARB 0x20000000 +#define GL_NAND 0x150E +#define GL_NEAREST 0x2600 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_NEVER 0x0200 +#define GL_NEXT_BUFFER_NV -2 +#define GL_NICEST 0x1102 +#define GL_NONE 0 +#define GL_NOOP 0x1505 +#define GL_NOR 0x1508 +#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897 +#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080 +#define GL_NORMAL_ARRAY_EXT 0x8075 +#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F +#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F +#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E +#define GL_NOTEQUAL 0x0205 +#define GL_NO_ERROR 0 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 +#define GL_NUM_EXTENSIONS 0x821D +#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89 +#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A +#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86 +#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87 +#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85 +#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 +#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80 +#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 +#define GL_OBJECT_LINK_STATUS_ARB 0x8B82 +#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88 +#define GL_OBJECT_SUBTYPE_ARB 0x8B4F +#define GL_OBJECT_TYPE 0x9112 +#define GL_OBJECT_TYPE_ARB 0x8B4E +#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83 +#define GL_ONE 1 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_OR 0x1507 +#define GL_OR_INVERTED 0x150D +#define GL_OR_REVERSE 0x150B +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C +#define GL_PACK_LSB_FIRST 0x0D01 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_SKIP_IMAGES_EXT 0x806B +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SWAP_BYTES 0x0D00 +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_POINT 0x1B00 +#define GL_POINTS 0x0000 +#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129 +#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 +#define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128 +#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128 +#define GL_POINT_FADE_THRESHOLD_SIZE_SGIS 0x8128 +#define GL_POINT_SIZE 0x0B11 +#define GL_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_POINT_SIZE_MAX_ARB 0x8127 +#define GL_POINT_SIZE_MAX_EXT 0x8127 +#define GL_POINT_SIZE_MAX_SGIS 0x8127 +#define GL_POINT_SIZE_MIN_ARB 0x8126 +#define GL_POINT_SIZE_MIN_EXT 0x8126 +#define GL_POINT_SIZE_MIN_SGIS 0x8126 +#define GL_POINT_SIZE_RANGE 0x0B12 +#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 +#define GL_POINT_SPRITE_NV 0x8861 +#define GL_POINT_SPRITE_R_MODE_NV 0x8863 +#define GL_POLYGON_MODE 0x0B40 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_POLYGON_OFFSET_LINE 0x2A02 +#define GL_POLYGON_OFFSET_POINT 0x2A01 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_SMOOTH 0x0B41 +#define GL_POLYGON_SMOOTH_HINT 0x0C53 +#define GL_PRIMITIVES_GENERATED 0x8C87 +#define GL_PRIMITIVES_GENERATED_EXT 0x8C87 +#define GL_PRIMITIVES_GENERATED_NV 0x8C87 +#define GL_PRIMITIVE_ID_NV 0x8C7C +#define GL_PRIMITIVE_RESTART 0x8F9D +#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E +#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0 +#define GL_PROGRAM_ATTRIBS_ARB 0x88AC +#define GL_PROGRAM_BINDING_ARB 0x8677 +#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B +#define GL_PROGRAM_ERROR_POSITION_NV 0x864B +#define GL_PROGRAM_ERROR_STRING_ARB 0x8874 +#define GL_PROGRAM_FORMAT_ARB 0x8876 +#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875 +#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0 +#define GL_PROGRAM_LENGTH_ARB 0x8627 +#define GL_PROGRAM_LENGTH_NV 0x8627 +#define GL_PROGRAM_MATRIX_EXT 0x8E2D +#define GL_PROGRAM_MATRIX_STACK_DEPTH_EXT 0x8E2F +#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2 +#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE +#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2 +#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA +#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6 +#define GL_PROGRAM_OBJECT_ARB 0x8B40 +#define GL_PROGRAM_PARAMETERS_ARB 0x88A8 +#define GL_PROGRAM_PARAMETER_NV 0x8644 +#define GL_PROGRAM_POINT_SIZE 0x8642 +#define GL_PROGRAM_POINT_SIZE_ARB 0x8642 +#define GL_PROGRAM_POINT_SIZE_EXT 0x8642 +#define GL_PROGRAM_RESIDENT_NV 0x8647 +#define GL_PROGRAM_STRING_ARB 0x8628 +#define GL_PROGRAM_STRING_NV 0x8628 +#define GL_PROGRAM_TARGET_NV 0x8646 +#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4 +#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6 +#define GL_PROVOKING_VERTEX 0x8E4F +#define GL_PROVOKING_VERTEX_EXT 0x8E4F +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 +#define GL_PROXY_TEXTURE_1D_ARRAY_EXT 0x8C19 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B +#define GL_PROXY_TEXTURE_2D_ARRAY_EXT 0x8C1B +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103 +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_PROXY_TEXTURE_3D_EXT 0x8070 +#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B +#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7 +#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C +#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT 0x8E4C +#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 +#define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16 +#define GL_QUERY_BY_REGION_WAIT 0x8E15 +#define GL_QUERY_BY_REGION_WAIT_NV 0x8E15 +#define GL_QUERY_COUNTER_BITS 0x8864 +#define GL_QUERY_COUNTER_BITS_ARB 0x8864 +#define GL_QUERY_NO_WAIT 0x8E14 +#define GL_QUERY_NO_WAIT_NV 0x8E14 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_ARB 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867 +#define GL_QUERY_WAIT 0x8E13 +#define GL_QUERY_WAIT_NV 0x8E13 +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_R16 0x822A +#define GL_R16F 0x822D +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R16_SNORM 0x8F98 +#define GL_R32F 0x822E +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_R3_G3_B2 0x2A10 +#define GL_R8 0x8229 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R8_SNORM 0x8F94 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_RASTERIZER_DISCARD_EXT 0x8C89 +#define GL_RASTERIZER_DISCARD_NV 0x8C89 +#define GL_READ_BUFFER 0x0C02 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA +#define GL_READ_FRAMEBUFFER_EXT 0x8CA8 +#define GL_READ_ONLY 0x88B8 +#define GL_READ_ONLY_ARB 0x88B8 +#define GL_READ_WRITE 0x88BA +#define GL_READ_WRITE_ARB 0x88BA +#define GL_RED 0x1903 +#define GL_RED_INTEGER 0x8D94 +#define GL_RED_INTEGER_EXT 0x8D94 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54 +#define GL_RENDERBUFFER_EXT 0x8D41 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50 +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42 +#define GL_RENDERER 0x1F01 +#define GL_REPEAT 0x2901 +#define GL_REPLACE 0x1E01 +#define GL_RG 0x8227 +#define GL_RG16 0x822C +#define GL_RG16F 0x822F +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG16_SNORM 0x8F99 +#define GL_RG32F 0x8230 +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#define GL_RG8 0x822B +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB 0x1907 +#define GL_RGB10 0x8052 +#define GL_RGB10_A2 0x8059 +#define GL_RGB12 0x8053 +#define GL_RGB16 0x8054 +#define GL_RGB16F 0x881B +#define GL_RGB16I 0x8D89 +#define GL_RGB16I_EXT 0x8D89 +#define GL_RGB16UI 0x8D77 +#define GL_RGB16UI_EXT 0x8D77 +#define GL_RGB16_SNORM 0x8F9A +#define GL_RGB32F 0x8815 +#define GL_RGB32I 0x8D83 +#define GL_RGB32I_EXT 0x8D83 +#define GL_RGB32UI 0x8D71 +#define GL_RGB32UI_EXT 0x8D71 +#define GL_RGB4 0x804F +#define GL_RGB5 0x8050 +#define GL_RGB5_A1 0x8057 +#define GL_RGB8 0x8051 +#define GL_RGB8I 0x8D8F +#define GL_RGB8I_EXT 0x8D8F +#define GL_RGB8UI 0x8D7D +#define GL_RGB8UI_EXT 0x8D7D +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGB9_E5 0x8C3D +#define GL_RGBA 0x1908 +#define GL_RGBA12 0x805A +#define GL_RGBA16 0x805B +#define GL_RGBA16F 0x881A +#define GL_RGBA16I 0x8D88 +#define GL_RGBA16I_EXT 0x8D88 +#define GL_RGBA16UI 0x8D76 +#define GL_RGBA16UI_EXT 0x8D76 +#define GL_RGBA16_SNORM 0x8F9B +#define GL_RGBA2 0x8055 +#define GL_RGBA32F 0x8814 +#define GL_RGBA32I 0x8D82 +#define GL_RGBA32I_EXT 0x8D82 +#define GL_RGBA32UI 0x8D70 +#define GL_RGBA32UI_EXT 0x8D70 +#define GL_RGBA4 0x8056 +#define GL_RGBA8 0x8058 +#define GL_RGBA8I 0x8D8E +#define GL_RGBA8I_EXT 0x8D8E +#define GL_RGBA8UI 0x8D7C +#define GL_RGBA8UI_EXT 0x8D7C +#define GL_RGBA8_SNORM 0x8F97 +#define GL_RGBA_FLOAT_MODE_ARB 0x8820 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_RGBA_INTEGER_EXT 0x8D99 +#define GL_RGBA_INTEGER_MODE_EXT 0x8D9E +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGB_INTEGER_EXT 0x8D98 +#define GL_RG_INTEGER 0x8228 +#define GL_RIGHT 0x0407 +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_1D_ARB 0x8B5D +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_1D_ARRAY_SHADOW_EXT 0x8DC3 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61 +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_2D_ARB 0x8B5E +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_SAMPLER_2D_RECT 0x8B63 +#define GL_SAMPLER_2D_RECT_ARB 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 +#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62 +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_3D_ARB 0x8B5F +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_SAMPLER_BUFFER_EXT 0x8DC2 +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_CUBE_ARB 0x8B60 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_SAMPLER_CUBE_SHADOW_EXT 0x8DC5 +#define GL_SAMPLER_RENDERBUFFER_NV 0x8E56 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLES_ARB 0x80A9 +#define GL_SAMPLES_PASSED 0x8914 +#define GL_SAMPLES_PASSED_ARB 0x8914 +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLE_BUFFERS_ARB 0x80A8 +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_COVERAGE_ARB 0x80A0 +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA +#define GL_SAMPLE_MASK 0x8E51 +#define GL_SAMPLE_MASK_NV 0x8E51 +#define GL_SAMPLE_MASK_VALUE 0x8E52 +#define GL_SAMPLE_MASK_VALUE_NV 0x8E52 +#define GL_SAMPLE_POSITION 0x8E50 +#define GL_SAMPLE_POSITION_NV 0x8E50 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_SEPARATE_ATTRIBS_EXT 0x8C8D +#define GL_SEPARATE_ATTRIBS_NV 0x8C8D +#define GL_SET 0x150F +#define GL_SHADER_OBJECT_ARB 0x8B48 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_SHADER_TYPE 0x8B4F +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_SHORT 0x1402 +#define GL_SIGNALED 0x9119 +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_SKIP_COMPONENTS1_NV -6 +#define GL_SKIP_COMPONENTS2_NV -5 +#define GL_SKIP_COMPONENTS3_NV -4 +#define GL_SKIP_COMPONENTS4_NV -3 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_SRC1_ALPHA 0x8589 +#define GL_SRC_ALPHA 0x0302 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_SRC_COLOR 0x0300 +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_SRGB_ALPHA 0x8C42 +#define GL_STATIC_COPY 0x88E6 +#define GL_STATIC_COPY_ARB 0x88E6 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_DRAW_ARB 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_READ_ARB 0x88E5 +#define GL_STENCIL 0x1802 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_STENCIL_ATTACHMENT_EXT 0x8D20 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_FAIL_ATI 0x8801 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FUNC_ATI 0x8800 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_INDEX 0x1901 +#define GL_STENCIL_INDEX1 0x8D46 +#define GL_STENCIL_INDEX16 0x8D49 +#define GL_STENCIL_INDEX16_EXT 0x8D49 +#define GL_STENCIL_INDEX1_EXT 0x8D46 +#define GL_STENCIL_INDEX4 0x8D47 +#define GL_STENCIL_INDEX4_EXT 0x8D47 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_STENCIL_INDEX8_EXT 0x8D48 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_TEST 0x0B90 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_STEREO 0x0C33 +#define GL_STREAM_COPY 0x88E2 +#define GL_STREAM_COPY_ARB 0x88E2 +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_DRAW_ARB 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_READ_ARB 0x88E1 +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_SYNC_STATUS 0x9114 +#define GL_TEXTURE 0x1702 +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE0_ARB 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE10_ARB 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE11_ARB 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE12_ARB 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE13_ARB 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE14_ARB 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE15_ARB 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE16_ARB 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE17_ARB 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE18_ARB 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE19_ARB 0x84D3 +#define GL_TEXTURE1_ARB 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE20_ARB 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE21_ARB 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE22_ARB 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE23_ARB 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE24_ARB 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE25_ARB 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE26_ARB 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE27_ARB 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE28_ARB 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE29_ARB 0x84DD +#define GL_TEXTURE2_ARB 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE30_ARB 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_TEXTURE31_ARB 0x84DF +#define GL_TEXTURE3_ARB 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE4_ARB 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE5_ARB 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE6_ARB 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE7_ARB 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE8_ARB 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE9_ARB 0x84C9 +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_1D_ARRAY 0x8C18 +#define GL_TEXTURE_1D_ARRAY_EXT 0x8C18 +#define GL_TEXTURE_1D_BINDING_EXT 0x8068 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_TEXTURE_2D_ARRAY_EXT 0x8C1A +#define GL_TEXTURE_2D_BINDING_EXT 0x8069 +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 +#define GL_TEXTURE_3D 0x806F +#define GL_TEXTURE_3D_BINDING_EXT 0x806A +#define GL_TEXTURE_3D_EXT 0x806F +#define GL_TEXTURE_ALPHA_SIZE 0x805F +#define GL_TEXTURE_ALPHA_TYPE 0x8C13 +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_BINDING_1D 0x8068 +#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C +#define GL_TEXTURE_BINDING_1D_ARRAY_EXT 0x8C1C +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_TEXTURE_BINDING_2D_ARRAY_EXT 0x8C1D +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105 +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_TEXTURE_BINDING_BUFFER 0x8C2C +#define GL_TEXTURE_BINDING_BUFFER_ARB 0x8C2C +#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6 +#define GL_TEXTURE_BINDING_RENDERBUFFER_NV 0x8E53 +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_BORDER_COLOR 0x1004 +#define GL_TEXTURE_BUFFER 0x8C2A +#define GL_TEXTURE_BUFFER_ARB 0x8C2A +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB 0x8C2D +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D +#define GL_TEXTURE_BUFFER_EXT 0x8C2A +#define GL_TEXTURE_BUFFER_FORMAT_ARB 0x8C2E +#define GL_TEXTURE_BUFFER_FORMAT_EXT 0x8C2E +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_TEXTURE_COMPRESSED_ARB 0x86A1 +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0 +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A +#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B +#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078 +#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092 +#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088 +#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A +#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089 +#define GL_TEXTURE_COORD_NV 0x8C79 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_DEPTH_EXT 0x8071 +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_TEXTURE_DEPTH_TYPE 0x8C16 +#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_TEXTURE_LOD_BIAS 0x8501 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_PRIORITY_EXT 0x8066 +#define GL_TEXTURE_RECTANGLE 0x84F5 +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV 0x8E54 +#define GL_TEXTURE_RENDERBUFFER_NV 0x8E55 +#define GL_TEXTURE_RESIDENT_EXT 0x8067 +#define GL_TEXTURE_SAMPLES 0x9106 +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#define GL_TEXTURE_STENCIL_SIZE 0x88F1 +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_TEXTURE_WRAP_R_EXT 0x8072 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFF +#define GL_TRACK_MATRIX_NV 0x8648 +#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649 +#define GL_TRANSFORM_FEEDBACK_ATTRIBS_NV 0x8C7E +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT 0x8C8F +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F +#define GL_TRANSFORM_FEEDBACK_BUFFER_EXT 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT 0x8C7F +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F +#define GL_TRANSFORM_FEEDBACK_BUFFER_NV 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT 0x8C85 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT 0x8C88 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88 +#define GL_TRANSFORM_FEEDBACK_RECORD_NV 0x8C86 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_VARYINGS_EXT 0x8C83 +#define GL_TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83 +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT 0x8C76 +#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7 +#define GL_TRANSPOSE_NV 0x862C +#define GL_TRANSPOSE_PROGRAM_MATRIX_EXT 0x8E2E +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLES_ADJACENCY 0x000C +#define GL_TRIANGLES_ADJACENCY_ARB 0x000C +#define GL_TRIANGLES_ADJACENCY_EXT 0x000C +#define GL_TRIANGLE_FAN 0x0006 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D +#define GL_TRIANGLE_STRIP_ADJACENCY_ARB 0x000D +#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0x000D +#define GL_TRUE 1 +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E +#define GL_UNPACK_LSB_FIRST 0x0CF1 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SWAP_BYTES 0x0CF0 +#define GL_UNSIGNALED 0x9118 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_INT 0x1405 +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_1D_EXT 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7 +#define GL_UNSIGNED_INT_SAMPLER_2D_EXT 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_3D_EXT 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_CUBE_EXT 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV 0x8E58 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC2_EXT 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC3_EXT 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_UNSIGNED_INT_VEC4_EXT 0x8DC8 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UPPER_LEFT 0x8CA2 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_VENDOR 0x1F00 +#define GL_VERSION 0x1F02 +#define GL_VERTEX_ARRAY_BINDING 0x85B5 +#define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5 +#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896 +#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D +#define GL_VERTEX_ARRAY_EXT 0x8074 +#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E +#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A +#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C +#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B +#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650 +#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A +#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B +#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C +#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D +#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E +#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F +#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651 +#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652 +#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653 +#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654 +#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655 +#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656 +#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657 +#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658 +#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV 0x88FD +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625 +#define GL_VERTEX_ID_NV 0x8C7B +#define GL_VERTEX_PROGRAM_ARB 0x8620 +#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A +#define GL_VERTEX_PROGRAM_NV 0x8620 +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 +#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643 +#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_VERTEX_SHADER_ARB 0x8B31 +#define GL_VERTEX_STATE_PROGRAM_NV 0x8621 +#define GL_VIEWPORT 0x0BA2 +#define GL_WAIT_FAILED 0x911D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E +#define GL_WRITE_ONLY 0x88B9 +#define GL_WRITE_ONLY_ARB 0x88B9 +#define GL_XOR 0x1506 +#define GL_ZERO 0 + + +#include +typedef unsigned int GLenum; +typedef unsigned char GLboolean; +typedef unsigned int GLbitfield; +typedef void GLvoid; +typedef khronos_int8_t GLbyte; +typedef khronos_uint8_t GLubyte; +typedef khronos_int16_t GLshort; +typedef khronos_uint16_t GLushort; +typedef int GLint; +typedef unsigned int GLuint; +typedef khronos_int32_t GLclampx; +typedef int GLsizei; +typedef khronos_float_t GLfloat; +typedef khronos_float_t GLclampf; +typedef double GLdouble; +typedef double GLclampd; +typedef void *GLeglClientBufferEXT; +typedef void *GLeglImageOES; +typedef char GLchar; +typedef char GLcharARB; +#ifdef __APPLE__ +typedef void *GLhandleARB; +#else +typedef unsigned int GLhandleARB; +#endif +typedef khronos_uint16_t GLhalf; +typedef khronos_uint16_t GLhalfARB; +typedef khronos_int32_t GLfixed; +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) +typedef khronos_intptr_t GLintptr; +#else +typedef khronos_intptr_t GLintptr; +#endif +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) +typedef khronos_intptr_t GLintptrARB; +#else +typedef khronos_intptr_t GLintptrARB; +#endif +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) +typedef khronos_ssize_t GLsizeiptr; +#else +typedef khronos_ssize_t GLsizeiptr; +#endif +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) +typedef khronos_ssize_t GLsizeiptrARB; +#else +typedef khronos_ssize_t GLsizeiptrARB; +#endif +typedef khronos_int64_t GLint64; +typedef khronos_int64_t GLint64EXT; +typedef khronos_uint64_t GLuint64; +typedef khronos_uint64_t GLuint64EXT; +typedef struct __GLsync *GLsync; +struct _cl_context; +struct _cl_event; +typedef void (GLAD_API_PTR *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +typedef void (GLAD_API_PTR *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +typedef void (GLAD_API_PTR *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +typedef void (GLAD_API_PTR *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam); +typedef unsigned short GLhalfNV; +typedef GLintptr GLvdpauSurfaceNV; +typedef void (GLAD_API_PTR *GLVULKANPROCNV)(void); + + +#define GL_VERSION_1_0 1 +#define GL_VERSION_1_1 1 +#define GL_VERSION_1_2 1 +#define GL_VERSION_1_3 1 +#define GL_VERSION_1_4 1 +#define GL_VERSION_1_5 1 +#define GL_VERSION_2_0 1 +#define GL_VERSION_2_1 1 +#define GL_VERSION_3_0 1 +#define GL_VERSION_3_1 1 +#define GL_VERSION_3_2 1 +#define GL_APPLE_flush_buffer_range 1 +#define GL_APPLE_vertex_array_object 1 +#define GL_ARB_color_buffer_float 1 +#define GL_ARB_copy_buffer 1 +#define GL_ARB_draw_buffers 1 +#define GL_ARB_draw_elements_base_vertex 1 +#define GL_ARB_draw_instanced 1 +#define GL_ARB_framebuffer_object 1 +#define GL_ARB_geometry_shader4 1 +#define GL_ARB_imaging 1 +#define GL_ARB_map_buffer_range 1 +#define GL_ARB_multisample 1 +#define GL_ARB_multitexture 1 +#define GL_ARB_occlusion_query 1 +#define GL_ARB_point_parameters 1 +#define GL_ARB_provoking_vertex 1 +#define GL_ARB_shader_objects 1 +#define GL_ARB_sync 1 +#define GL_ARB_texture_buffer_object 1 +#define GL_ARB_texture_compression 1 +#define GL_ARB_texture_multisample 1 +#define GL_ARB_uniform_buffer_object 1 +#define GL_ARB_vertex_array_object 1 +#define GL_ARB_vertex_buffer_object 1 +#define GL_ARB_vertex_program 1 +#define GL_ARB_vertex_shader 1 +#define GL_ATI_draw_buffers 1 +#define GL_ATI_separate_stencil 1 +#define GL_EXT_blend_color 1 +#define GL_EXT_blend_equation_separate 1 +#define GL_EXT_blend_func_separate 1 +#define GL_EXT_blend_minmax 1 +#define GL_EXT_copy_texture 1 +#define GL_EXT_direct_state_access 1 +#define GL_EXT_draw_buffers2 1 +#define GL_EXT_draw_instanced 1 +#define GL_EXT_draw_range_elements 1 +#define GL_EXT_framebuffer_blit 1 +#define GL_EXT_framebuffer_multisample 1 +#define GL_EXT_framebuffer_object 1 +#define GL_EXT_gpu_shader4 1 +#define GL_EXT_multi_draw_arrays 1 +#define GL_EXT_point_parameters 1 +#define GL_EXT_provoking_vertex 1 +#define GL_EXT_subtexture 1 +#define GL_EXT_texture3D 1 +#define GL_EXT_texture_array 1 +#define GL_EXT_texture_buffer_object 1 +#define GL_EXT_texture_integer 1 +#define GL_EXT_texture_object 1 +#define GL_EXT_transform_feedback 1 +#define GL_EXT_vertex_array 1 +#define GL_INGR_blend_func_separate 1 +#define GL_NVX_conditional_render 1 +#define GL_NV_conditional_render 1 +#define GL_NV_explicit_multisample 1 +#define GL_NV_geometry_program4 1 +#define GL_NV_point_sprite 1 +#define GL_NV_transform_feedback 1 +#define GL_NV_vertex_program 1 +#define GL_NV_vertex_program4 1 +#define GL_SGIS_point_parameters 1 + + +typedef void (GLAD_API_PTR *PFNGLACTIVETEXTUREPROC)(GLenum texture); +typedef void (GLAD_API_PTR *PFNGLACTIVETEXTUREARBPROC)(GLenum texture); +typedef void (GLAD_API_PTR *PFNGLACTIVEVARYINGNVPROC)(GLuint program, const GLchar * name); +typedef GLboolean (GLAD_API_PTR *PFNGLAREPROGRAMSRESIDENTNVPROC)(GLsizei n, const GLuint * programs, GLboolean * residences); +typedef GLboolean (GLAD_API_PTR *PFNGLARETEXTURESRESIDENTEXTPROC)(GLsizei n, const GLuint * textures, GLboolean * residences); +typedef void (GLAD_API_PTR *PFNGLARRAYELEMENTEXTPROC)(GLint i); +typedef void (GLAD_API_PTR *PFNGLATTACHOBJECTARBPROC)(GLhandleARB containerObj, GLhandleARB obj); +typedef void (GLAD_API_PTR *PFNGLATTACHSHADERPROC)(GLuint program, GLuint shader); +typedef void (GLAD_API_PTR *PFNGLBEGINCONDITIONALRENDERPROC)(GLuint id, GLenum mode); +typedef void (GLAD_API_PTR *PFNGLBEGINCONDITIONALRENDERNVPROC)(GLuint id, GLenum mode); +typedef void (GLAD_API_PTR *PFNGLBEGINCONDITIONALRENDERNVXPROC)(GLuint id); +typedef void (GLAD_API_PTR *PFNGLBEGINQUERYPROC)(GLenum target, GLuint id); +typedef void (GLAD_API_PTR *PFNGLBEGINQUERYARBPROC)(GLenum target, GLuint id); +typedef void (GLAD_API_PTR *PFNGLBEGINTRANSFORMFEEDBACKPROC)(GLenum primitiveMode); +typedef void (GLAD_API_PTR *PFNGLBEGINTRANSFORMFEEDBACKEXTPROC)(GLenum primitiveMode); +typedef void (GLAD_API_PTR *PFNGLBEGINTRANSFORMFEEDBACKNVPROC)(GLenum primitiveMode); +typedef void (GLAD_API_PTR *PFNGLBINDATTRIBLOCATIONPROC)(GLuint program, GLuint index, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLBINDATTRIBLOCATIONARBPROC)(GLhandleARB programObj, GLuint index, const GLcharARB * name); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERARBPROC)(GLenum target, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERBASEPROC)(GLenum target, GLuint index, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERBASEEXTPROC)(GLenum target, GLuint index, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERBASENVPROC)(GLenum target, GLuint index, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFEROFFSETEXTPROC)(GLenum target, GLuint index, GLuint buffer, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFEROFFSETNVPROC)(GLenum target, GLuint index, GLuint buffer, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERRANGEPROC)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERRANGEEXTPROC)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERRANGENVPROC)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONPROC)(GLuint program, GLuint color, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONEXTPROC)(GLuint program, GLuint color, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLBINDFRAMEBUFFERPROC)(GLenum target, GLuint framebuffer); +typedef void (GLAD_API_PTR *PFNGLBINDFRAMEBUFFEREXTPROC)(GLenum target, GLuint framebuffer); +typedef void (GLAD_API_PTR *PFNGLBINDMULTITEXTUREEXTPROC)(GLenum texunit, GLenum target, GLuint texture); +typedef void (GLAD_API_PTR *PFNGLBINDPROGRAMARBPROC)(GLenum target, GLuint program); +typedef void (GLAD_API_PTR *PFNGLBINDPROGRAMNVPROC)(GLenum target, GLuint id); +typedef void (GLAD_API_PTR *PFNGLBINDRENDERBUFFERPROC)(GLenum target, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLBINDRENDERBUFFEREXTPROC)(GLenum target, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLBINDTEXTUREPROC)(GLenum target, GLuint texture); +typedef void (GLAD_API_PTR *PFNGLBINDTEXTUREEXTPROC)(GLenum target, GLuint texture); +typedef void (GLAD_API_PTR *PFNGLBINDVERTEXARRAYPROC)(GLuint array); +typedef void (GLAD_API_PTR *PFNGLBINDVERTEXARRAYAPPLEPROC)(GLuint array); +typedef void (GLAD_API_PTR *PFNGLBLENDCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (GLAD_API_PTR *PFNGLBLENDCOLOREXTPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONEXTPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum modeRGB, GLenum modeAlpha); +typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEEXTPROC)(GLenum modeRGB, GLenum modeAlpha); +typedef void (GLAD_API_PTR *PFNGLBLENDFUNCPROC)(GLenum sfactor, GLenum dfactor); +typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEPROC)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEEXTPROC)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEINGRPROC)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +typedef void (GLAD_API_PTR *PFNGLBLITFRAMEBUFFERPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef void (GLAD_API_PTR *PFNGLBLITFRAMEBUFFEREXTPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef void (GLAD_API_PTR *PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const void * data, GLenum usage); +typedef void (GLAD_API_PTR *PFNGLBUFFERDATAARBPROC)(GLenum target, GLsizeiptrARB size, const void * data, GLenum usage); +typedef void (GLAD_API_PTR *PFNGLBUFFERPARAMETERIAPPLEPROC)(GLenum target, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data); +typedef void (GLAD_API_PTR *PFNGLBUFFERSUBDATAARBPROC)(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const void * data); +typedef GLenum (GLAD_API_PTR *PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum target); +typedef GLenum (GLAD_API_PTR *PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)(GLenum target); +typedef GLenum (GLAD_API_PTR *PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC)(GLuint framebuffer, GLenum target); +typedef void (GLAD_API_PTR *PFNGLCLAMPCOLORPROC)(GLenum target, GLenum clamp); +typedef void (GLAD_API_PTR *PFNGLCLAMPCOLORARBPROC)(GLenum target, GLenum clamp); +typedef void (GLAD_API_PTR *PFNGLCLEARPROC)(GLbitfield mask); +typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERFIPROC)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERFVPROC)(GLenum buffer, GLint drawbuffer, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERIVPROC)(GLenum buffer, GLint drawbuffer, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERUIVPROC)(GLenum buffer, GLint drawbuffer, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLCLEARCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (GLAD_API_PTR *PFNGLCLEARCOLORIIEXTPROC)(GLint red, GLint green, GLint blue, GLint alpha); +typedef void (GLAD_API_PTR *PFNGLCLEARCOLORIUIEXTPROC)(GLuint red, GLuint green, GLuint blue, GLuint alpha); +typedef void (GLAD_API_PTR *PFNGLCLEARDEPTHPROC)(GLdouble depth); +typedef void (GLAD_API_PTR *PFNGLCLEARNAMEDBUFFERDATAEXTPROC)(GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void * data); +typedef void (GLAD_API_PTR *PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC)(GLuint buffer, GLenum internalformat, GLsizeiptr offset, GLsizeiptr size, GLenum format, GLenum type, const void * data); +typedef void (GLAD_API_PTR *PFNGLCLEARSTENCILPROC)(GLint s); +typedef void (GLAD_API_PTR *PFNGLCLIENTACTIVETEXTUREARBPROC)(GLenum texture); +typedef void (GLAD_API_PTR *PFNGLCLIENTATTRIBDEFAULTEXTPROC)(GLbitfield mask); +typedef GLenum (GLAD_API_PTR *PFNGLCLIENTWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (GLAD_API_PTR *PFNGLCOLORMASKPROC)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +typedef void (GLAD_API_PTR *PFNGLCOLORMASKINDEXEDEXTPROC)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +typedef void (GLAD_API_PTR *PFNGLCOLORMASKIPROC)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +typedef void (GLAD_API_PTR *PFNGLCOLORPOINTEREXTPROC)(GLint size, GLenum type, GLsizei stride, GLsizei count, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLCOMPILESHADERPROC)(GLuint shader); +typedef void (GLAD_API_PTR *PFNGLCOMPILESHADERARBPROC)(GLhandleARB shaderObj); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE1DARBPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE2DARBPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE3DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE3DARBPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC)(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC)(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC)(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOPYBUFFERSUBDATAPROC)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +typedef void (GLAD_API_PTR *PFNGLCOPYMULTITEXIMAGE1DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (GLAD_API_PTR *PFNGLCOPYMULTITEXIMAGE2DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAD_API_PTR *PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAD_API_PTR *PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE1DEXTPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE2DEXTPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE1DEXTPROC)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE2DEXTPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE3DEXTPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXTUREIMAGE1DEXTPROC)(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXTUREIMAGE2DEXTPROC)(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef GLuint (GLAD_API_PTR *PFNGLCREATEPROGRAMPROC)(void); +typedef GLhandleARB (GLAD_API_PTR *PFNGLCREATEPROGRAMOBJECTARBPROC)(void); +typedef GLuint (GLAD_API_PTR *PFNGLCREATESHADERPROC)(GLenum type); +typedef GLhandleARB (GLAD_API_PTR *PFNGLCREATESHADEROBJECTARBPROC)(GLenum shaderType); +typedef void (GLAD_API_PTR *PFNGLCULLFACEPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLDELETEBUFFERSPROC)(GLsizei n, const GLuint * buffers); +typedef void (GLAD_API_PTR *PFNGLDELETEBUFFERSARBPROC)(GLsizei n, const GLuint * buffers); +typedef void (GLAD_API_PTR *PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei n, const GLuint * framebuffers); +typedef void (GLAD_API_PTR *PFNGLDELETEFRAMEBUFFERSEXTPROC)(GLsizei n, const GLuint * framebuffers); +typedef void (GLAD_API_PTR *PFNGLDELETEOBJECTARBPROC)(GLhandleARB obj); +typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMPROC)(GLuint program); +typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMSARBPROC)(GLsizei n, const GLuint * programs); +typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMSNVPROC)(GLsizei n, const GLuint * programs); +typedef void (GLAD_API_PTR *PFNGLDELETEQUERIESPROC)(GLsizei n, const GLuint * ids); +typedef void (GLAD_API_PTR *PFNGLDELETEQUERIESARBPROC)(GLsizei n, const GLuint * ids); +typedef void (GLAD_API_PTR *PFNGLDELETERENDERBUFFERSPROC)(GLsizei n, const GLuint * renderbuffers); +typedef void (GLAD_API_PTR *PFNGLDELETERENDERBUFFERSEXTPROC)(GLsizei n, const GLuint * renderbuffers); +typedef void (GLAD_API_PTR *PFNGLDELETESHADERPROC)(GLuint shader); +typedef void (GLAD_API_PTR *PFNGLDELETESYNCPROC)(GLsync sync); +typedef void (GLAD_API_PTR *PFNGLDELETETEXTURESPROC)(GLsizei n, const GLuint * textures); +typedef void (GLAD_API_PTR *PFNGLDELETETEXTURESEXTPROC)(GLsizei n, const GLuint * textures); +typedef void (GLAD_API_PTR *PFNGLDELETEVERTEXARRAYSPROC)(GLsizei n, const GLuint * arrays); +typedef void (GLAD_API_PTR *PFNGLDELETEVERTEXARRAYSAPPLEPROC)(GLsizei n, const GLuint * arrays); +typedef void (GLAD_API_PTR *PFNGLDEPTHFUNCPROC)(GLenum func); +typedef void (GLAD_API_PTR *PFNGLDEPTHMASKPROC)(GLboolean flag); +typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEPROC)(GLdouble n, GLdouble f); +typedef void (GLAD_API_PTR *PFNGLDETACHOBJECTARBPROC)(GLhandleARB containerObj, GLhandleARB attachedObj); +typedef void (GLAD_API_PTR *PFNGLDETACHSHADERPROC)(GLuint program, GLuint shader); +typedef void (GLAD_API_PTR *PFNGLDISABLEPROC)(GLenum cap); +typedef void (GLAD_API_PTR *PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC)(GLenum array, GLuint index); +typedef void (GLAD_API_PTR *PFNGLDISABLECLIENTSTATEIEXTPROC)(GLenum array, GLuint index); +typedef void (GLAD_API_PTR *PFNGLDISABLEINDEXEDEXTPROC)(GLenum target, GLuint index); +typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC)(GLuint vaobj, GLuint index); +typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXARRAYEXTPROC)(GLuint vaobj, GLenum array); +typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint index); +typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXATTRIBARRAYARBPROC)(GLuint index); +typedef void (GLAD_API_PTR *PFNGLDISABLEIPROC)(GLenum target, GLuint index); +typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSPROC)(GLenum mode, GLint first, GLsizei count); +typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSEXTPROC)(GLenum mode, GLint first, GLsizei count); +typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount); +typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDARBPROC)(GLenum mode, GLint first, GLsizei count, GLsizei primcount); +typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDEXTPROC)(GLenum mode, GLint start, GLsizei count, GLsizei primcount); +typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERPROC)(GLenum buf); +typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERSPROC)(GLsizei n, const GLenum * bufs); +typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERSARBPROC)(GLsizei n, const GLenum * bufs); +typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERSATIPROC)(GLsizei n, const GLenum * bufs); +typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices); +typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLint basevertex); +typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount); +typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDARBPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount); +typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex); +typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDEXTPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount); +typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices); +typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices, GLint basevertex); +typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSEXTPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices); +typedef void (GLAD_API_PTR *PFNGLEDGEFLAGPOINTEREXTPROC)(GLsizei stride, GLsizei count, const GLboolean * pointer); +typedef void (GLAD_API_PTR *PFNGLENABLEPROC)(GLenum cap); +typedef void (GLAD_API_PTR *PFNGLENABLECLIENTSTATEINDEXEDEXTPROC)(GLenum array, GLuint index); +typedef void (GLAD_API_PTR *PFNGLENABLECLIENTSTATEIEXTPROC)(GLenum array, GLuint index); +typedef void (GLAD_API_PTR *PFNGLENABLEINDEXEDEXTPROC)(GLenum target, GLuint index); +typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXARRAYATTRIBEXTPROC)(GLuint vaobj, GLuint index); +typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXARRAYEXTPROC)(GLuint vaobj, GLenum array); +typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint index); +typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXATTRIBARRAYARBPROC)(GLuint index); +typedef void (GLAD_API_PTR *PFNGLENABLEIPROC)(GLenum target, GLuint index); +typedef void (GLAD_API_PTR *PFNGLENDCONDITIONALRENDERPROC)(void); +typedef void (GLAD_API_PTR *PFNGLENDCONDITIONALRENDERNVPROC)(void); +typedef void (GLAD_API_PTR *PFNGLENDCONDITIONALRENDERNVXPROC)(void); +typedef void (GLAD_API_PTR *PFNGLENDQUERYPROC)(GLenum target); +typedef void (GLAD_API_PTR *PFNGLENDQUERYARBPROC)(GLenum target); +typedef void (GLAD_API_PTR *PFNGLENDTRANSFORMFEEDBACKPROC)(void); +typedef void (GLAD_API_PTR *PFNGLENDTRANSFORMFEEDBACKEXTPROC)(void); +typedef void (GLAD_API_PTR *PFNGLENDTRANSFORMFEEDBACKNVPROC)(void); +typedef void (GLAD_API_PTR *PFNGLEXECUTEPROGRAMNVPROC)(GLenum target, GLuint id, const GLfloat * params); +typedef GLsync (GLAD_API_PTR *PFNGLFENCESYNCPROC)(GLenum condition, GLbitfield flags); +typedef void (GLAD_API_PTR *PFNGLFINISHPROC)(void); +typedef void (GLAD_API_PTR *PFNGLFLUSHPROC)(void); +typedef void (GLAD_API_PTR *PFNGLFLUSHMAPPEDBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length); +typedef void (GLAD_API_PTR *PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC)(GLenum target, GLintptr offset, GLsizeiptr size); +typedef void (GLAD_API_PTR *PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC)(GLuint buffer, GLintptr offset, GLsizeiptr length); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC)(GLuint framebuffer, GLenum mode); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC)(GLuint framebuffer, GLsizei n, const GLenum * bufs); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERREADBUFFEREXTPROC)(GLuint framebuffer, GLenum mode); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE1DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE3DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREARBPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREEXTPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREFACEARBPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURELAYERPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURELAYERARBPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (GLAD_API_PTR *PFNGLFRONTFACEPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLGENBUFFERSPROC)(GLsizei n, GLuint * buffers); +typedef void (GLAD_API_PTR *PFNGLGENBUFFERSARBPROC)(GLsizei n, GLuint * buffers); +typedef void (GLAD_API_PTR *PFNGLGENFRAMEBUFFERSPROC)(GLsizei n, GLuint * framebuffers); +typedef void (GLAD_API_PTR *PFNGLGENFRAMEBUFFERSEXTPROC)(GLsizei n, GLuint * framebuffers); +typedef void (GLAD_API_PTR *PFNGLGENPROGRAMSARBPROC)(GLsizei n, GLuint * programs); +typedef void (GLAD_API_PTR *PFNGLGENPROGRAMSNVPROC)(GLsizei n, GLuint * programs); +typedef void (GLAD_API_PTR *PFNGLGENQUERIESPROC)(GLsizei n, GLuint * ids); +typedef void (GLAD_API_PTR *PFNGLGENQUERIESARBPROC)(GLsizei n, GLuint * ids); +typedef void (GLAD_API_PTR *PFNGLGENRENDERBUFFERSPROC)(GLsizei n, GLuint * renderbuffers); +typedef void (GLAD_API_PTR *PFNGLGENRENDERBUFFERSEXTPROC)(GLsizei n, GLuint * renderbuffers); +typedef void (GLAD_API_PTR *PFNGLGENTEXTURESPROC)(GLsizei n, GLuint * textures); +typedef void (GLAD_API_PTR *PFNGLGENTEXTURESEXTPROC)(GLsizei n, GLuint * textures); +typedef void (GLAD_API_PTR *PFNGLGENVERTEXARRAYSPROC)(GLsizei n, GLuint * arrays); +typedef void (GLAD_API_PTR *PFNGLGENVERTEXARRAYSAPPLEPROC)(GLsizei n, GLuint * arrays); +typedef void (GLAD_API_PTR *PFNGLGENERATEMIPMAPPROC)(GLenum target); +typedef void (GLAD_API_PTR *PFNGLGENERATEMIPMAPEXTPROC)(GLenum target); +typedef void (GLAD_API_PTR *PFNGLGENERATEMULTITEXMIPMAPEXTPROC)(GLenum texunit, GLenum target); +typedef void (GLAD_API_PTR *PFNGLGENERATETEXTUREMIPMAPEXTPROC)(GLuint texture, GLenum target); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEATTRIBPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEATTRIBARBPROC)(GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei * length, GLint * size, GLenum * type, GLcharARB * name); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMARBPROC)(GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei * length, GLint * size, GLenum * type, GLcharARB * name); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformBlockName); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMBLOCKIVPROC)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMNAMEPROC)(GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformName); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMSIVPROC)(GLuint program, GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEVARYINGNVPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETATTACHEDOBJECTSARBPROC)(GLhandleARB containerObj, GLsizei maxCount, GLsizei * count, GLhandleARB * obj); +typedef void (GLAD_API_PTR *PFNGLGETATTACHEDSHADERSPROC)(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders); +typedef GLint (GLAD_API_PTR *PFNGLGETATTRIBLOCATIONPROC)(GLuint program, const GLchar * name); +typedef GLint (GLAD_API_PTR *PFNGLGETATTRIBLOCATIONARBPROC)(GLhandleARB programObj, const GLcharARB * name); +typedef void (GLAD_API_PTR *PFNGLGETBOOLEANINDEXEDVEXTPROC)(GLenum target, GLuint index, GLboolean * data); +typedef void (GLAD_API_PTR *PFNGLGETBOOLEANI_VPROC)(GLenum target, GLuint index, GLboolean * data); +typedef void (GLAD_API_PTR *PFNGLGETBOOLEANVPROC)(GLenum pname, GLboolean * data); +typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERI64VPROC)(GLenum target, GLenum pname, GLint64 * params); +typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERIVARBPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETBUFFERPOINTERVPROC)(GLenum target, GLenum pname, void ** params); +typedef void (GLAD_API_PTR *PFNGLGETBUFFERPOINTERVARBPROC)(GLenum target, GLenum pname, void ** params); +typedef void (GLAD_API_PTR *PFNGLGETBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, void * data); +typedef void (GLAD_API_PTR *PFNGLGETBUFFERSUBDATAARBPROC)(GLenum target, GLintptrARB offset, GLsizeiptrARB size, void * data); +typedef void (GLAD_API_PTR *PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC)(GLenum texunit, GLenum target, GLint lod, void * img); +typedef void (GLAD_API_PTR *PFNGLGETCOMPRESSEDTEXIMAGEPROC)(GLenum target, GLint level, void * img); +typedef void (GLAD_API_PTR *PFNGLGETCOMPRESSEDTEXIMAGEARBPROC)(GLenum target, GLint level, void * img); +typedef void (GLAD_API_PTR *PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC)(GLuint texture, GLenum target, GLint lod, void * img); +typedef void (GLAD_API_PTR *PFNGLGETDOUBLEINDEXEDVEXTPROC)(GLenum target, GLuint index, GLdouble * data); +typedef void (GLAD_API_PTR *PFNGLGETDOUBLEI_VEXTPROC)(GLenum pname, GLuint index, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETDOUBLEVPROC)(GLenum pname, GLdouble * data); +typedef GLenum (GLAD_API_PTR *PFNGLGETERRORPROC)(void); +typedef void (GLAD_API_PTR *PFNGLGETFLOATINDEXEDVEXTPROC)(GLenum target, GLuint index, GLfloat * data); +typedef void (GLAD_API_PTR *PFNGLGETFLOATI_VEXTPROC)(GLenum pname, GLuint index, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETFLOATVPROC)(GLenum pname, GLfloat * data); +typedef GLint (GLAD_API_PTR *PFNGLGETFRAGDATALOCATIONPROC)(GLuint program, const GLchar * name); +typedef GLint (GLAD_API_PTR *PFNGLGETFRAGDATALOCATIONEXTPROC)(GLuint program, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum target, GLenum attachment, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)(GLenum target, GLenum attachment, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC)(GLuint framebuffer, GLenum pname, GLint * params); +typedef GLhandleARB (GLAD_API_PTR *PFNGLGETHANDLEARBPROC)(GLenum pname); +typedef void (GLAD_API_PTR *PFNGLGETINFOLOGARBPROC)(GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog); +typedef void (GLAD_API_PTR *PFNGLGETINTEGER64I_VPROC)(GLenum target, GLuint index, GLint64 * data); +typedef void (GLAD_API_PTR *PFNGLGETINTEGER64VPROC)(GLenum pname, GLint64 * data); +typedef void (GLAD_API_PTR *PFNGLGETINTEGERINDEXEDVEXTPROC)(GLenum target, GLuint index, GLint * data); +typedef void (GLAD_API_PTR *PFNGLGETINTEGERI_VPROC)(GLenum target, GLuint index, GLint * data); +typedef void (GLAD_API_PTR *PFNGLGETINTEGERVPROC)(GLenum pname, GLint * data); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXENVFVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXENVIVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXGENDVEXTPROC)(GLenum texunit, GLenum coord, GLenum pname, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXGENFVEXTPROC)(GLenum texunit, GLenum coord, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXGENIVEXTPROC)(GLenum texunit, GLenum coord, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXIMAGEEXTPROC)(GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, void * pixels); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC)(GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC)(GLenum texunit, GLenum target, GLint level, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXPARAMETERIIVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXPARAMETERIUIVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXPARAMETERFVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXPARAMETERIVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTISAMPLEFVPROC)(GLenum pname, GLuint index, GLfloat * val); +typedef void (GLAD_API_PTR *PFNGLGETMULTISAMPLEFVNVPROC)(GLenum pname, GLuint index, GLfloat * val); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC)(GLuint buffer, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDBUFFERPOINTERVEXTPROC)(GLuint buffer, GLenum pname, void ** params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDBUFFERSUBDATAEXTPROC)(GLuint buffer, GLintptr offset, GLsizeiptr size, void * data); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)(GLuint framebuffer, GLenum attachment, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC)(GLuint framebuffer, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC)(GLuint program, GLenum target, GLuint index, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC)(GLuint program, GLenum target, GLuint index, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC)(GLuint program, GLenum target, GLuint index, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC)(GLuint program, GLenum target, GLuint index, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDPROGRAMSTRINGEXTPROC)(GLuint program, GLenum target, GLenum pname, void * string); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDPROGRAMIVEXTPROC)(GLuint program, GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC)(GLuint renderbuffer, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETOBJECTPARAMETERFVARBPROC)(GLhandleARB obj, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETOBJECTPARAMETERIVARBPROC)(GLhandleARB obj, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETPOINTERINDEXEDVEXTPROC)(GLenum target, GLuint index, void ** data); +typedef void (GLAD_API_PTR *PFNGLGETPOINTERI_VEXTPROC)(GLenum pname, GLuint index, void ** params); +typedef void (GLAD_API_PTR *PFNGLGETPOINTERVEXTPROC)(GLenum pname, void ** params); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMENVPARAMETERDVARBPROC)(GLenum target, GLuint index, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMENVPARAMETERFVARBPROC)(GLenum target, GLuint index, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMINFOLOGPROC)(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC)(GLenum target, GLuint index, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC)(GLenum target, GLuint index, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMPARAMETERDVNVPROC)(GLenum target, GLuint index, GLenum pname, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMPARAMETERFVNVPROC)(GLenum target, GLuint index, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMSTRINGARBPROC)(GLenum target, GLenum pname, void * string); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMSTRINGNVPROC)(GLuint id, GLenum pname, GLubyte * program); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMIVPROC)(GLuint program, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMIVARBPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMIVNVPROC)(GLuint id, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTIVPROC)(GLuint id, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTIVARBPROC)(GLuint id, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUIVPROC)(GLuint id, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUIVARBPROC)(GLuint id, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETQUERYIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETQUERYIVARBPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog); +typedef void (GLAD_API_PTR *PFNGLGETSHADERSOURCEPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source); +typedef void (GLAD_API_PTR *PFNGLGETSHADERSOURCEARBPROC)(GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * source); +typedef void (GLAD_API_PTR *PFNGLGETSHADERIVPROC)(GLuint shader, GLenum pname, GLint * params); +typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGPROC)(GLenum name); +typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGIPROC)(GLenum name, GLuint index); +typedef void (GLAD_API_PTR *PFNGLGETSYNCIVPROC)(GLsync sync, GLenum pname, GLsizei count, GLsizei * length, GLint * values); +typedef void (GLAD_API_PTR *PFNGLGETTEXIMAGEPROC)(GLenum target, GLint level, GLenum format, GLenum type, void * pixels); +typedef void (GLAD_API_PTR *PFNGLGETTEXLEVELPARAMETERFVPROC)(GLenum target, GLint level, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXLEVELPARAMETERIVPROC)(GLenum target, GLint level, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIIVEXTPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIUIVEXTPROC)(GLenum target, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERFVPROC)(GLenum target, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXTUREIMAGEEXTPROC)(GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void * pixels); +typedef void (GLAD_API_PTR *PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC)(GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC)(GLuint texture, GLenum target, GLint level, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXTUREPARAMETERIIVEXTPROC)(GLuint texture, GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXTUREPARAMETERIUIVEXTPROC)(GLuint texture, GLenum target, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXTUREPARAMETERFVEXTPROC)(GLuint texture, GLenum target, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXTUREPARAMETERIVEXTPROC)(GLuint texture, GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTRACKMATRIXIVNVPROC)(GLenum target, GLuint address, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC)(GLuint program, GLuint index, GLint * location); +typedef GLuint (GLAD_API_PTR *PFNGLGETUNIFORMBLOCKINDEXPROC)(GLuint program, const GLchar * uniformBlockName); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMINDICESPROC)(GLuint program, GLsizei uniformCount, const GLchar *const* uniformNames, GLuint * uniformIndices); +typedef GLint (GLAD_API_PTR *PFNGLGETUNIFORMLOCATIONPROC)(GLuint program, const GLchar * name); +typedef GLint (GLAD_API_PTR *PFNGLGETUNIFORMLOCATIONARBPROC)(GLhandleARB programObj, const GLcharARB * name); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMFVPROC)(GLuint program, GLint location, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMFVARBPROC)(GLhandleARB programObj, GLint location, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMIVPROC)(GLuint program, GLint location, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMIVARBPROC)(GLhandleARB programObj, GLint location, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMUIVPROC)(GLuint program, GLint location, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMUIVEXTPROC)(GLuint program, GLint location, GLuint * params); +typedef GLint (GLAD_API_PTR *PFNGLGETVARYINGLOCATIONNVPROC)(GLuint program, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC)(GLuint vaobj, GLuint index, GLenum pname, GLint * param); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXARRAYINTEGERVEXTPROC)(GLuint vaobj, GLenum pname, GLint * param); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC)(GLuint vaobj, GLuint index, GLenum pname, void ** param); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXARRAYPOINTERVEXTPROC)(GLuint vaobj, GLenum pname, void ** param); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIIVPROC)(GLuint index, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIIVEXTPROC)(GLuint index, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIUIVPROC)(GLuint index, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIUIVEXTPROC)(GLuint index, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint index, GLenum pname, void ** pointer); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBPOINTERVARBPROC)(GLuint index, GLenum pname, void ** pointer); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBPOINTERVNVPROC)(GLuint index, GLenum pname, void ** pointer); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBDVPROC)(GLuint index, GLenum pname, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBDVARBPROC)(GLuint index, GLenum pname, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBDVNVPROC)(GLuint index, GLenum pname, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBFVPROC)(GLuint index, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBFVARBPROC)(GLuint index, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBFVNVPROC)(GLuint index, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIVPROC)(GLuint index, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIVARBPROC)(GLuint index, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIVNVPROC)(GLuint index, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLHINTPROC)(GLenum target, GLenum mode); +typedef void (GLAD_API_PTR *PFNGLINDEXPOINTEREXTPROC)(GLenum type, GLsizei stride, GLsizei count, const void * pointer); +typedef GLboolean (GLAD_API_PTR *PFNGLISBUFFERPROC)(GLuint buffer); +typedef GLboolean (GLAD_API_PTR *PFNGLISBUFFERARBPROC)(GLuint buffer); +typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDPROC)(GLenum cap); +typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDINDEXEDEXTPROC)(GLenum target, GLuint index); +typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDIPROC)(GLenum target, GLuint index); +typedef GLboolean (GLAD_API_PTR *PFNGLISFRAMEBUFFERPROC)(GLuint framebuffer); +typedef GLboolean (GLAD_API_PTR *PFNGLISFRAMEBUFFEREXTPROC)(GLuint framebuffer); +typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMPROC)(GLuint program); +typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMARBPROC)(GLuint program); +typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMNVPROC)(GLuint id); +typedef GLboolean (GLAD_API_PTR *PFNGLISQUERYPROC)(GLuint id); +typedef GLboolean (GLAD_API_PTR *PFNGLISQUERYARBPROC)(GLuint id); +typedef GLboolean (GLAD_API_PTR *PFNGLISRENDERBUFFERPROC)(GLuint renderbuffer); +typedef GLboolean (GLAD_API_PTR *PFNGLISRENDERBUFFEREXTPROC)(GLuint renderbuffer); +typedef GLboolean (GLAD_API_PTR *PFNGLISSHADERPROC)(GLuint shader); +typedef GLboolean (GLAD_API_PTR *PFNGLISSYNCPROC)(GLsync sync); +typedef GLboolean (GLAD_API_PTR *PFNGLISTEXTUREPROC)(GLuint texture); +typedef GLboolean (GLAD_API_PTR *PFNGLISTEXTUREEXTPROC)(GLuint texture); +typedef GLboolean (GLAD_API_PTR *PFNGLISVERTEXARRAYPROC)(GLuint array); +typedef GLboolean (GLAD_API_PTR *PFNGLISVERTEXARRAYAPPLEPROC)(GLuint array); +typedef void (GLAD_API_PTR *PFNGLLINEWIDTHPROC)(GLfloat width); +typedef void (GLAD_API_PTR *PFNGLLINKPROGRAMPROC)(GLuint program); +typedef void (GLAD_API_PTR *PFNGLLINKPROGRAMARBPROC)(GLhandleARB programObj); +typedef void (GLAD_API_PTR *PFNGLLOADPROGRAMNVPROC)(GLenum target, GLuint id, GLsizei len, const GLubyte * program); +typedef void (GLAD_API_PTR *PFNGLLOGICOPPROC)(GLenum opcode); +typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERPROC)(GLenum target, GLenum access); +typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERARBPROC)(GLenum target, GLenum access); +typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void * (GLAD_API_PTR *PFNGLMAPNAMEDBUFFEREXTPROC)(GLuint buffer, GLenum access); +typedef void * (GLAD_API_PTR *PFNGLMAPNAMEDBUFFERRANGEEXTPROC)(GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (GLAD_API_PTR *PFNGLMATRIXFRUSTUMEXTPROC)(GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +typedef void (GLAD_API_PTR *PFNGLMATRIXLOADIDENTITYEXTPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLMATRIXLOADTRANSPOSEDEXTPROC)(GLenum mode, const GLdouble * m); +typedef void (GLAD_API_PTR *PFNGLMATRIXLOADTRANSPOSEFEXTPROC)(GLenum mode, const GLfloat * m); +typedef void (GLAD_API_PTR *PFNGLMATRIXLOADDEXTPROC)(GLenum mode, const GLdouble * m); +typedef void (GLAD_API_PTR *PFNGLMATRIXLOADFEXTPROC)(GLenum mode, const GLfloat * m); +typedef void (GLAD_API_PTR *PFNGLMATRIXMULTTRANSPOSEDEXTPROC)(GLenum mode, const GLdouble * m); +typedef void (GLAD_API_PTR *PFNGLMATRIXMULTTRANSPOSEFEXTPROC)(GLenum mode, const GLfloat * m); +typedef void (GLAD_API_PTR *PFNGLMATRIXMULTDEXTPROC)(GLenum mode, const GLdouble * m); +typedef void (GLAD_API_PTR *PFNGLMATRIXMULTFEXTPROC)(GLenum mode, const GLfloat * m); +typedef void (GLAD_API_PTR *PFNGLMATRIXORTHOEXTPROC)(GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +typedef void (GLAD_API_PTR *PFNGLMATRIXPOPEXTPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLMATRIXPUSHEXTPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLMATRIXROTATEDEXTPROC)(GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLMATRIXROTATEFEXTPROC)(GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAD_API_PTR *PFNGLMATRIXSCALEDEXTPROC)(GLenum mode, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLMATRIXSCALEFEXTPROC)(GLenum mode, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAD_API_PTR *PFNGLMATRIXTRANSLATEDEXTPROC)(GLenum mode, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLMATRIXTRANSLATEFEXTPROC)(GLenum mode, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAD_API_PTR *PFNGLMULTIDRAWARRAYSPROC)(GLenum mode, const GLint * first, const GLsizei * count, GLsizei drawcount); +typedef void (GLAD_API_PTR *PFNGLMULTIDRAWARRAYSEXTPROC)(GLenum mode, const GLint * first, const GLsizei * count, GLsizei primcount); +typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSPROC)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount); +typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount, const GLint * basevertex); +typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSEXTPROC)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei primcount); +typedef void (GLAD_API_PTR *PFNGLMULTITEXBUFFEREXTPROC)(GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1DARBPROC)(GLenum target, GLdouble s); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1DVARBPROC)(GLenum target, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1FARBPROC)(GLenum target, GLfloat s); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1FVARBPROC)(GLenum target, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1IARBPROC)(GLenum target, GLint s); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1IVARBPROC)(GLenum target, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1SARBPROC)(GLenum target, GLshort s); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1SVARBPROC)(GLenum target, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2DARBPROC)(GLenum target, GLdouble s, GLdouble t); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2DVARBPROC)(GLenum target, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2FARBPROC)(GLenum target, GLfloat s, GLfloat t); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2FVARBPROC)(GLenum target, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2IARBPROC)(GLenum target, GLint s, GLint t); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2IVARBPROC)(GLenum target, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2SARBPROC)(GLenum target, GLshort s, GLshort t); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2SVARBPROC)(GLenum target, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3DARBPROC)(GLenum target, GLdouble s, GLdouble t, GLdouble r); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3DVARBPROC)(GLenum target, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3FARBPROC)(GLenum target, GLfloat s, GLfloat t, GLfloat r); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3FVARBPROC)(GLenum target, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3IARBPROC)(GLenum target, GLint s, GLint t, GLint r); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3IVARBPROC)(GLenum target, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3SARBPROC)(GLenum target, GLshort s, GLshort t, GLshort r); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3SVARBPROC)(GLenum target, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4DARBPROC)(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4DVARBPROC)(GLenum target, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4FARBPROC)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4FVARBPROC)(GLenum target, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4IARBPROC)(GLenum target, GLint s, GLint t, GLint r, GLint q); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4IVARBPROC)(GLenum target, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4SARBPROC)(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4SVARBPROC)(GLenum target, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDPOINTEREXTPROC)(GLenum texunit, GLint size, GLenum type, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLMULTITEXENVFEXTPROC)(GLenum texunit, GLenum target, GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLMULTITEXENVFVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLMULTITEXENVIEXTPROC)(GLenum texunit, GLenum target, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLMULTITEXENVIVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLMULTITEXGENDEXTPROC)(GLenum texunit, GLenum coord, GLenum pname, GLdouble param); +typedef void (GLAD_API_PTR *PFNGLMULTITEXGENDVEXTPROC)(GLenum texunit, GLenum coord, GLenum pname, const GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLMULTITEXGENFEXTPROC)(GLenum texunit, GLenum coord, GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLMULTITEXGENFVEXTPROC)(GLenum texunit, GLenum coord, GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLMULTITEXGENIEXTPROC)(GLenum texunit, GLenum coord, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLMULTITEXGENIVEXTPROC)(GLenum texunit, GLenum coord, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLMULTITEXIMAGE1DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLMULTITEXIMAGE2DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLMULTITEXIMAGE3DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLMULTITEXPARAMETERIIVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLMULTITEXPARAMETERIUIVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, const GLuint * params); +typedef void (GLAD_API_PTR *PFNGLMULTITEXPARAMETERFEXTPROC)(GLenum texunit, GLenum target, GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLMULTITEXPARAMETERFVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLMULTITEXPARAMETERIEXTPROC)(GLenum texunit, GLenum target, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLMULTITEXPARAMETERIVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLMULTITEXRENDERBUFFEREXTPROC)(GLenum texunit, GLenum target, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLMULTITEXSUBIMAGE1DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLMULTITEXSUBIMAGE2DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLMULTITEXSUBIMAGE3DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLNAMEDBUFFERDATAEXTPROC)(GLuint buffer, GLsizeiptr size, const void * data, GLenum usage); +typedef void (GLAD_API_PTR *PFNGLNAMEDBUFFERSTORAGEEXTPROC)(GLuint buffer, GLsizeiptr size, const void * data, GLbitfield flags); +typedef void (GLAD_API_PTR *PFNGLNAMEDBUFFERSUBDATAEXTPROC)(GLuint buffer, GLintptr offset, GLsizeiptr size, const void * data); +typedef void (GLAD_API_PTR *PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC)(GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC)(GLuint framebuffer, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC)(GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC)(GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC)(GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC)(GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC)(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC)(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC)(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC)(GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC)(GLuint program, GLenum target, GLuint index, const GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC)(GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC)(GLuint program, GLenum target, GLuint index, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC)(GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC)(GLuint program, GLenum target, GLuint index, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC)(GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC)(GLuint program, GLenum target, GLuint index, const GLuint * params); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC)(GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC)(GLuint program, GLenum target, GLuint index, GLsizei count, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC)(GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint * params); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMSTRINGEXTPROC)(GLuint program, GLenum target, GLenum format, GLsizei len, const void * string); +typedef void (GLAD_API_PTR *PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC)(GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC)(GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)(GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLNORMALPOINTEREXTPROC)(GLenum type, GLsizei stride, GLsizei count, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLPIXELSTOREFPROC)(GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLPIXELSTOREIPROC)(GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFPROC)(GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFARBPROC)(GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFEXTPROC)(GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFSGISPROC)(GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFVPROC)(GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFVARBPROC)(GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFVEXTPROC)(GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFVSGISPROC)(GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERIPROC)(GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERINVPROC)(GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERIVPROC)(GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERIVNVPROC)(GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLPOINTSIZEPROC)(GLfloat size); +typedef void (GLAD_API_PTR *PFNGLPOLYGONMODEPROC)(GLenum face, GLenum mode); +typedef void (GLAD_API_PTR *PFNGLPOLYGONOFFSETPROC)(GLfloat factor, GLfloat units); +typedef void (GLAD_API_PTR *PFNGLPRIMITIVERESTARTINDEXPROC)(GLuint index); +typedef void (GLAD_API_PTR *PFNGLPRIORITIZETEXTURESEXTPROC)(GLsizei n, const GLuint * textures, const GLclampf * priorities); +typedef void (GLAD_API_PTR *PFNGLPROGRAMENVPARAMETER4DARBPROC)(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAD_API_PTR *PFNGLPROGRAMENVPARAMETER4DVARBPROC)(GLenum target, GLuint index, const GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLPROGRAMENVPARAMETER4FARBPROC)(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAD_API_PTR *PFNGLPROGRAMENVPARAMETER4FVARBPROC)(GLenum target, GLuint index, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLPROGRAMLOCALPARAMETER4DARBPROC)(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAD_API_PTR *PFNGLPROGRAMLOCALPARAMETER4DVARBPROC)(GLenum target, GLuint index, const GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLPROGRAMLOCALPARAMETER4FARBPROC)(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAD_API_PTR *PFNGLPROGRAMLOCALPARAMETER4FVARBPROC)(GLenum target, GLuint index, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLPROGRAMPARAMETER4DNVPROC)(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAD_API_PTR *PFNGLPROGRAMPARAMETER4DVNVPROC)(GLenum target, GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLPROGRAMPARAMETER4FNVPROC)(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAD_API_PTR *PFNGLPROGRAMPARAMETER4FVNVPROC)(GLenum target, GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLPROGRAMPARAMETERIARBPROC)(GLuint program, GLenum pname, GLint value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMPARAMETERS4DVNVPROC)(GLenum target, GLuint index, GLsizei count, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLPROGRAMPARAMETERS4FVNVPROC)(GLenum target, GLuint index, GLsizei count, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLPROGRAMSTRINGARBPROC)(GLenum target, GLenum format, GLsizei len, const void * string); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1DEXTPROC)(GLuint program, GLint location, GLdouble x); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1DVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1FEXTPROC)(GLuint program, GLint location, GLfloat v0); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1FVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1IEXTPROC)(GLuint program, GLint location, GLint v0); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1IVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1UIEXTPROC)(GLuint program, GLint location, GLuint v0); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1UIVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2DEXTPROC)(GLuint program, GLint location, GLdouble x, GLdouble y); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2DVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2FEXTPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2FVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2IEXTPROC)(GLuint program, GLint location, GLint v0, GLint v1); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2IVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2UIEXTPROC)(GLuint program, GLint location, GLuint v0, GLuint v1); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2UIVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3DEXTPROC)(GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3DVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3FEXTPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3FVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3IEXTPROC)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3IVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3UIEXTPROC)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3UIVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4DEXTPROC)(GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4DVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4FEXTPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4FVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4IEXTPROC)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4IVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4UIEXTPROC)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4UIVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMVERTEXLIMITNVPROC)(GLenum target, GLint limit); +typedef void (GLAD_API_PTR *PFNGLPROVOKINGVERTEXPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLPROVOKINGVERTEXEXTPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC)(GLbitfield mask); +typedef void (GLAD_API_PTR *PFNGLREADBUFFERPROC)(GLenum src); +typedef void (GLAD_API_PTR *PFNGLREADPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels); +typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEEXTPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLREQUESTRESIDENTPROGRAMSNVPROC)(GLsizei n, const GLuint * programs); +typedef void (GLAD_API_PTR *PFNGLSAMPLECOVERAGEPROC)(GLfloat value, GLboolean invert); +typedef void (GLAD_API_PTR *PFNGLSAMPLECOVERAGEARBPROC)(GLfloat value, GLboolean invert); +typedef void (GLAD_API_PTR *PFNGLSAMPLEMASKINDEXEDNVPROC)(GLuint index, GLbitfield mask); +typedef void (GLAD_API_PTR *PFNGLSAMPLEMASKIPROC)(GLuint maskNumber, GLbitfield mask); +typedef void (GLAD_API_PTR *PFNGLSCISSORPROC)(GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLSHADERSOURCEPROC)(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length); +typedef void (GLAD_API_PTR *PFNGLSHADERSOURCEARBPROC)(GLhandleARB shaderObj, GLsizei count, const GLcharARB ** string, const GLint * length); +typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCPROC)(GLenum func, GLint ref, GLuint mask); +typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCSEPARATEPROC)(GLenum face, GLenum func, GLint ref, GLuint mask); +typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCSEPARATEATIPROC)(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); +typedef void (GLAD_API_PTR *PFNGLSTENCILMASKPROC)(GLuint mask); +typedef void (GLAD_API_PTR *PFNGLSTENCILMASKSEPARATEPROC)(GLenum face, GLuint mask); +typedef void (GLAD_API_PTR *PFNGLSTENCILOPPROC)(GLenum fail, GLenum zfail, GLenum zpass); +typedef void (GLAD_API_PTR *PFNGLSTENCILOPSEPARATEPROC)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +typedef void (GLAD_API_PTR *PFNGLSTENCILOPSEPARATEATIPROC)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +typedef void (GLAD_API_PTR *PFNGLTEXBUFFERPROC)(GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLTEXBUFFERARBPROC)(GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLTEXBUFFEREXTPROC)(GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLTEXCOORDPOINTEREXTPROC)(GLint size, GLenum type, GLsizei stride, GLsizei count, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLTEXIMAGE1DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXIMAGE2DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXIMAGE2DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (GLAD_API_PTR *PFNGLTEXIMAGE3DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXIMAGE3DEXTPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXIMAGE3DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIIVEXTPROC)(GLenum target, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, const GLuint * params); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIUIVEXTPROC)(GLenum target, GLenum pname, const GLuint * params); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFPROC)(GLenum target, GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFVPROC)(GLenum target, GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIPROC)(GLenum target, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIVPROC)(GLenum target, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLTEXRENDERBUFFERNVPROC)(GLenum target, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE1DEXTPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE2DEXTPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE3DEXTPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXTUREBUFFEREXTPROC)(GLuint texture, GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLTEXTUREBUFFERRANGEEXTPROC)(GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAD_API_PTR *PFNGLTEXTUREIMAGE1DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXTUREIMAGE2DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXTUREIMAGE3DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXTUREPAGECOMMITMENTEXTPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit); +typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERIIVEXTPROC)(GLuint texture, GLenum target, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERIUIVEXTPROC)(GLuint texture, GLenum target, GLenum pname, const GLuint * params); +typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERFEXTPROC)(GLuint texture, GLenum target, GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERFVEXTPROC)(GLuint texture, GLenum target, GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERIEXTPROC)(GLuint texture, GLenum target, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERIVEXTPROC)(GLuint texture, GLenum target, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLTEXTURERENDERBUFFEREXTPROC)(GLuint texture, GLenum target, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE1DEXTPROC)(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE2DEXTPROC)(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC)(GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE3DEXTPROC)(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC)(GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +typedef void (GLAD_API_PTR *PFNGLTEXTURESUBIMAGE1DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXTURESUBIMAGE2DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXTURESUBIMAGE3DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTRACKMATRIXNVPROC)(GLenum target, GLuint address, GLenum matrix, GLenum transform); +typedef void (GLAD_API_PTR *PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC)(GLsizei count, const GLint * attribs, GLenum bufferMode); +typedef void (GLAD_API_PTR *PFNGLTRANSFORMFEEDBACKSTREAMATTRIBSNVPROC)(GLsizei count, const GLint * attribs, GLsizei nbuffers, const GLint * bufstreams, GLenum bufferMode); +typedef void (GLAD_API_PTR *PFNGLTRANSFORMFEEDBACKVARYINGSPROC)(GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode); +typedef void (GLAD_API_PTR *PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC)(GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode); +typedef void (GLAD_API_PTR *PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC)(GLuint program, GLsizei count, const GLint * locations, GLenum bufferMode); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1FPROC)(GLint location, GLfloat v0); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1FARBPROC)(GLint location, GLfloat v0); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1FVPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1FVARBPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1IPROC)(GLint location, GLint v0); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1IARBPROC)(GLint location, GLint v0); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1IVPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1IVARBPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIPROC)(GLint location, GLuint v0); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIEXTPROC)(GLint location, GLuint v0); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIVPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIVEXTPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2FPROC)(GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2FARBPROC)(GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2FVPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2FVARBPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2IPROC)(GLint location, GLint v0, GLint v1); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2IARBPROC)(GLint location, GLint v0, GLint v1); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2IVPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2IVARBPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIPROC)(GLint location, GLuint v0, GLuint v1); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIEXTPROC)(GLint location, GLuint v0, GLuint v1); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIVPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIVEXTPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3FARBPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3FVPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3FVARBPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3IPROC)(GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3IARBPROC)(GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3IVPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3IVARBPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIEXTPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIVPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIVEXTPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4FARBPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4FVPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4FVARBPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4IPROC)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4IARBPROC)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4IVPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4IVARBPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIEXTPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIVPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIVEXTPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMBLOCKBINDINGPROC)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2FVARBPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3FVARBPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4FVARBPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef GLboolean (GLAD_API_PTR *PFNGLUNMAPBUFFERPROC)(GLenum target); +typedef GLboolean (GLAD_API_PTR *PFNGLUNMAPBUFFERARBPROC)(GLenum target); +typedef GLboolean (GLAD_API_PTR *PFNGLUNMAPNAMEDBUFFEREXTPROC)(GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMPROC)(GLuint program); +typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMOBJECTARBPROC)(GLhandleARB programObj); +typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMPROC)(GLuint program); +typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMARBPROC)(GLhandleARB programObj); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYBINDVERTEXBUFFEREXTPROC)(GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYCOLOROFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYINDEXOFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLenum texunit, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYNORMALOFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC)(GLuint vaobj, GLuint attribindex, GLuint bindingindex); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXATTRIBDIVISOREXTPROC)(GLuint vaobj, GLuint index, GLuint divisor); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXATTRIBFORMATEXTPROC)(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXATTRIBIFORMATEXTPROC)(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC)(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC)(GLuint vaobj, GLuint bindingindex, GLuint divisor); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DPROC)(GLuint index, GLdouble x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DARBPROC)(GLuint index, GLdouble x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DNVPROC)(GLuint index, GLdouble x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DVPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DVARBPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DVNVPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FPROC)(GLuint index, GLfloat x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FARBPROC)(GLuint index, GLfloat x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FNVPROC)(GLuint index, GLfloat x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FVARBPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FVNVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SPROC)(GLuint index, GLshort x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SARBPROC)(GLuint index, GLshort x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SNVPROC)(GLuint index, GLshort x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SVARBPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SVNVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DPROC)(GLuint index, GLdouble x, GLdouble y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DARBPROC)(GLuint index, GLdouble x, GLdouble y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DNVPROC)(GLuint index, GLdouble x, GLdouble y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DVPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DVARBPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DVNVPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FPROC)(GLuint index, GLfloat x, GLfloat y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FARBPROC)(GLuint index, GLfloat x, GLfloat y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FNVPROC)(GLuint index, GLfloat x, GLfloat y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FVARBPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FVNVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SPROC)(GLuint index, GLshort x, GLshort y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SARBPROC)(GLuint index, GLshort x, GLshort y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SNVPROC)(GLuint index, GLshort x, GLshort y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SVARBPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SVNVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DARBPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DNVPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DVPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DVARBPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DVNVPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FARBPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FNVPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FVARBPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FVNVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SPROC)(GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SARBPROC)(GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SNVPROC)(GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SVARBPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SVNVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NBVPROC)(GLuint index, const GLbyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NBVARBPROC)(GLuint index, const GLbyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NIVPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NIVARBPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NSVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NSVARBPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBPROC)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBARBPROC)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBVPROC)(GLuint index, const GLubyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBVARBPROC)(GLuint index, const GLubyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUIVPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUIVARBPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUSVPROC)(GLuint index, const GLushort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUSVARBPROC)(GLuint index, const GLushort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4BVPROC)(GLuint index, const GLbyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4BVARBPROC)(GLuint index, const GLbyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DARBPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DNVPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DVPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DVARBPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DVNVPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FARBPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FNVPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FVARBPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FVNVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4IVPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4IVARBPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SPROC)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SARBPROC)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SNVPROC)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SVARBPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SVNVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UBNVPROC)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UBVPROC)(GLuint index, const GLubyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UBVARBPROC)(GLuint index, const GLubyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UBVNVPROC)(GLuint index, const GLubyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UIVPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UIVARBPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4USVPROC)(GLuint index, const GLushort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4USVARBPROC)(GLuint index, const GLushort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IPROC)(GLuint index, GLint x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IEXTPROC)(GLuint index, GLint x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IVPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IVEXTPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIPROC)(GLuint index, GLuint x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIEXTPROC)(GLuint index, GLuint x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIVPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIVEXTPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IPROC)(GLuint index, GLint x, GLint y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IEXTPROC)(GLuint index, GLint x, GLint y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IVPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IVEXTPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIPROC)(GLuint index, GLuint x, GLuint y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIEXTPROC)(GLuint index, GLuint x, GLuint y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIVPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIVEXTPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IPROC)(GLuint index, GLint x, GLint y, GLint z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IEXTPROC)(GLuint index, GLint x, GLint y, GLint z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IVPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IVEXTPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIEXTPROC)(GLuint index, GLuint x, GLuint y, GLuint z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIVPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIVEXTPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4BVPROC)(GLuint index, const GLbyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4BVEXTPROC)(GLuint index, const GLbyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IPROC)(GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IEXTPROC)(GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IVPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IVEXTPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4SVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4SVEXTPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UBVPROC)(GLuint index, const GLubyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UBVEXTPROC)(GLuint index, const GLubyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIEXTPROC)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIVPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIVEXTPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4USVPROC)(GLuint index, const GLushort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4USVEXTPROC)(GLuint index, const GLushort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBIPOINTERPROC)(GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBIPOINTEREXTPROC)(GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBPOINTERPROC)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBPOINTERARBPROC)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBPOINTERNVPROC)(GLuint index, GLint fsize, GLenum type, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBS1DVNVPROC)(GLuint index, GLsizei count, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBS1FVNVPROC)(GLuint index, GLsizei count, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBS1SVNVPROC)(GLuint index, GLsizei count, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBS2DVNVPROC)(GLuint index, GLsizei count, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBS2FVNVPROC)(GLuint index, GLsizei count, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBS2SVNVPROC)(GLuint index, GLsizei count, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBS3DVNVPROC)(GLuint index, GLsizei count, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBS3FVNVPROC)(GLuint index, GLsizei count, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBS3SVNVPROC)(GLuint index, GLsizei count, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBS4DVNVPROC)(GLuint index, GLsizei count, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBS4FVNVPROC)(GLuint index, GLsizei count, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBS4SVNVPROC)(GLuint index, GLsizei count, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBS4UBVNVPROC)(GLuint index, GLsizei count, const GLubyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXPOINTEREXTPROC)(GLint size, GLenum type, GLsizei stride, GLsizei count, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLVIEWPORTPROC)(GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout); + +typedef struct GladGLContext { + void* userptr; + + int VERSION_1_0; + int VERSION_1_1; + int VERSION_1_2; + int VERSION_1_3; + int VERSION_1_4; + int VERSION_1_5; + int VERSION_2_0; + int VERSION_2_1; + int VERSION_3_0; + int VERSION_3_1; + int VERSION_3_2; + int APPLE_flush_buffer_range; + int APPLE_vertex_array_object; + int ARB_color_buffer_float; + int ARB_copy_buffer; + int ARB_draw_buffers; + int ARB_draw_elements_base_vertex; + int ARB_draw_instanced; + int ARB_framebuffer_object; + int ARB_geometry_shader4; + int ARB_imaging; + int ARB_map_buffer_range; + int ARB_multisample; + int ARB_multitexture; + int ARB_occlusion_query; + int ARB_point_parameters; + int ARB_provoking_vertex; + int ARB_shader_objects; + int ARB_sync; + int ARB_texture_buffer_object; + int ARB_texture_compression; + int ARB_texture_multisample; + int ARB_uniform_buffer_object; + int ARB_vertex_array_object; + int ARB_vertex_buffer_object; + int ARB_vertex_program; + int ARB_vertex_shader; + int ATI_draw_buffers; + int ATI_separate_stencil; + int EXT_blend_color; + int EXT_blend_equation_separate; + int EXT_blend_func_separate; + int EXT_blend_minmax; + int EXT_copy_texture; + int EXT_direct_state_access; + int EXT_draw_buffers2; + int EXT_draw_instanced; + int EXT_draw_range_elements; + int EXT_framebuffer_blit; + int EXT_framebuffer_multisample; + int EXT_framebuffer_object; + int EXT_gpu_shader4; + int EXT_multi_draw_arrays; + int EXT_point_parameters; + int EXT_provoking_vertex; + int EXT_subtexture; + int EXT_texture3D; + int EXT_texture_array; + int EXT_texture_buffer_object; + int EXT_texture_integer; + int EXT_texture_object; + int EXT_transform_feedback; + int EXT_vertex_array; + int INGR_blend_func_separate; + int NVX_conditional_render; + int NV_conditional_render; + int NV_explicit_multisample; + int NV_geometry_program4; + int NV_point_sprite; + int NV_transform_feedback; + int NV_vertex_program; + int NV_vertex_program4; + int SGIS_point_parameters; + + PFNGLACTIVETEXTUREPROC ActiveTexture; + PFNGLACTIVETEXTUREARBPROC ActiveTextureARB; + PFNGLACTIVEVARYINGNVPROC ActiveVaryingNV; + PFNGLAREPROGRAMSRESIDENTNVPROC AreProgramsResidentNV; + PFNGLARETEXTURESRESIDENTEXTPROC AreTexturesResidentEXT; + PFNGLARRAYELEMENTEXTPROC ArrayElementEXT; + PFNGLATTACHOBJECTARBPROC AttachObjectARB; + PFNGLATTACHSHADERPROC AttachShader; + PFNGLBEGINCONDITIONALRENDERPROC BeginConditionalRender; + PFNGLBEGINCONDITIONALRENDERNVPROC BeginConditionalRenderNV; + PFNGLBEGINCONDITIONALRENDERNVXPROC BeginConditionalRenderNVX; + PFNGLBEGINQUERYPROC BeginQuery; + PFNGLBEGINQUERYARBPROC BeginQueryARB; + PFNGLBEGINTRANSFORMFEEDBACKPROC BeginTransformFeedback; + PFNGLBEGINTRANSFORMFEEDBACKEXTPROC BeginTransformFeedbackEXT; + PFNGLBEGINTRANSFORMFEEDBACKNVPROC BeginTransformFeedbackNV; + PFNGLBINDATTRIBLOCATIONPROC BindAttribLocation; + PFNGLBINDATTRIBLOCATIONARBPROC BindAttribLocationARB; + PFNGLBINDBUFFERPROC BindBuffer; + PFNGLBINDBUFFERARBPROC BindBufferARB; + PFNGLBINDBUFFERBASEPROC BindBufferBase; + PFNGLBINDBUFFERBASEEXTPROC BindBufferBaseEXT; + PFNGLBINDBUFFERBASENVPROC BindBufferBaseNV; + PFNGLBINDBUFFEROFFSETEXTPROC BindBufferOffsetEXT; + PFNGLBINDBUFFEROFFSETNVPROC BindBufferOffsetNV; + PFNGLBINDBUFFERRANGEPROC BindBufferRange; + PFNGLBINDBUFFERRANGEEXTPROC BindBufferRangeEXT; + PFNGLBINDBUFFERRANGENVPROC BindBufferRangeNV; + PFNGLBINDFRAGDATALOCATIONPROC BindFragDataLocation; + PFNGLBINDFRAGDATALOCATIONEXTPROC BindFragDataLocationEXT; + PFNGLBINDFRAMEBUFFERPROC BindFramebuffer; + PFNGLBINDFRAMEBUFFEREXTPROC BindFramebufferEXT; + PFNGLBINDMULTITEXTUREEXTPROC BindMultiTextureEXT; + PFNGLBINDPROGRAMARBPROC BindProgramARB; + PFNGLBINDPROGRAMNVPROC BindProgramNV; + PFNGLBINDRENDERBUFFERPROC BindRenderbuffer; + PFNGLBINDRENDERBUFFEREXTPROC BindRenderbufferEXT; + PFNGLBINDTEXTUREPROC BindTexture; + PFNGLBINDTEXTUREEXTPROC BindTextureEXT; + PFNGLBINDVERTEXARRAYPROC BindVertexArray; + PFNGLBINDVERTEXARRAYAPPLEPROC BindVertexArrayAPPLE; + PFNGLBLENDCOLORPROC BlendColor; + PFNGLBLENDCOLOREXTPROC BlendColorEXT; + PFNGLBLENDEQUATIONPROC BlendEquation; + PFNGLBLENDEQUATIONEXTPROC BlendEquationEXT; + PFNGLBLENDEQUATIONSEPARATEPROC BlendEquationSeparate; + PFNGLBLENDEQUATIONSEPARATEEXTPROC BlendEquationSeparateEXT; + PFNGLBLENDFUNCPROC BlendFunc; + PFNGLBLENDFUNCSEPARATEPROC BlendFuncSeparate; + PFNGLBLENDFUNCSEPARATEEXTPROC BlendFuncSeparateEXT; + PFNGLBLENDFUNCSEPARATEINGRPROC BlendFuncSeparateINGR; + PFNGLBLITFRAMEBUFFERPROC BlitFramebuffer; + PFNGLBLITFRAMEBUFFEREXTPROC BlitFramebufferEXT; + PFNGLBUFFERDATAPROC BufferData; + PFNGLBUFFERDATAARBPROC BufferDataARB; + PFNGLBUFFERPARAMETERIAPPLEPROC BufferParameteriAPPLE; + PFNGLBUFFERSUBDATAPROC BufferSubData; + PFNGLBUFFERSUBDATAARBPROC BufferSubDataARB; + PFNGLCHECKFRAMEBUFFERSTATUSPROC CheckFramebufferStatus; + PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC CheckFramebufferStatusEXT; + PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC CheckNamedFramebufferStatusEXT; + PFNGLCLAMPCOLORPROC ClampColor; + PFNGLCLAMPCOLORARBPROC ClampColorARB; + PFNGLCLEARPROC Clear; + PFNGLCLEARBUFFERFIPROC ClearBufferfi; + PFNGLCLEARBUFFERFVPROC ClearBufferfv; + PFNGLCLEARBUFFERIVPROC ClearBufferiv; + PFNGLCLEARBUFFERUIVPROC ClearBufferuiv; + PFNGLCLEARCOLORPROC ClearColor; + PFNGLCLEARCOLORIIEXTPROC ClearColorIiEXT; + PFNGLCLEARCOLORIUIEXTPROC ClearColorIuiEXT; + PFNGLCLEARDEPTHPROC ClearDepth; + PFNGLCLEARNAMEDBUFFERDATAEXTPROC ClearNamedBufferDataEXT; + PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC ClearNamedBufferSubDataEXT; + PFNGLCLEARSTENCILPROC ClearStencil; + PFNGLCLIENTACTIVETEXTUREARBPROC ClientActiveTextureARB; + PFNGLCLIENTATTRIBDEFAULTEXTPROC ClientAttribDefaultEXT; + PFNGLCLIENTWAITSYNCPROC ClientWaitSync; + PFNGLCOLORMASKPROC ColorMask; + PFNGLCOLORMASKINDEXEDEXTPROC ColorMaskIndexedEXT; + PFNGLCOLORMASKIPROC ColorMaski; + PFNGLCOLORPOINTEREXTPROC ColorPointerEXT; + PFNGLCOMPILESHADERPROC CompileShader; + PFNGLCOMPILESHADERARBPROC CompileShaderARB; + PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC CompressedMultiTexImage1DEXT; + PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC CompressedMultiTexImage2DEXT; + PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC CompressedMultiTexImage3DEXT; + PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC CompressedMultiTexSubImage1DEXT; + PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC CompressedMultiTexSubImage2DEXT; + PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC CompressedMultiTexSubImage3DEXT; + PFNGLCOMPRESSEDTEXIMAGE1DPROC CompressedTexImage1D; + PFNGLCOMPRESSEDTEXIMAGE1DARBPROC CompressedTexImage1DARB; + PFNGLCOMPRESSEDTEXIMAGE2DPROC CompressedTexImage2D; + PFNGLCOMPRESSEDTEXIMAGE2DARBPROC CompressedTexImage2DARB; + PFNGLCOMPRESSEDTEXIMAGE3DPROC CompressedTexImage3D; + PFNGLCOMPRESSEDTEXIMAGE3DARBPROC CompressedTexImage3DARB; + PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC CompressedTexSubImage1D; + PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC CompressedTexSubImage1DARB; + PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC CompressedTexSubImage2D; + PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC CompressedTexSubImage2DARB; + PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC CompressedTexSubImage3D; + PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC CompressedTexSubImage3DARB; + PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC CompressedTextureImage1DEXT; + PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC CompressedTextureImage2DEXT; + PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC CompressedTextureImage3DEXT; + PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC CompressedTextureSubImage1DEXT; + PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC CompressedTextureSubImage2DEXT; + PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC CompressedTextureSubImage3DEXT; + PFNGLCOPYBUFFERSUBDATAPROC CopyBufferSubData; + PFNGLCOPYMULTITEXIMAGE1DEXTPROC CopyMultiTexImage1DEXT; + PFNGLCOPYMULTITEXIMAGE2DEXTPROC CopyMultiTexImage2DEXT; + PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC CopyMultiTexSubImage1DEXT; + PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC CopyMultiTexSubImage2DEXT; + PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC CopyMultiTexSubImage3DEXT; + PFNGLCOPYTEXIMAGE1DPROC CopyTexImage1D; + PFNGLCOPYTEXIMAGE1DEXTPROC CopyTexImage1DEXT; + PFNGLCOPYTEXIMAGE2DPROC CopyTexImage2D; + PFNGLCOPYTEXIMAGE2DEXTPROC CopyTexImage2DEXT; + PFNGLCOPYTEXSUBIMAGE1DPROC CopyTexSubImage1D; + PFNGLCOPYTEXSUBIMAGE1DEXTPROC CopyTexSubImage1DEXT; + PFNGLCOPYTEXSUBIMAGE2DPROC CopyTexSubImage2D; + PFNGLCOPYTEXSUBIMAGE2DEXTPROC CopyTexSubImage2DEXT; + PFNGLCOPYTEXSUBIMAGE3DPROC CopyTexSubImage3D; + PFNGLCOPYTEXSUBIMAGE3DEXTPROC CopyTexSubImage3DEXT; + PFNGLCOPYTEXTUREIMAGE1DEXTPROC CopyTextureImage1DEXT; + PFNGLCOPYTEXTUREIMAGE2DEXTPROC CopyTextureImage2DEXT; + PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC CopyTextureSubImage1DEXT; + PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC CopyTextureSubImage2DEXT; + PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC CopyTextureSubImage3DEXT; + PFNGLCREATEPROGRAMPROC CreateProgram; + PFNGLCREATEPROGRAMOBJECTARBPROC CreateProgramObjectARB; + PFNGLCREATESHADERPROC CreateShader; + PFNGLCREATESHADEROBJECTARBPROC CreateShaderObjectARB; + PFNGLCULLFACEPROC CullFace; + PFNGLDELETEBUFFERSPROC DeleteBuffers; + PFNGLDELETEBUFFERSARBPROC DeleteBuffersARB; + PFNGLDELETEFRAMEBUFFERSPROC DeleteFramebuffers; + PFNGLDELETEFRAMEBUFFERSEXTPROC DeleteFramebuffersEXT; + PFNGLDELETEOBJECTARBPROC DeleteObjectARB; + PFNGLDELETEPROGRAMPROC DeleteProgram; + PFNGLDELETEPROGRAMSARBPROC DeleteProgramsARB; + PFNGLDELETEPROGRAMSNVPROC DeleteProgramsNV; + PFNGLDELETEQUERIESPROC DeleteQueries; + PFNGLDELETEQUERIESARBPROC DeleteQueriesARB; + PFNGLDELETERENDERBUFFERSPROC DeleteRenderbuffers; + PFNGLDELETERENDERBUFFERSEXTPROC DeleteRenderbuffersEXT; + PFNGLDELETESHADERPROC DeleteShader; + PFNGLDELETESYNCPROC DeleteSync; + PFNGLDELETETEXTURESPROC DeleteTextures; + PFNGLDELETETEXTURESEXTPROC DeleteTexturesEXT; + PFNGLDELETEVERTEXARRAYSPROC DeleteVertexArrays; + PFNGLDELETEVERTEXARRAYSAPPLEPROC DeleteVertexArraysAPPLE; + PFNGLDEPTHFUNCPROC DepthFunc; + PFNGLDEPTHMASKPROC DepthMask; + PFNGLDEPTHRANGEPROC DepthRange; + PFNGLDETACHOBJECTARBPROC DetachObjectARB; + PFNGLDETACHSHADERPROC DetachShader; + PFNGLDISABLEPROC Disable; + PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC DisableClientStateIndexedEXT; + PFNGLDISABLECLIENTSTATEIEXTPROC DisableClientStateiEXT; + PFNGLDISABLEINDEXEDEXTPROC DisableIndexedEXT; + PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC DisableVertexArrayAttribEXT; + PFNGLDISABLEVERTEXARRAYEXTPROC DisableVertexArrayEXT; + PFNGLDISABLEVERTEXATTRIBARRAYPROC DisableVertexAttribArray; + PFNGLDISABLEVERTEXATTRIBARRAYARBPROC DisableVertexAttribArrayARB; + PFNGLDISABLEIPROC Disablei; + PFNGLDRAWARRAYSPROC DrawArrays; + PFNGLDRAWARRAYSEXTPROC DrawArraysEXT; + PFNGLDRAWARRAYSINSTANCEDPROC DrawArraysInstanced; + PFNGLDRAWARRAYSINSTANCEDARBPROC DrawArraysInstancedARB; + PFNGLDRAWARRAYSINSTANCEDEXTPROC DrawArraysInstancedEXT; + PFNGLDRAWBUFFERPROC DrawBuffer; + PFNGLDRAWBUFFERSPROC DrawBuffers; + PFNGLDRAWBUFFERSARBPROC DrawBuffersARB; + PFNGLDRAWBUFFERSATIPROC DrawBuffersATI; + PFNGLDRAWELEMENTSPROC DrawElements; + PFNGLDRAWELEMENTSBASEVERTEXPROC DrawElementsBaseVertex; + PFNGLDRAWELEMENTSINSTANCEDPROC DrawElementsInstanced; + PFNGLDRAWELEMENTSINSTANCEDARBPROC DrawElementsInstancedARB; + PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC DrawElementsInstancedBaseVertex; + PFNGLDRAWELEMENTSINSTANCEDEXTPROC DrawElementsInstancedEXT; + PFNGLDRAWRANGEELEMENTSPROC DrawRangeElements; + PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC DrawRangeElementsBaseVertex; + PFNGLDRAWRANGEELEMENTSEXTPROC DrawRangeElementsEXT; + PFNGLEDGEFLAGPOINTEREXTPROC EdgeFlagPointerEXT; + PFNGLENABLEPROC Enable; + PFNGLENABLECLIENTSTATEINDEXEDEXTPROC EnableClientStateIndexedEXT; + PFNGLENABLECLIENTSTATEIEXTPROC EnableClientStateiEXT; + PFNGLENABLEINDEXEDEXTPROC EnableIndexedEXT; + PFNGLENABLEVERTEXARRAYATTRIBEXTPROC EnableVertexArrayAttribEXT; + PFNGLENABLEVERTEXARRAYEXTPROC EnableVertexArrayEXT; + PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray; + PFNGLENABLEVERTEXATTRIBARRAYARBPROC EnableVertexAttribArrayARB; + PFNGLENABLEIPROC Enablei; + PFNGLENDCONDITIONALRENDERPROC EndConditionalRender; + PFNGLENDCONDITIONALRENDERNVPROC EndConditionalRenderNV; + PFNGLENDCONDITIONALRENDERNVXPROC EndConditionalRenderNVX; + PFNGLENDQUERYPROC EndQuery; + PFNGLENDQUERYARBPROC EndQueryARB; + PFNGLENDTRANSFORMFEEDBACKPROC EndTransformFeedback; + PFNGLENDTRANSFORMFEEDBACKEXTPROC EndTransformFeedbackEXT; + PFNGLENDTRANSFORMFEEDBACKNVPROC EndTransformFeedbackNV; + PFNGLEXECUTEPROGRAMNVPROC ExecuteProgramNV; + PFNGLFENCESYNCPROC FenceSync; + PFNGLFINISHPROC Finish; + PFNGLFLUSHPROC Flush; + PFNGLFLUSHMAPPEDBUFFERRANGEPROC FlushMappedBufferRange; + PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC FlushMappedBufferRangeAPPLE; + PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC FlushMappedNamedBufferRangeEXT; + PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC FramebufferDrawBufferEXT; + PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC FramebufferDrawBuffersEXT; + PFNGLFRAMEBUFFERREADBUFFEREXTPROC FramebufferReadBufferEXT; + PFNGLFRAMEBUFFERRENDERBUFFERPROC FramebufferRenderbuffer; + PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC FramebufferRenderbufferEXT; + PFNGLFRAMEBUFFERTEXTUREPROC FramebufferTexture; + PFNGLFRAMEBUFFERTEXTURE1DPROC FramebufferTexture1D; + PFNGLFRAMEBUFFERTEXTURE1DEXTPROC FramebufferTexture1DEXT; + PFNGLFRAMEBUFFERTEXTURE2DPROC FramebufferTexture2D; + PFNGLFRAMEBUFFERTEXTURE2DEXTPROC FramebufferTexture2DEXT; + PFNGLFRAMEBUFFERTEXTURE3DPROC FramebufferTexture3D; + PFNGLFRAMEBUFFERTEXTURE3DEXTPROC FramebufferTexture3DEXT; + PFNGLFRAMEBUFFERTEXTUREARBPROC FramebufferTextureARB; + PFNGLFRAMEBUFFERTEXTUREEXTPROC FramebufferTextureEXT; + PFNGLFRAMEBUFFERTEXTUREFACEARBPROC FramebufferTextureFaceARB; + PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC FramebufferTextureFaceEXT; + PFNGLFRAMEBUFFERTEXTURELAYERPROC FramebufferTextureLayer; + PFNGLFRAMEBUFFERTEXTURELAYERARBPROC FramebufferTextureLayerARB; + PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC FramebufferTextureLayerEXT; + PFNGLFRONTFACEPROC FrontFace; + PFNGLGENBUFFERSPROC GenBuffers; + PFNGLGENBUFFERSARBPROC GenBuffersARB; + PFNGLGENFRAMEBUFFERSPROC GenFramebuffers; + PFNGLGENFRAMEBUFFERSEXTPROC GenFramebuffersEXT; + PFNGLGENPROGRAMSARBPROC GenProgramsARB; + PFNGLGENPROGRAMSNVPROC GenProgramsNV; + PFNGLGENQUERIESPROC GenQueries; + PFNGLGENQUERIESARBPROC GenQueriesARB; + PFNGLGENRENDERBUFFERSPROC GenRenderbuffers; + PFNGLGENRENDERBUFFERSEXTPROC GenRenderbuffersEXT; + PFNGLGENTEXTURESPROC GenTextures; + PFNGLGENTEXTURESEXTPROC GenTexturesEXT; + PFNGLGENVERTEXARRAYSPROC GenVertexArrays; + PFNGLGENVERTEXARRAYSAPPLEPROC GenVertexArraysAPPLE; + PFNGLGENERATEMIPMAPPROC GenerateMipmap; + PFNGLGENERATEMIPMAPEXTPROC GenerateMipmapEXT; + PFNGLGENERATEMULTITEXMIPMAPEXTPROC GenerateMultiTexMipmapEXT; + PFNGLGENERATETEXTUREMIPMAPEXTPROC GenerateTextureMipmapEXT; + PFNGLGETACTIVEATTRIBPROC GetActiveAttrib; + PFNGLGETACTIVEATTRIBARBPROC GetActiveAttribARB; + PFNGLGETACTIVEUNIFORMPROC GetActiveUniform; + PFNGLGETACTIVEUNIFORMARBPROC GetActiveUniformARB; + PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC GetActiveUniformBlockName; + PFNGLGETACTIVEUNIFORMBLOCKIVPROC GetActiveUniformBlockiv; + PFNGLGETACTIVEUNIFORMNAMEPROC GetActiveUniformName; + PFNGLGETACTIVEUNIFORMSIVPROC GetActiveUniformsiv; + PFNGLGETACTIVEVARYINGNVPROC GetActiveVaryingNV; + PFNGLGETATTACHEDOBJECTSARBPROC GetAttachedObjectsARB; + PFNGLGETATTACHEDSHADERSPROC GetAttachedShaders; + PFNGLGETATTRIBLOCATIONPROC GetAttribLocation; + PFNGLGETATTRIBLOCATIONARBPROC GetAttribLocationARB; + PFNGLGETBOOLEANINDEXEDVEXTPROC GetBooleanIndexedvEXT; + PFNGLGETBOOLEANI_VPROC GetBooleani_v; + PFNGLGETBOOLEANVPROC GetBooleanv; + PFNGLGETBUFFERPARAMETERI64VPROC GetBufferParameteri64v; + PFNGLGETBUFFERPARAMETERIVPROC GetBufferParameteriv; + PFNGLGETBUFFERPARAMETERIVARBPROC GetBufferParameterivARB; + PFNGLGETBUFFERPOINTERVPROC GetBufferPointerv; + PFNGLGETBUFFERPOINTERVARBPROC GetBufferPointervARB; + PFNGLGETBUFFERSUBDATAPROC GetBufferSubData; + PFNGLGETBUFFERSUBDATAARBPROC GetBufferSubDataARB; + PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC GetCompressedMultiTexImageEXT; + PFNGLGETCOMPRESSEDTEXIMAGEPROC GetCompressedTexImage; + PFNGLGETCOMPRESSEDTEXIMAGEARBPROC GetCompressedTexImageARB; + PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC GetCompressedTextureImageEXT; + PFNGLGETDOUBLEINDEXEDVEXTPROC GetDoubleIndexedvEXT; + PFNGLGETDOUBLEI_VEXTPROC GetDoublei_vEXT; + PFNGLGETDOUBLEVPROC GetDoublev; + PFNGLGETERRORPROC GetError; + PFNGLGETFLOATINDEXEDVEXTPROC GetFloatIndexedvEXT; + PFNGLGETFLOATI_VEXTPROC GetFloati_vEXT; + PFNGLGETFLOATVPROC GetFloatv; + PFNGLGETFRAGDATALOCATIONPROC GetFragDataLocation; + PFNGLGETFRAGDATALOCATIONEXTPROC GetFragDataLocationEXT; + PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC GetFramebufferAttachmentParameteriv; + PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC GetFramebufferAttachmentParameterivEXT; + PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC GetFramebufferParameterivEXT; + PFNGLGETHANDLEARBPROC GetHandleARB; + PFNGLGETINFOLOGARBPROC GetInfoLogARB; + PFNGLGETINTEGER64I_VPROC GetInteger64i_v; + PFNGLGETINTEGER64VPROC GetInteger64v; + PFNGLGETINTEGERINDEXEDVEXTPROC GetIntegerIndexedvEXT; + PFNGLGETINTEGERI_VPROC GetIntegeri_v; + PFNGLGETINTEGERVPROC GetIntegerv; + PFNGLGETMULTITEXENVFVEXTPROC GetMultiTexEnvfvEXT; + PFNGLGETMULTITEXENVIVEXTPROC GetMultiTexEnvivEXT; + PFNGLGETMULTITEXGENDVEXTPROC GetMultiTexGendvEXT; + PFNGLGETMULTITEXGENFVEXTPROC GetMultiTexGenfvEXT; + PFNGLGETMULTITEXGENIVEXTPROC GetMultiTexGenivEXT; + PFNGLGETMULTITEXIMAGEEXTPROC GetMultiTexImageEXT; + PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC GetMultiTexLevelParameterfvEXT; + PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC GetMultiTexLevelParameterivEXT; + PFNGLGETMULTITEXPARAMETERIIVEXTPROC GetMultiTexParameterIivEXT; + PFNGLGETMULTITEXPARAMETERIUIVEXTPROC GetMultiTexParameterIuivEXT; + PFNGLGETMULTITEXPARAMETERFVEXTPROC GetMultiTexParameterfvEXT; + PFNGLGETMULTITEXPARAMETERIVEXTPROC GetMultiTexParameterivEXT; + PFNGLGETMULTISAMPLEFVPROC GetMultisamplefv; + PFNGLGETMULTISAMPLEFVNVPROC GetMultisamplefvNV; + PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC GetNamedBufferParameterivEXT; + PFNGLGETNAMEDBUFFERPOINTERVEXTPROC GetNamedBufferPointervEXT; + PFNGLGETNAMEDBUFFERSUBDATAEXTPROC GetNamedBufferSubDataEXT; + PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC GetNamedFramebufferAttachmentParameterivEXT; + PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC GetNamedFramebufferParameterivEXT; + PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC GetNamedProgramLocalParameterIivEXT; + PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC GetNamedProgramLocalParameterIuivEXT; + PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC GetNamedProgramLocalParameterdvEXT; + PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC GetNamedProgramLocalParameterfvEXT; + PFNGLGETNAMEDPROGRAMSTRINGEXTPROC GetNamedProgramStringEXT; + PFNGLGETNAMEDPROGRAMIVEXTPROC GetNamedProgramivEXT; + PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC GetNamedRenderbufferParameterivEXT; + PFNGLGETOBJECTPARAMETERFVARBPROC GetObjectParameterfvARB; + PFNGLGETOBJECTPARAMETERIVARBPROC GetObjectParameterivARB; + PFNGLGETPOINTERINDEXEDVEXTPROC GetPointerIndexedvEXT; + PFNGLGETPOINTERI_VEXTPROC GetPointeri_vEXT; + PFNGLGETPOINTERVEXTPROC GetPointervEXT; + PFNGLGETPROGRAMENVPARAMETERDVARBPROC GetProgramEnvParameterdvARB; + PFNGLGETPROGRAMENVPARAMETERFVARBPROC GetProgramEnvParameterfvARB; + PFNGLGETPROGRAMINFOLOGPROC GetProgramInfoLog; + PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC GetProgramLocalParameterdvARB; + PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC GetProgramLocalParameterfvARB; + PFNGLGETPROGRAMPARAMETERDVNVPROC GetProgramParameterdvNV; + PFNGLGETPROGRAMPARAMETERFVNVPROC GetProgramParameterfvNV; + PFNGLGETPROGRAMSTRINGARBPROC GetProgramStringARB; + PFNGLGETPROGRAMSTRINGNVPROC GetProgramStringNV; + PFNGLGETPROGRAMIVPROC GetProgramiv; + PFNGLGETPROGRAMIVARBPROC GetProgramivARB; + PFNGLGETPROGRAMIVNVPROC GetProgramivNV; + PFNGLGETQUERYOBJECTIVPROC GetQueryObjectiv; + PFNGLGETQUERYOBJECTIVARBPROC GetQueryObjectivARB; + PFNGLGETQUERYOBJECTUIVPROC GetQueryObjectuiv; + PFNGLGETQUERYOBJECTUIVARBPROC GetQueryObjectuivARB; + PFNGLGETQUERYIVPROC GetQueryiv; + PFNGLGETQUERYIVARBPROC GetQueryivARB; + PFNGLGETRENDERBUFFERPARAMETERIVPROC GetRenderbufferParameteriv; + PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC GetRenderbufferParameterivEXT; + PFNGLGETSHADERINFOLOGPROC GetShaderInfoLog; + PFNGLGETSHADERSOURCEPROC GetShaderSource; + PFNGLGETSHADERSOURCEARBPROC GetShaderSourceARB; + PFNGLGETSHADERIVPROC GetShaderiv; + PFNGLGETSTRINGPROC GetString; + PFNGLGETSTRINGIPROC GetStringi; + PFNGLGETSYNCIVPROC GetSynciv; + PFNGLGETTEXIMAGEPROC GetTexImage; + PFNGLGETTEXLEVELPARAMETERFVPROC GetTexLevelParameterfv; + PFNGLGETTEXLEVELPARAMETERIVPROC GetTexLevelParameteriv; + PFNGLGETTEXPARAMETERIIVPROC GetTexParameterIiv; + PFNGLGETTEXPARAMETERIIVEXTPROC GetTexParameterIivEXT; + PFNGLGETTEXPARAMETERIUIVPROC GetTexParameterIuiv; + PFNGLGETTEXPARAMETERIUIVEXTPROC GetTexParameterIuivEXT; + PFNGLGETTEXPARAMETERFVPROC GetTexParameterfv; + PFNGLGETTEXPARAMETERIVPROC GetTexParameteriv; + PFNGLGETTEXTUREIMAGEEXTPROC GetTextureImageEXT; + PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC GetTextureLevelParameterfvEXT; + PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC GetTextureLevelParameterivEXT; + PFNGLGETTEXTUREPARAMETERIIVEXTPROC GetTextureParameterIivEXT; + PFNGLGETTEXTUREPARAMETERIUIVEXTPROC GetTextureParameterIuivEXT; + PFNGLGETTEXTUREPARAMETERFVEXTPROC GetTextureParameterfvEXT; + PFNGLGETTEXTUREPARAMETERIVEXTPROC GetTextureParameterivEXT; + PFNGLGETTRACKMATRIXIVNVPROC GetTrackMatrixivNV; + PFNGLGETTRANSFORMFEEDBACKVARYINGPROC GetTransformFeedbackVarying; + PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC GetTransformFeedbackVaryingEXT; + PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC GetTransformFeedbackVaryingNV; + PFNGLGETUNIFORMBLOCKINDEXPROC GetUniformBlockIndex; + PFNGLGETUNIFORMINDICESPROC GetUniformIndices; + PFNGLGETUNIFORMLOCATIONPROC GetUniformLocation; + PFNGLGETUNIFORMLOCATIONARBPROC GetUniformLocationARB; + PFNGLGETUNIFORMFVPROC GetUniformfv; + PFNGLGETUNIFORMFVARBPROC GetUniformfvARB; + PFNGLGETUNIFORMIVPROC GetUniformiv; + PFNGLGETUNIFORMIVARBPROC GetUniformivARB; + PFNGLGETUNIFORMUIVPROC GetUniformuiv; + PFNGLGETUNIFORMUIVEXTPROC GetUniformuivEXT; + PFNGLGETVARYINGLOCATIONNVPROC GetVaryingLocationNV; + PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC GetVertexArrayIntegeri_vEXT; + PFNGLGETVERTEXARRAYINTEGERVEXTPROC GetVertexArrayIntegervEXT; + PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC GetVertexArrayPointeri_vEXT; + PFNGLGETVERTEXARRAYPOINTERVEXTPROC GetVertexArrayPointervEXT; + PFNGLGETVERTEXATTRIBIIVPROC GetVertexAttribIiv; + PFNGLGETVERTEXATTRIBIIVEXTPROC GetVertexAttribIivEXT; + PFNGLGETVERTEXATTRIBIUIVPROC GetVertexAttribIuiv; + PFNGLGETVERTEXATTRIBIUIVEXTPROC GetVertexAttribIuivEXT; + PFNGLGETVERTEXATTRIBPOINTERVPROC GetVertexAttribPointerv; + PFNGLGETVERTEXATTRIBPOINTERVARBPROC GetVertexAttribPointervARB; + PFNGLGETVERTEXATTRIBPOINTERVNVPROC GetVertexAttribPointervNV; + PFNGLGETVERTEXATTRIBDVPROC GetVertexAttribdv; + PFNGLGETVERTEXATTRIBDVARBPROC GetVertexAttribdvARB; + PFNGLGETVERTEXATTRIBDVNVPROC GetVertexAttribdvNV; + PFNGLGETVERTEXATTRIBFVPROC GetVertexAttribfv; + PFNGLGETVERTEXATTRIBFVARBPROC GetVertexAttribfvARB; + PFNGLGETVERTEXATTRIBFVNVPROC GetVertexAttribfvNV; + PFNGLGETVERTEXATTRIBIVPROC GetVertexAttribiv; + PFNGLGETVERTEXATTRIBIVARBPROC GetVertexAttribivARB; + PFNGLGETVERTEXATTRIBIVNVPROC GetVertexAttribivNV; + PFNGLHINTPROC Hint; + PFNGLINDEXPOINTEREXTPROC IndexPointerEXT; + PFNGLISBUFFERPROC IsBuffer; + PFNGLISBUFFERARBPROC IsBufferARB; + PFNGLISENABLEDPROC IsEnabled; + PFNGLISENABLEDINDEXEDEXTPROC IsEnabledIndexedEXT; + PFNGLISENABLEDIPROC IsEnabledi; + PFNGLISFRAMEBUFFERPROC IsFramebuffer; + PFNGLISFRAMEBUFFEREXTPROC IsFramebufferEXT; + PFNGLISPROGRAMPROC IsProgram; + PFNGLISPROGRAMARBPROC IsProgramARB; + PFNGLISPROGRAMNVPROC IsProgramNV; + PFNGLISQUERYPROC IsQuery; + PFNGLISQUERYARBPROC IsQueryARB; + PFNGLISRENDERBUFFERPROC IsRenderbuffer; + PFNGLISRENDERBUFFEREXTPROC IsRenderbufferEXT; + PFNGLISSHADERPROC IsShader; + PFNGLISSYNCPROC IsSync; + PFNGLISTEXTUREPROC IsTexture; + PFNGLISTEXTUREEXTPROC IsTextureEXT; + PFNGLISVERTEXARRAYPROC IsVertexArray; + PFNGLISVERTEXARRAYAPPLEPROC IsVertexArrayAPPLE; + PFNGLLINEWIDTHPROC LineWidth; + PFNGLLINKPROGRAMPROC LinkProgram; + PFNGLLINKPROGRAMARBPROC LinkProgramARB; + PFNGLLOADPROGRAMNVPROC LoadProgramNV; + PFNGLLOGICOPPROC LogicOp; + PFNGLMAPBUFFERPROC MapBuffer; + PFNGLMAPBUFFERARBPROC MapBufferARB; + PFNGLMAPBUFFERRANGEPROC MapBufferRange; + PFNGLMAPNAMEDBUFFEREXTPROC MapNamedBufferEXT; + PFNGLMAPNAMEDBUFFERRANGEEXTPROC MapNamedBufferRangeEXT; + PFNGLMATRIXFRUSTUMEXTPROC MatrixFrustumEXT; + PFNGLMATRIXLOADIDENTITYEXTPROC MatrixLoadIdentityEXT; + PFNGLMATRIXLOADTRANSPOSEDEXTPROC MatrixLoadTransposedEXT; + PFNGLMATRIXLOADTRANSPOSEFEXTPROC MatrixLoadTransposefEXT; + PFNGLMATRIXLOADDEXTPROC MatrixLoaddEXT; + PFNGLMATRIXLOADFEXTPROC MatrixLoadfEXT; + PFNGLMATRIXMULTTRANSPOSEDEXTPROC MatrixMultTransposedEXT; + PFNGLMATRIXMULTTRANSPOSEFEXTPROC MatrixMultTransposefEXT; + PFNGLMATRIXMULTDEXTPROC MatrixMultdEXT; + PFNGLMATRIXMULTFEXTPROC MatrixMultfEXT; + PFNGLMATRIXORTHOEXTPROC MatrixOrthoEXT; + PFNGLMATRIXPOPEXTPROC MatrixPopEXT; + PFNGLMATRIXPUSHEXTPROC MatrixPushEXT; + PFNGLMATRIXROTATEDEXTPROC MatrixRotatedEXT; + PFNGLMATRIXROTATEFEXTPROC MatrixRotatefEXT; + PFNGLMATRIXSCALEDEXTPROC MatrixScaledEXT; + PFNGLMATRIXSCALEFEXTPROC MatrixScalefEXT; + PFNGLMATRIXTRANSLATEDEXTPROC MatrixTranslatedEXT; + PFNGLMATRIXTRANSLATEFEXTPROC MatrixTranslatefEXT; + PFNGLMULTIDRAWARRAYSPROC MultiDrawArrays; + PFNGLMULTIDRAWARRAYSEXTPROC MultiDrawArraysEXT; + PFNGLMULTIDRAWELEMENTSPROC MultiDrawElements; + PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC MultiDrawElementsBaseVertex; + PFNGLMULTIDRAWELEMENTSEXTPROC MultiDrawElementsEXT; + PFNGLMULTITEXBUFFEREXTPROC MultiTexBufferEXT; + PFNGLMULTITEXCOORD1DARBPROC MultiTexCoord1dARB; + PFNGLMULTITEXCOORD1DVARBPROC MultiTexCoord1dvARB; + PFNGLMULTITEXCOORD1FARBPROC MultiTexCoord1fARB; + PFNGLMULTITEXCOORD1FVARBPROC MultiTexCoord1fvARB; + PFNGLMULTITEXCOORD1IARBPROC MultiTexCoord1iARB; + PFNGLMULTITEXCOORD1IVARBPROC MultiTexCoord1ivARB; + PFNGLMULTITEXCOORD1SARBPROC MultiTexCoord1sARB; + PFNGLMULTITEXCOORD1SVARBPROC MultiTexCoord1svARB; + PFNGLMULTITEXCOORD2DARBPROC MultiTexCoord2dARB; + PFNGLMULTITEXCOORD2DVARBPROC MultiTexCoord2dvARB; + PFNGLMULTITEXCOORD2FARBPROC MultiTexCoord2fARB; + PFNGLMULTITEXCOORD2FVARBPROC MultiTexCoord2fvARB; + PFNGLMULTITEXCOORD2IARBPROC MultiTexCoord2iARB; + PFNGLMULTITEXCOORD2IVARBPROC MultiTexCoord2ivARB; + PFNGLMULTITEXCOORD2SARBPROC MultiTexCoord2sARB; + PFNGLMULTITEXCOORD2SVARBPROC MultiTexCoord2svARB; + PFNGLMULTITEXCOORD3DARBPROC MultiTexCoord3dARB; + PFNGLMULTITEXCOORD3DVARBPROC MultiTexCoord3dvARB; + PFNGLMULTITEXCOORD3FARBPROC MultiTexCoord3fARB; + PFNGLMULTITEXCOORD3FVARBPROC MultiTexCoord3fvARB; + PFNGLMULTITEXCOORD3IARBPROC MultiTexCoord3iARB; + PFNGLMULTITEXCOORD3IVARBPROC MultiTexCoord3ivARB; + PFNGLMULTITEXCOORD3SARBPROC MultiTexCoord3sARB; + PFNGLMULTITEXCOORD3SVARBPROC MultiTexCoord3svARB; + PFNGLMULTITEXCOORD4DARBPROC MultiTexCoord4dARB; + PFNGLMULTITEXCOORD4DVARBPROC MultiTexCoord4dvARB; + PFNGLMULTITEXCOORD4FARBPROC MultiTexCoord4fARB; + PFNGLMULTITEXCOORD4FVARBPROC MultiTexCoord4fvARB; + PFNGLMULTITEXCOORD4IARBPROC MultiTexCoord4iARB; + PFNGLMULTITEXCOORD4IVARBPROC MultiTexCoord4ivARB; + PFNGLMULTITEXCOORD4SARBPROC MultiTexCoord4sARB; + PFNGLMULTITEXCOORD4SVARBPROC MultiTexCoord4svARB; + PFNGLMULTITEXCOORDPOINTEREXTPROC MultiTexCoordPointerEXT; + PFNGLMULTITEXENVFEXTPROC MultiTexEnvfEXT; + PFNGLMULTITEXENVFVEXTPROC MultiTexEnvfvEXT; + PFNGLMULTITEXENVIEXTPROC MultiTexEnviEXT; + PFNGLMULTITEXENVIVEXTPROC MultiTexEnvivEXT; + PFNGLMULTITEXGENDEXTPROC MultiTexGendEXT; + PFNGLMULTITEXGENDVEXTPROC MultiTexGendvEXT; + PFNGLMULTITEXGENFEXTPROC MultiTexGenfEXT; + PFNGLMULTITEXGENFVEXTPROC MultiTexGenfvEXT; + PFNGLMULTITEXGENIEXTPROC MultiTexGeniEXT; + PFNGLMULTITEXGENIVEXTPROC MultiTexGenivEXT; + PFNGLMULTITEXIMAGE1DEXTPROC MultiTexImage1DEXT; + PFNGLMULTITEXIMAGE2DEXTPROC MultiTexImage2DEXT; + PFNGLMULTITEXIMAGE3DEXTPROC MultiTexImage3DEXT; + PFNGLMULTITEXPARAMETERIIVEXTPROC MultiTexParameterIivEXT; + PFNGLMULTITEXPARAMETERIUIVEXTPROC MultiTexParameterIuivEXT; + PFNGLMULTITEXPARAMETERFEXTPROC MultiTexParameterfEXT; + PFNGLMULTITEXPARAMETERFVEXTPROC MultiTexParameterfvEXT; + PFNGLMULTITEXPARAMETERIEXTPROC MultiTexParameteriEXT; + PFNGLMULTITEXPARAMETERIVEXTPROC MultiTexParameterivEXT; + PFNGLMULTITEXRENDERBUFFEREXTPROC MultiTexRenderbufferEXT; + PFNGLMULTITEXSUBIMAGE1DEXTPROC MultiTexSubImage1DEXT; + PFNGLMULTITEXSUBIMAGE2DEXTPROC MultiTexSubImage2DEXT; + PFNGLMULTITEXSUBIMAGE3DEXTPROC MultiTexSubImage3DEXT; + PFNGLNAMEDBUFFERDATAEXTPROC NamedBufferDataEXT; + PFNGLNAMEDBUFFERSTORAGEEXTPROC NamedBufferStorageEXT; + PFNGLNAMEDBUFFERSUBDATAEXTPROC NamedBufferSubDataEXT; + PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC NamedCopyBufferSubDataEXT; + PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC NamedFramebufferParameteriEXT; + PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC NamedFramebufferRenderbufferEXT; + PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC NamedFramebufferTexture1DEXT; + PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC NamedFramebufferTexture2DEXT; + PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC NamedFramebufferTexture3DEXT; + PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC NamedFramebufferTextureEXT; + PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC NamedFramebufferTextureFaceEXT; + PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC NamedFramebufferTextureLayerEXT; + PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC NamedProgramLocalParameter4dEXT; + PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC NamedProgramLocalParameter4dvEXT; + PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC NamedProgramLocalParameter4fEXT; + PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC NamedProgramLocalParameter4fvEXT; + PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC NamedProgramLocalParameterI4iEXT; + PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC NamedProgramLocalParameterI4ivEXT; + PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC NamedProgramLocalParameterI4uiEXT; + PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC NamedProgramLocalParameterI4uivEXT; + PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC NamedProgramLocalParameters4fvEXT; + PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC NamedProgramLocalParametersI4ivEXT; + PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC NamedProgramLocalParametersI4uivEXT; + PFNGLNAMEDPROGRAMSTRINGEXTPROC NamedProgramStringEXT; + PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC NamedRenderbufferStorageEXT; + PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC NamedRenderbufferStorageMultisampleCoverageEXT; + PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC NamedRenderbufferStorageMultisampleEXT; + PFNGLNORMALPOINTEREXTPROC NormalPointerEXT; + PFNGLPIXELSTOREFPROC PixelStoref; + PFNGLPIXELSTOREIPROC PixelStorei; + PFNGLPOINTPARAMETERFPROC PointParameterf; + PFNGLPOINTPARAMETERFARBPROC PointParameterfARB; + PFNGLPOINTPARAMETERFEXTPROC PointParameterfEXT; + PFNGLPOINTPARAMETERFSGISPROC PointParameterfSGIS; + PFNGLPOINTPARAMETERFVPROC PointParameterfv; + PFNGLPOINTPARAMETERFVARBPROC PointParameterfvARB; + PFNGLPOINTPARAMETERFVEXTPROC PointParameterfvEXT; + PFNGLPOINTPARAMETERFVSGISPROC PointParameterfvSGIS; + PFNGLPOINTPARAMETERIPROC PointParameteri; + PFNGLPOINTPARAMETERINVPROC PointParameteriNV; + PFNGLPOINTPARAMETERIVPROC PointParameteriv; + PFNGLPOINTPARAMETERIVNVPROC PointParameterivNV; + PFNGLPOINTSIZEPROC PointSize; + PFNGLPOLYGONMODEPROC PolygonMode; + PFNGLPOLYGONOFFSETPROC PolygonOffset; + PFNGLPRIMITIVERESTARTINDEXPROC PrimitiveRestartIndex; + PFNGLPRIORITIZETEXTURESEXTPROC PrioritizeTexturesEXT; + PFNGLPROGRAMENVPARAMETER4DARBPROC ProgramEnvParameter4dARB; + PFNGLPROGRAMENVPARAMETER4DVARBPROC ProgramEnvParameter4dvARB; + PFNGLPROGRAMENVPARAMETER4FARBPROC ProgramEnvParameter4fARB; + PFNGLPROGRAMENVPARAMETER4FVARBPROC ProgramEnvParameter4fvARB; + PFNGLPROGRAMLOCALPARAMETER4DARBPROC ProgramLocalParameter4dARB; + PFNGLPROGRAMLOCALPARAMETER4DVARBPROC ProgramLocalParameter4dvARB; + PFNGLPROGRAMLOCALPARAMETER4FARBPROC ProgramLocalParameter4fARB; + PFNGLPROGRAMLOCALPARAMETER4FVARBPROC ProgramLocalParameter4fvARB; + PFNGLPROGRAMPARAMETER4DNVPROC ProgramParameter4dNV; + PFNGLPROGRAMPARAMETER4DVNVPROC ProgramParameter4dvNV; + PFNGLPROGRAMPARAMETER4FNVPROC ProgramParameter4fNV; + PFNGLPROGRAMPARAMETER4FVNVPROC ProgramParameter4fvNV; + PFNGLPROGRAMPARAMETERIARBPROC ProgramParameteriARB; + PFNGLPROGRAMPARAMETERS4DVNVPROC ProgramParameters4dvNV; + PFNGLPROGRAMPARAMETERS4FVNVPROC ProgramParameters4fvNV; + PFNGLPROGRAMSTRINGARBPROC ProgramStringARB; + PFNGLPROGRAMUNIFORM1DEXTPROC ProgramUniform1dEXT; + PFNGLPROGRAMUNIFORM1DVEXTPROC ProgramUniform1dvEXT; + PFNGLPROGRAMUNIFORM1FEXTPROC ProgramUniform1fEXT; + PFNGLPROGRAMUNIFORM1FVEXTPROC ProgramUniform1fvEXT; + PFNGLPROGRAMUNIFORM1IEXTPROC ProgramUniform1iEXT; + PFNGLPROGRAMUNIFORM1IVEXTPROC ProgramUniform1ivEXT; + PFNGLPROGRAMUNIFORM1UIEXTPROC ProgramUniform1uiEXT; + PFNGLPROGRAMUNIFORM1UIVEXTPROC ProgramUniform1uivEXT; + PFNGLPROGRAMUNIFORM2DEXTPROC ProgramUniform2dEXT; + PFNGLPROGRAMUNIFORM2DVEXTPROC ProgramUniform2dvEXT; + PFNGLPROGRAMUNIFORM2FEXTPROC ProgramUniform2fEXT; + PFNGLPROGRAMUNIFORM2FVEXTPROC ProgramUniform2fvEXT; + PFNGLPROGRAMUNIFORM2IEXTPROC ProgramUniform2iEXT; + PFNGLPROGRAMUNIFORM2IVEXTPROC ProgramUniform2ivEXT; + PFNGLPROGRAMUNIFORM2UIEXTPROC ProgramUniform2uiEXT; + PFNGLPROGRAMUNIFORM2UIVEXTPROC ProgramUniform2uivEXT; + PFNGLPROGRAMUNIFORM3DEXTPROC ProgramUniform3dEXT; + PFNGLPROGRAMUNIFORM3DVEXTPROC ProgramUniform3dvEXT; + PFNGLPROGRAMUNIFORM3FEXTPROC ProgramUniform3fEXT; + PFNGLPROGRAMUNIFORM3FVEXTPROC ProgramUniform3fvEXT; + PFNGLPROGRAMUNIFORM3IEXTPROC ProgramUniform3iEXT; + PFNGLPROGRAMUNIFORM3IVEXTPROC ProgramUniform3ivEXT; + PFNGLPROGRAMUNIFORM3UIEXTPROC ProgramUniform3uiEXT; + PFNGLPROGRAMUNIFORM3UIVEXTPROC ProgramUniform3uivEXT; + PFNGLPROGRAMUNIFORM4DEXTPROC ProgramUniform4dEXT; + PFNGLPROGRAMUNIFORM4DVEXTPROC ProgramUniform4dvEXT; + PFNGLPROGRAMUNIFORM4FEXTPROC ProgramUniform4fEXT; + PFNGLPROGRAMUNIFORM4FVEXTPROC ProgramUniform4fvEXT; + PFNGLPROGRAMUNIFORM4IEXTPROC ProgramUniform4iEXT; + PFNGLPROGRAMUNIFORM4IVEXTPROC ProgramUniform4ivEXT; + PFNGLPROGRAMUNIFORM4UIEXTPROC ProgramUniform4uiEXT; + PFNGLPROGRAMUNIFORM4UIVEXTPROC ProgramUniform4uivEXT; + PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC ProgramUniformMatrix2dvEXT; + PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC ProgramUniformMatrix2fvEXT; + PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC ProgramUniformMatrix2x3dvEXT; + PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC ProgramUniformMatrix2x3fvEXT; + PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC ProgramUniformMatrix2x4dvEXT; + PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC ProgramUniformMatrix2x4fvEXT; + PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC ProgramUniformMatrix3dvEXT; + PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC ProgramUniformMatrix3fvEXT; + PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC ProgramUniformMatrix3x2dvEXT; + PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC ProgramUniformMatrix3x2fvEXT; + PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC ProgramUniformMatrix3x4dvEXT; + PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC ProgramUniformMatrix3x4fvEXT; + PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC ProgramUniformMatrix4dvEXT; + PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC ProgramUniformMatrix4fvEXT; + PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC ProgramUniformMatrix4x2dvEXT; + PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC ProgramUniformMatrix4x2fvEXT; + PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC ProgramUniformMatrix4x3dvEXT; + PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC ProgramUniformMatrix4x3fvEXT; + PFNGLPROGRAMVERTEXLIMITNVPROC ProgramVertexLimitNV; + PFNGLPROVOKINGVERTEXPROC ProvokingVertex; + PFNGLPROVOKINGVERTEXEXTPROC ProvokingVertexEXT; + PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC PushClientAttribDefaultEXT; + PFNGLREADBUFFERPROC ReadBuffer; + PFNGLREADPIXELSPROC ReadPixels; + PFNGLRENDERBUFFERSTORAGEPROC RenderbufferStorage; + PFNGLRENDERBUFFERSTORAGEEXTPROC RenderbufferStorageEXT; + PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC RenderbufferStorageMultisample; + PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC RenderbufferStorageMultisampleEXT; + PFNGLREQUESTRESIDENTPROGRAMSNVPROC RequestResidentProgramsNV; + PFNGLSAMPLECOVERAGEPROC SampleCoverage; + PFNGLSAMPLECOVERAGEARBPROC SampleCoverageARB; + PFNGLSAMPLEMASKINDEXEDNVPROC SampleMaskIndexedNV; + PFNGLSAMPLEMASKIPROC SampleMaski; + PFNGLSCISSORPROC Scissor; + PFNGLSHADERSOURCEPROC ShaderSource; + PFNGLSHADERSOURCEARBPROC ShaderSourceARB; + PFNGLSTENCILFUNCPROC StencilFunc; + PFNGLSTENCILFUNCSEPARATEPROC StencilFuncSeparate; + PFNGLSTENCILFUNCSEPARATEATIPROC StencilFuncSeparateATI; + PFNGLSTENCILMASKPROC StencilMask; + PFNGLSTENCILMASKSEPARATEPROC StencilMaskSeparate; + PFNGLSTENCILOPPROC StencilOp; + PFNGLSTENCILOPSEPARATEPROC StencilOpSeparate; + PFNGLSTENCILOPSEPARATEATIPROC StencilOpSeparateATI; + PFNGLTEXBUFFERPROC TexBuffer; + PFNGLTEXBUFFERARBPROC TexBufferARB; + PFNGLTEXBUFFEREXTPROC TexBufferEXT; + PFNGLTEXCOORDPOINTEREXTPROC TexCoordPointerEXT; + PFNGLTEXIMAGE1DPROC TexImage1D; + PFNGLTEXIMAGE2DPROC TexImage2D; + PFNGLTEXIMAGE2DMULTISAMPLEPROC TexImage2DMultisample; + PFNGLTEXIMAGE3DPROC TexImage3D; + PFNGLTEXIMAGE3DEXTPROC TexImage3DEXT; + PFNGLTEXIMAGE3DMULTISAMPLEPROC TexImage3DMultisample; + PFNGLTEXPARAMETERIIVPROC TexParameterIiv; + PFNGLTEXPARAMETERIIVEXTPROC TexParameterIivEXT; + PFNGLTEXPARAMETERIUIVPROC TexParameterIuiv; + PFNGLTEXPARAMETERIUIVEXTPROC TexParameterIuivEXT; + PFNGLTEXPARAMETERFPROC TexParameterf; + PFNGLTEXPARAMETERFVPROC TexParameterfv; + PFNGLTEXPARAMETERIPROC TexParameteri; + PFNGLTEXPARAMETERIVPROC TexParameteriv; + PFNGLTEXRENDERBUFFERNVPROC TexRenderbufferNV; + PFNGLTEXSUBIMAGE1DPROC TexSubImage1D; + PFNGLTEXSUBIMAGE1DEXTPROC TexSubImage1DEXT; + PFNGLTEXSUBIMAGE2DPROC TexSubImage2D; + PFNGLTEXSUBIMAGE2DEXTPROC TexSubImage2DEXT; + PFNGLTEXSUBIMAGE3DPROC TexSubImage3D; + PFNGLTEXSUBIMAGE3DEXTPROC TexSubImage3DEXT; + PFNGLTEXTUREBUFFEREXTPROC TextureBufferEXT; + PFNGLTEXTUREBUFFERRANGEEXTPROC TextureBufferRangeEXT; + PFNGLTEXTUREIMAGE1DEXTPROC TextureImage1DEXT; + PFNGLTEXTUREIMAGE2DEXTPROC TextureImage2DEXT; + PFNGLTEXTUREIMAGE3DEXTPROC TextureImage3DEXT; + PFNGLTEXTUREPAGECOMMITMENTEXTPROC TexturePageCommitmentEXT; + PFNGLTEXTUREPARAMETERIIVEXTPROC TextureParameterIivEXT; + PFNGLTEXTUREPARAMETERIUIVEXTPROC TextureParameterIuivEXT; + PFNGLTEXTUREPARAMETERFEXTPROC TextureParameterfEXT; + PFNGLTEXTUREPARAMETERFVEXTPROC TextureParameterfvEXT; + PFNGLTEXTUREPARAMETERIEXTPROC TextureParameteriEXT; + PFNGLTEXTUREPARAMETERIVEXTPROC TextureParameterivEXT; + PFNGLTEXTURERENDERBUFFEREXTPROC TextureRenderbufferEXT; + PFNGLTEXTURESTORAGE1DEXTPROC TextureStorage1DEXT; + PFNGLTEXTURESTORAGE2DEXTPROC TextureStorage2DEXT; + PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC TextureStorage2DMultisampleEXT; + PFNGLTEXTURESTORAGE3DEXTPROC TextureStorage3DEXT; + PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC TextureStorage3DMultisampleEXT; + PFNGLTEXTURESUBIMAGE1DEXTPROC TextureSubImage1DEXT; + PFNGLTEXTURESUBIMAGE2DEXTPROC TextureSubImage2DEXT; + PFNGLTEXTURESUBIMAGE3DEXTPROC TextureSubImage3DEXT; + PFNGLTRACKMATRIXNVPROC TrackMatrixNV; + PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC TransformFeedbackAttribsNV; + PFNGLTRANSFORMFEEDBACKSTREAMATTRIBSNVPROC TransformFeedbackStreamAttribsNV; + PFNGLTRANSFORMFEEDBACKVARYINGSPROC TransformFeedbackVaryings; + PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC TransformFeedbackVaryingsEXT; + PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC TransformFeedbackVaryingsNV; + PFNGLUNIFORM1FPROC Uniform1f; + PFNGLUNIFORM1FARBPROC Uniform1fARB; + PFNGLUNIFORM1FVPROC Uniform1fv; + PFNGLUNIFORM1FVARBPROC Uniform1fvARB; + PFNGLUNIFORM1IPROC Uniform1i; + PFNGLUNIFORM1IARBPROC Uniform1iARB; + PFNGLUNIFORM1IVPROC Uniform1iv; + PFNGLUNIFORM1IVARBPROC Uniform1ivARB; + PFNGLUNIFORM1UIPROC Uniform1ui; + PFNGLUNIFORM1UIEXTPROC Uniform1uiEXT; + PFNGLUNIFORM1UIVPROC Uniform1uiv; + PFNGLUNIFORM1UIVEXTPROC Uniform1uivEXT; + PFNGLUNIFORM2FPROC Uniform2f; + PFNGLUNIFORM2FARBPROC Uniform2fARB; + PFNGLUNIFORM2FVPROC Uniform2fv; + PFNGLUNIFORM2FVARBPROC Uniform2fvARB; + PFNGLUNIFORM2IPROC Uniform2i; + PFNGLUNIFORM2IARBPROC Uniform2iARB; + PFNGLUNIFORM2IVPROC Uniform2iv; + PFNGLUNIFORM2IVARBPROC Uniform2ivARB; + PFNGLUNIFORM2UIPROC Uniform2ui; + PFNGLUNIFORM2UIEXTPROC Uniform2uiEXT; + PFNGLUNIFORM2UIVPROC Uniform2uiv; + PFNGLUNIFORM2UIVEXTPROC Uniform2uivEXT; + PFNGLUNIFORM3FPROC Uniform3f; + PFNGLUNIFORM3FARBPROC Uniform3fARB; + PFNGLUNIFORM3FVPROC Uniform3fv; + PFNGLUNIFORM3FVARBPROC Uniform3fvARB; + PFNGLUNIFORM3IPROC Uniform3i; + PFNGLUNIFORM3IARBPROC Uniform3iARB; + PFNGLUNIFORM3IVPROC Uniform3iv; + PFNGLUNIFORM3IVARBPROC Uniform3ivARB; + PFNGLUNIFORM3UIPROC Uniform3ui; + PFNGLUNIFORM3UIEXTPROC Uniform3uiEXT; + PFNGLUNIFORM3UIVPROC Uniform3uiv; + PFNGLUNIFORM3UIVEXTPROC Uniform3uivEXT; + PFNGLUNIFORM4FPROC Uniform4f; + PFNGLUNIFORM4FARBPROC Uniform4fARB; + PFNGLUNIFORM4FVPROC Uniform4fv; + PFNGLUNIFORM4FVARBPROC Uniform4fvARB; + PFNGLUNIFORM4IPROC Uniform4i; + PFNGLUNIFORM4IARBPROC Uniform4iARB; + PFNGLUNIFORM4IVPROC Uniform4iv; + PFNGLUNIFORM4IVARBPROC Uniform4ivARB; + PFNGLUNIFORM4UIPROC Uniform4ui; + PFNGLUNIFORM4UIEXTPROC Uniform4uiEXT; + PFNGLUNIFORM4UIVPROC Uniform4uiv; + PFNGLUNIFORM4UIVEXTPROC Uniform4uivEXT; + PFNGLUNIFORMBLOCKBINDINGPROC UniformBlockBinding; + PFNGLUNIFORMMATRIX2FVPROC UniformMatrix2fv; + PFNGLUNIFORMMATRIX2FVARBPROC UniformMatrix2fvARB; + PFNGLUNIFORMMATRIX2X3FVPROC UniformMatrix2x3fv; + PFNGLUNIFORMMATRIX2X4FVPROC UniformMatrix2x4fv; + PFNGLUNIFORMMATRIX3FVPROC UniformMatrix3fv; + PFNGLUNIFORMMATRIX3FVARBPROC UniformMatrix3fvARB; + PFNGLUNIFORMMATRIX3X2FVPROC UniformMatrix3x2fv; + PFNGLUNIFORMMATRIX3X4FVPROC UniformMatrix3x4fv; + PFNGLUNIFORMMATRIX4FVPROC UniformMatrix4fv; + PFNGLUNIFORMMATRIX4FVARBPROC UniformMatrix4fvARB; + PFNGLUNIFORMMATRIX4X2FVPROC UniformMatrix4x2fv; + PFNGLUNIFORMMATRIX4X3FVPROC UniformMatrix4x3fv; + PFNGLUNMAPBUFFERPROC UnmapBuffer; + PFNGLUNMAPBUFFERARBPROC UnmapBufferARB; + PFNGLUNMAPNAMEDBUFFEREXTPROC UnmapNamedBufferEXT; + PFNGLUSEPROGRAMPROC UseProgram; + PFNGLUSEPROGRAMOBJECTARBPROC UseProgramObjectARB; + PFNGLVALIDATEPROGRAMPROC ValidateProgram; + PFNGLVALIDATEPROGRAMARBPROC ValidateProgramARB; + PFNGLVERTEXARRAYBINDVERTEXBUFFEREXTPROC VertexArrayBindVertexBufferEXT; + PFNGLVERTEXARRAYCOLOROFFSETEXTPROC VertexArrayColorOffsetEXT; + PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC VertexArrayEdgeFlagOffsetEXT; + PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC VertexArrayFogCoordOffsetEXT; + PFNGLVERTEXARRAYINDEXOFFSETEXTPROC VertexArrayIndexOffsetEXT; + PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC VertexArrayMultiTexCoordOffsetEXT; + PFNGLVERTEXARRAYNORMALOFFSETEXTPROC VertexArrayNormalOffsetEXT; + PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC VertexArraySecondaryColorOffsetEXT; + PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC VertexArrayTexCoordOffsetEXT; + PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC VertexArrayVertexAttribBindingEXT; + PFNGLVERTEXARRAYVERTEXATTRIBDIVISOREXTPROC VertexArrayVertexAttribDivisorEXT; + PFNGLVERTEXARRAYVERTEXATTRIBFORMATEXTPROC VertexArrayVertexAttribFormatEXT; + PFNGLVERTEXARRAYVERTEXATTRIBIFORMATEXTPROC VertexArrayVertexAttribIFormatEXT; + PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC VertexArrayVertexAttribIOffsetEXT; + PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC VertexArrayVertexAttribLFormatEXT; + PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC VertexArrayVertexAttribLOffsetEXT; + PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC VertexArrayVertexAttribOffsetEXT; + PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC VertexArrayVertexBindingDivisorEXT; + PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC VertexArrayVertexOffsetEXT; + PFNGLVERTEXATTRIB1DPROC VertexAttrib1d; + PFNGLVERTEXATTRIB1DARBPROC VertexAttrib1dARB; + PFNGLVERTEXATTRIB1DNVPROC VertexAttrib1dNV; + PFNGLVERTEXATTRIB1DVPROC VertexAttrib1dv; + PFNGLVERTEXATTRIB1DVARBPROC VertexAttrib1dvARB; + PFNGLVERTEXATTRIB1DVNVPROC VertexAttrib1dvNV; + PFNGLVERTEXATTRIB1FPROC VertexAttrib1f; + PFNGLVERTEXATTRIB1FARBPROC VertexAttrib1fARB; + PFNGLVERTEXATTRIB1FNVPROC VertexAttrib1fNV; + PFNGLVERTEXATTRIB1FVPROC VertexAttrib1fv; + PFNGLVERTEXATTRIB1FVARBPROC VertexAttrib1fvARB; + PFNGLVERTEXATTRIB1FVNVPROC VertexAttrib1fvNV; + PFNGLVERTEXATTRIB1SPROC VertexAttrib1s; + PFNGLVERTEXATTRIB1SARBPROC VertexAttrib1sARB; + PFNGLVERTEXATTRIB1SNVPROC VertexAttrib1sNV; + PFNGLVERTEXATTRIB1SVPROC VertexAttrib1sv; + PFNGLVERTEXATTRIB1SVARBPROC VertexAttrib1svARB; + PFNGLVERTEXATTRIB1SVNVPROC VertexAttrib1svNV; + PFNGLVERTEXATTRIB2DPROC VertexAttrib2d; + PFNGLVERTEXATTRIB2DARBPROC VertexAttrib2dARB; + PFNGLVERTEXATTRIB2DNVPROC VertexAttrib2dNV; + PFNGLVERTEXATTRIB2DVPROC VertexAttrib2dv; + PFNGLVERTEXATTRIB2DVARBPROC VertexAttrib2dvARB; + PFNGLVERTEXATTRIB2DVNVPROC VertexAttrib2dvNV; + PFNGLVERTEXATTRIB2FPROC VertexAttrib2f; + PFNGLVERTEXATTRIB2FARBPROC VertexAttrib2fARB; + PFNGLVERTEXATTRIB2FNVPROC VertexAttrib2fNV; + PFNGLVERTEXATTRIB2FVPROC VertexAttrib2fv; + PFNGLVERTEXATTRIB2FVARBPROC VertexAttrib2fvARB; + PFNGLVERTEXATTRIB2FVNVPROC VertexAttrib2fvNV; + PFNGLVERTEXATTRIB2SPROC VertexAttrib2s; + PFNGLVERTEXATTRIB2SARBPROC VertexAttrib2sARB; + PFNGLVERTEXATTRIB2SNVPROC VertexAttrib2sNV; + PFNGLVERTEXATTRIB2SVPROC VertexAttrib2sv; + PFNGLVERTEXATTRIB2SVARBPROC VertexAttrib2svARB; + PFNGLVERTEXATTRIB2SVNVPROC VertexAttrib2svNV; + PFNGLVERTEXATTRIB3DPROC VertexAttrib3d; + PFNGLVERTEXATTRIB3DARBPROC VertexAttrib3dARB; + PFNGLVERTEXATTRIB3DNVPROC VertexAttrib3dNV; + PFNGLVERTEXATTRIB3DVPROC VertexAttrib3dv; + PFNGLVERTEXATTRIB3DVARBPROC VertexAttrib3dvARB; + PFNGLVERTEXATTRIB3DVNVPROC VertexAttrib3dvNV; + PFNGLVERTEXATTRIB3FPROC VertexAttrib3f; + PFNGLVERTEXATTRIB3FARBPROC VertexAttrib3fARB; + PFNGLVERTEXATTRIB3FNVPROC VertexAttrib3fNV; + PFNGLVERTEXATTRIB3FVPROC VertexAttrib3fv; + PFNGLVERTEXATTRIB3FVARBPROC VertexAttrib3fvARB; + PFNGLVERTEXATTRIB3FVNVPROC VertexAttrib3fvNV; + PFNGLVERTEXATTRIB3SPROC VertexAttrib3s; + PFNGLVERTEXATTRIB3SARBPROC VertexAttrib3sARB; + PFNGLVERTEXATTRIB3SNVPROC VertexAttrib3sNV; + PFNGLVERTEXATTRIB3SVPROC VertexAttrib3sv; + PFNGLVERTEXATTRIB3SVARBPROC VertexAttrib3svARB; + PFNGLVERTEXATTRIB3SVNVPROC VertexAttrib3svNV; + PFNGLVERTEXATTRIB4NBVPROC VertexAttrib4Nbv; + PFNGLVERTEXATTRIB4NBVARBPROC VertexAttrib4NbvARB; + PFNGLVERTEXATTRIB4NIVPROC VertexAttrib4Niv; + PFNGLVERTEXATTRIB4NIVARBPROC VertexAttrib4NivARB; + PFNGLVERTEXATTRIB4NSVPROC VertexAttrib4Nsv; + PFNGLVERTEXATTRIB4NSVARBPROC VertexAttrib4NsvARB; + PFNGLVERTEXATTRIB4NUBPROC VertexAttrib4Nub; + PFNGLVERTEXATTRIB4NUBARBPROC VertexAttrib4NubARB; + PFNGLVERTEXATTRIB4NUBVPROC VertexAttrib4Nubv; + PFNGLVERTEXATTRIB4NUBVARBPROC VertexAttrib4NubvARB; + PFNGLVERTEXATTRIB4NUIVPROC VertexAttrib4Nuiv; + PFNGLVERTEXATTRIB4NUIVARBPROC VertexAttrib4NuivARB; + PFNGLVERTEXATTRIB4NUSVPROC VertexAttrib4Nusv; + PFNGLVERTEXATTRIB4NUSVARBPROC VertexAttrib4NusvARB; + PFNGLVERTEXATTRIB4BVPROC VertexAttrib4bv; + PFNGLVERTEXATTRIB4BVARBPROC VertexAttrib4bvARB; + PFNGLVERTEXATTRIB4DPROC VertexAttrib4d; + PFNGLVERTEXATTRIB4DARBPROC VertexAttrib4dARB; + PFNGLVERTEXATTRIB4DNVPROC VertexAttrib4dNV; + PFNGLVERTEXATTRIB4DVPROC VertexAttrib4dv; + PFNGLVERTEXATTRIB4DVARBPROC VertexAttrib4dvARB; + PFNGLVERTEXATTRIB4DVNVPROC VertexAttrib4dvNV; + PFNGLVERTEXATTRIB4FPROC VertexAttrib4f; + PFNGLVERTEXATTRIB4FARBPROC VertexAttrib4fARB; + PFNGLVERTEXATTRIB4FNVPROC VertexAttrib4fNV; + PFNGLVERTEXATTRIB4FVPROC VertexAttrib4fv; + PFNGLVERTEXATTRIB4FVARBPROC VertexAttrib4fvARB; + PFNGLVERTEXATTRIB4FVNVPROC VertexAttrib4fvNV; + PFNGLVERTEXATTRIB4IVPROC VertexAttrib4iv; + PFNGLVERTEXATTRIB4IVARBPROC VertexAttrib4ivARB; + PFNGLVERTEXATTRIB4SPROC VertexAttrib4s; + PFNGLVERTEXATTRIB4SARBPROC VertexAttrib4sARB; + PFNGLVERTEXATTRIB4SNVPROC VertexAttrib4sNV; + PFNGLVERTEXATTRIB4SVPROC VertexAttrib4sv; + PFNGLVERTEXATTRIB4SVARBPROC VertexAttrib4svARB; + PFNGLVERTEXATTRIB4SVNVPROC VertexAttrib4svNV; + PFNGLVERTEXATTRIB4UBNVPROC VertexAttrib4ubNV; + PFNGLVERTEXATTRIB4UBVPROC VertexAttrib4ubv; + PFNGLVERTEXATTRIB4UBVARBPROC VertexAttrib4ubvARB; + PFNGLVERTEXATTRIB4UBVNVPROC VertexAttrib4ubvNV; + PFNGLVERTEXATTRIB4UIVPROC VertexAttrib4uiv; + PFNGLVERTEXATTRIB4UIVARBPROC VertexAttrib4uivARB; + PFNGLVERTEXATTRIB4USVPROC VertexAttrib4usv; + PFNGLVERTEXATTRIB4USVARBPROC VertexAttrib4usvARB; + PFNGLVERTEXATTRIBI1IPROC VertexAttribI1i; + PFNGLVERTEXATTRIBI1IEXTPROC VertexAttribI1iEXT; + PFNGLVERTEXATTRIBI1IVPROC VertexAttribI1iv; + PFNGLVERTEXATTRIBI1IVEXTPROC VertexAttribI1ivEXT; + PFNGLVERTEXATTRIBI1UIPROC VertexAttribI1ui; + PFNGLVERTEXATTRIBI1UIEXTPROC VertexAttribI1uiEXT; + PFNGLVERTEXATTRIBI1UIVPROC VertexAttribI1uiv; + PFNGLVERTEXATTRIBI1UIVEXTPROC VertexAttribI1uivEXT; + PFNGLVERTEXATTRIBI2IPROC VertexAttribI2i; + PFNGLVERTEXATTRIBI2IEXTPROC VertexAttribI2iEXT; + PFNGLVERTEXATTRIBI2IVPROC VertexAttribI2iv; + PFNGLVERTEXATTRIBI2IVEXTPROC VertexAttribI2ivEXT; + PFNGLVERTEXATTRIBI2UIPROC VertexAttribI2ui; + PFNGLVERTEXATTRIBI2UIEXTPROC VertexAttribI2uiEXT; + PFNGLVERTEXATTRIBI2UIVPROC VertexAttribI2uiv; + PFNGLVERTEXATTRIBI2UIVEXTPROC VertexAttribI2uivEXT; + PFNGLVERTEXATTRIBI3IPROC VertexAttribI3i; + PFNGLVERTEXATTRIBI3IEXTPROC VertexAttribI3iEXT; + PFNGLVERTEXATTRIBI3IVPROC VertexAttribI3iv; + PFNGLVERTEXATTRIBI3IVEXTPROC VertexAttribI3ivEXT; + PFNGLVERTEXATTRIBI3UIPROC VertexAttribI3ui; + PFNGLVERTEXATTRIBI3UIEXTPROC VertexAttribI3uiEXT; + PFNGLVERTEXATTRIBI3UIVPROC VertexAttribI3uiv; + PFNGLVERTEXATTRIBI3UIVEXTPROC VertexAttribI3uivEXT; + PFNGLVERTEXATTRIBI4BVPROC VertexAttribI4bv; + PFNGLVERTEXATTRIBI4BVEXTPROC VertexAttribI4bvEXT; + PFNGLVERTEXATTRIBI4IPROC VertexAttribI4i; + PFNGLVERTEXATTRIBI4IEXTPROC VertexAttribI4iEXT; + PFNGLVERTEXATTRIBI4IVPROC VertexAttribI4iv; + PFNGLVERTEXATTRIBI4IVEXTPROC VertexAttribI4ivEXT; + PFNGLVERTEXATTRIBI4SVPROC VertexAttribI4sv; + PFNGLVERTEXATTRIBI4SVEXTPROC VertexAttribI4svEXT; + PFNGLVERTEXATTRIBI4UBVPROC VertexAttribI4ubv; + PFNGLVERTEXATTRIBI4UBVEXTPROC VertexAttribI4ubvEXT; + PFNGLVERTEXATTRIBI4UIPROC VertexAttribI4ui; + PFNGLVERTEXATTRIBI4UIEXTPROC VertexAttribI4uiEXT; + PFNGLVERTEXATTRIBI4UIVPROC VertexAttribI4uiv; + PFNGLVERTEXATTRIBI4UIVEXTPROC VertexAttribI4uivEXT; + PFNGLVERTEXATTRIBI4USVPROC VertexAttribI4usv; + PFNGLVERTEXATTRIBI4USVEXTPROC VertexAttribI4usvEXT; + PFNGLVERTEXATTRIBIPOINTERPROC VertexAttribIPointer; + PFNGLVERTEXATTRIBIPOINTEREXTPROC VertexAttribIPointerEXT; + PFNGLVERTEXATTRIBPOINTERPROC VertexAttribPointer; + PFNGLVERTEXATTRIBPOINTERARBPROC VertexAttribPointerARB; + PFNGLVERTEXATTRIBPOINTERNVPROC VertexAttribPointerNV; + PFNGLVERTEXATTRIBS1DVNVPROC VertexAttribs1dvNV; + PFNGLVERTEXATTRIBS1FVNVPROC VertexAttribs1fvNV; + PFNGLVERTEXATTRIBS1SVNVPROC VertexAttribs1svNV; + PFNGLVERTEXATTRIBS2DVNVPROC VertexAttribs2dvNV; + PFNGLVERTEXATTRIBS2FVNVPROC VertexAttribs2fvNV; + PFNGLVERTEXATTRIBS2SVNVPROC VertexAttribs2svNV; + PFNGLVERTEXATTRIBS3DVNVPROC VertexAttribs3dvNV; + PFNGLVERTEXATTRIBS3FVNVPROC VertexAttribs3fvNV; + PFNGLVERTEXATTRIBS3SVNVPROC VertexAttribs3svNV; + PFNGLVERTEXATTRIBS4DVNVPROC VertexAttribs4dvNV; + PFNGLVERTEXATTRIBS4FVNVPROC VertexAttribs4fvNV; + PFNGLVERTEXATTRIBS4SVNVPROC VertexAttribs4svNV; + PFNGLVERTEXATTRIBS4UBVNVPROC VertexAttribs4ubvNV; + PFNGLVERTEXPOINTEREXTPROC VertexPointerEXT; + PFNGLVIEWPORTPROC Viewport; + PFNGLWAITSYNCPROC WaitSync; + +} GladGLContext; + + + + + + +GLAD_API_CALL int gladLoadGLContextUserPtr(GladGLContext *context, GLADuserptrloadfunc load, void *userptr); +GLAD_API_CALL int gladLoadGLContext(GladGLContext *context, GLADloadfunc load); + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/thirdparty/glad/include/glad/gles2.h b/thirdparty/glad/include/glad/gles2.h new file mode 100644 index 000000000..a03d1e261 --- /dev/null +++ b/thirdparty/glad/include/glad/gles2.h @@ -0,0 +1,861 @@ +/** + * Loader generated by glad 2.0.2 on Sun Jan 8 22:32:41 2023 + * + * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0 + * + * Generator: C/C++ + * Specification: gl + * Extensions: 1 + * + * APIs: + * - gles2=2.0 + * + * Options: + * - ALIAS = True + * - DEBUG = False + * - HEADER_ONLY = False + * - LOADER = False + * - MX = True + * - ON_DEMAND = False + * + * Commandline: + * --api='gles2=2.0' --extensions='GL_OES_rgb8_rgba8' c --alias --mx + * + * Online: + * http://glad.sh/#api=gles2%3D2.0&extensions=GL_OES_rgb8_rgba8&generator=c&options=ALIAS%2CMX + * + */ + +#ifndef GLAD_GLES2_H_ +#define GLAD_GLES2_H_ + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreserved-id-macro" +#endif +#ifdef __gl2_h_ + #error OpenGL ES 2 header already included (API: gles2), remove previous include! +#endif +#define __gl2_h_ 1 +#ifdef __gles2_gl2_h_ + #error OpenGL ES 2 header already included (API: gles2), remove previous include! +#endif +#define __gles2_gl2_h_ 1 +#ifdef __gl3_h_ + #error OpenGL ES 3 header already included (API: gles2), remove previous include! +#endif +#define __gl3_h_ 1 +#ifdef __gles2_gl3_h_ + #error OpenGL ES 3 header already included (API: gles2), remove previous include! +#endif +#define __gles2_gl3_h_ 1 +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#define GLAD_GLES2 +#define GLAD_OPTION_GLES2_ALIAS +#define GLAD_OPTION_GLES2_MX + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef GLAD_PLATFORM_H_ +#define GLAD_PLATFORM_H_ + +#ifndef GLAD_PLATFORM_WIN32 + #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__) + #define GLAD_PLATFORM_WIN32 1 + #else + #define GLAD_PLATFORM_WIN32 0 + #endif +#endif + +#ifndef GLAD_PLATFORM_APPLE + #ifdef __APPLE__ + #define GLAD_PLATFORM_APPLE 1 + #else + #define GLAD_PLATFORM_APPLE 0 + #endif +#endif + +#ifndef GLAD_PLATFORM_EMSCRIPTEN + #ifdef __EMSCRIPTEN__ + #define GLAD_PLATFORM_EMSCRIPTEN 1 + #else + #define GLAD_PLATFORM_EMSCRIPTEN 0 + #endif +#endif + +#ifndef GLAD_PLATFORM_UWP + #if defined(_MSC_VER) && !defined(GLAD_INTERNAL_HAVE_WINAPIFAMILY) + #ifdef __has_include + #if __has_include() + #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1 + #endif + #elif _MSC_VER >= 1700 && !_USING_V110_SDK71_ + #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1 + #endif + #endif + + #ifdef GLAD_INTERNAL_HAVE_WINAPIFAMILY + #include + #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) + #define GLAD_PLATFORM_UWP 1 + #endif + #endif + + #ifndef GLAD_PLATFORM_UWP + #define GLAD_PLATFORM_UWP 0 + #endif +#endif + +#ifdef __GNUC__ + #define GLAD_GNUC_EXTENSION __extension__ +#else + #define GLAD_GNUC_EXTENSION +#endif + +#define GLAD_UNUSED(x) (void)(x) + +#ifndef GLAD_API_CALL + #if defined(GLAD_API_CALL_EXPORT) + #if GLAD_PLATFORM_WIN32 || defined(__CYGWIN__) + #if defined(GLAD_API_CALL_EXPORT_BUILD) + #if defined(__GNUC__) + #define GLAD_API_CALL __attribute__ ((dllexport)) extern + #else + #define GLAD_API_CALL __declspec(dllexport) extern + #endif + #else + #if defined(__GNUC__) + #define GLAD_API_CALL __attribute__ ((dllimport)) extern + #else + #define GLAD_API_CALL __declspec(dllimport) extern + #endif + #endif + #elif defined(__GNUC__) && defined(GLAD_API_CALL_EXPORT_BUILD) + #define GLAD_API_CALL __attribute__ ((visibility ("default"))) extern + #else + #define GLAD_API_CALL extern + #endif + #else + #define GLAD_API_CALL extern + #endif +#endif + +#ifdef APIENTRY + #define GLAD_API_PTR APIENTRY +#elif GLAD_PLATFORM_WIN32 + #define GLAD_API_PTR __stdcall +#else + #define GLAD_API_PTR +#endif + +#ifndef GLAPI +#define GLAPI GLAD_API_CALL +#endif + +#ifndef GLAPIENTRY +#define GLAPIENTRY GLAD_API_PTR +#endif + +#define GLAD_MAKE_VERSION(major, minor) (major * 10000 + minor) +#define GLAD_VERSION_MAJOR(version) (version / 10000) +#define GLAD_VERSION_MINOR(version) (version % 10000) + +#define GLAD_GENERATOR_VERSION "2.0.2" + +typedef void (*GLADapiproc)(void); + +typedef GLADapiproc (*GLADloadfunc)(const char *name); +typedef GLADapiproc (*GLADuserptrloadfunc)(void *userptr, const char *name); + +typedef void (*GLADprecallback)(const char *name, GLADapiproc apiproc, int len_args, ...); +typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apiproc, int len_args, ...); + +#endif /* GLAD_PLATFORM_H_ */ + +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALPHA 0x1906 +#define GL_ALPHA_BITS 0x0D55 +#define GL_ALWAYS 0x0207 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_BACK 0x0405 +#define GL_BLEND 0x0BE2 +#define GL_BLEND_COLOR 0x8005 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_EQUATION 0x8009 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLUE_BITS 0x0D54 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_BYTE 0x1400 +#define GL_CCW 0x0901 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_CONSTANT_COLOR 0x8001 +#define GL_CULL_FACE 0x0B44 +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_CW 0x0900 +#define GL_DECR 0x1E03 +#define GL_DECR_WRAP 0x8508 +#define GL_DELETE_STATUS 0x8B80 +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_DEPTH_BITS 0x0D56 +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_TEST 0x0B71 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DITHER 0x0BD0 +#define GL_DONT_CARE 0x1100 +#define GL_DST_ALPHA 0x0304 +#define GL_DST_COLOR 0x0306 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_EQUAL 0x0202 +#define GL_EXTENSIONS 0x1F03 +#define GL_FALSE 0 +#define GL_FASTEST 0x1101 +#define GL_FIXED 0x140C +#define GL_FLOAT 0x1406 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_FRONT 0x0404 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_FRONT_FACE 0x0B46 +#define GL_FUNC_ADD 0x8006 +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_FUNC_SUBTRACT 0x800A +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#define GL_GEQUAL 0x0206 +#define GL_GREATER 0x0204 +#define GL_GREEN_BITS 0x0D53 +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_HIGH_INT 0x8DF5 +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_INCR 0x1E02 +#define GL_INCR_WRAP 0x8507 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_INT 0x1404 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#define GL_INVALID_OPERATION 0x0502 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVERT 0x150A +#define GL_KEEP 0x1E00 +#define GL_LEQUAL 0x0203 +#define GL_LESS 0x0201 +#define GL_LINEAR 0x2601 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_LINE_WIDTH 0x0B21 +#define GL_LINK_STATUS 0x8B82 +#define GL_LOW_FLOAT 0x8DF0 +#define GL_LOW_INT 0x8DF3 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_NEAREST 0x2600 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_NEVER 0x0200 +#define GL_NICEST 0x1102 +#define GL_NONE 0 +#define GL_NOTEQUAL 0x0205 +#define GL_NO_ERROR 0 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 +#define GL_ONE 1 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_POINTS 0x0000 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_RED_BITS 0x0D52 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERER 0x1F01 +#define GL_REPEAT 0x2901 +#define GL_REPLACE 0x1E01 +#define GL_RGB 0x1907 +#define GL_RGB565 0x8D62 +#define GL_RGB5_A1 0x8057 +#define GL_RGB8_OES 0x8051 +#define GL_RGBA 0x1908 +#define GL_RGBA4 0x8056 +#define GL_RGBA8_OES 0x8058 +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_SHADER_COMPILER 0x8DFA +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_SHADER_TYPE 0x8B4F +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_SHORT 0x1402 +#define GL_SRC_ALPHA 0x0302 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_SRC_COLOR 0x0300 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#define GL_STENCIL_BITS 0x0D57 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_TEST 0x0B90 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_STREAM_DRAW 0x88E0 +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_TEXTURE 0x1702 +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRUE 1 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_UNSIGNED_INT 0x1405 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_VENDOR 0x1F00 +#define GL_VERSION 0x1F02 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_VIEWPORT 0x0BA2 +#define GL_ZERO 0 + + +#include +typedef unsigned int GLenum; +typedef unsigned char GLboolean; +typedef unsigned int GLbitfield; +typedef void GLvoid; +typedef khronos_int8_t GLbyte; +typedef khronos_uint8_t GLubyte; +typedef khronos_int16_t GLshort; +typedef khronos_uint16_t GLushort; +typedef int GLint; +typedef unsigned int GLuint; +typedef khronos_int32_t GLclampx; +typedef int GLsizei; +typedef khronos_float_t GLfloat; +typedef khronos_float_t GLclampf; +typedef double GLdouble; +typedef double GLclampd; +typedef void *GLeglClientBufferEXT; +typedef void *GLeglImageOES; +typedef char GLchar; +typedef char GLcharARB; +#ifdef __APPLE__ +typedef void *GLhandleARB; +#else +typedef unsigned int GLhandleARB; +#endif +typedef khronos_uint16_t GLhalf; +typedef khronos_uint16_t GLhalfARB; +typedef khronos_int32_t GLfixed; +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) +typedef khronos_intptr_t GLintptr; +#else +typedef khronos_intptr_t GLintptr; +#endif +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) +typedef khronos_intptr_t GLintptrARB; +#else +typedef khronos_intptr_t GLintptrARB; +#endif +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) +typedef khronos_ssize_t GLsizeiptr; +#else +typedef khronos_ssize_t GLsizeiptr; +#endif +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) +typedef khronos_ssize_t GLsizeiptrARB; +#else +typedef khronos_ssize_t GLsizeiptrARB; +#endif +typedef khronos_int64_t GLint64; +typedef khronos_int64_t GLint64EXT; +typedef khronos_uint64_t GLuint64; +typedef khronos_uint64_t GLuint64EXT; +typedef struct __GLsync *GLsync; +struct _cl_context; +struct _cl_event; +typedef void (GLAD_API_PTR *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +typedef void (GLAD_API_PTR *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +typedef void (GLAD_API_PTR *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +typedef void (GLAD_API_PTR *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam); +typedef unsigned short GLhalfNV; +typedef GLintptr GLvdpauSurfaceNV; +typedef void (GLAD_API_PTR *GLVULKANPROCNV)(void); + + +#define GL_ES_VERSION_2_0 1 +#define GL_OES_rgb8_rgba8 1 + + +typedef void (GLAD_API_PTR *PFNGLACTIVETEXTUREPROC)(GLenum texture); +typedef void (GLAD_API_PTR *PFNGLATTACHSHADERPROC)(GLuint program, GLuint shader); +typedef void (GLAD_API_PTR *PFNGLBINDATTRIBLOCATIONPROC)(GLuint program, GLuint index, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLBINDFRAMEBUFFERPROC)(GLenum target, GLuint framebuffer); +typedef void (GLAD_API_PTR *PFNGLBINDRENDERBUFFERPROC)(GLenum target, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLBINDTEXTUREPROC)(GLenum target, GLuint texture); +typedef void (GLAD_API_PTR *PFNGLBLENDCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum modeRGB, GLenum modeAlpha); +typedef void (GLAD_API_PTR *PFNGLBLENDFUNCPROC)(GLenum sfactor, GLenum dfactor); +typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEPROC)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +typedef void (GLAD_API_PTR *PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const void * data, GLenum usage); +typedef void (GLAD_API_PTR *PFNGLBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data); +typedef GLenum (GLAD_API_PTR *PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum target); +typedef void (GLAD_API_PTR *PFNGLCLEARPROC)(GLbitfield mask); +typedef void (GLAD_API_PTR *PFNGLCLEARCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (GLAD_API_PTR *PFNGLCLEARDEPTHFPROC)(GLfloat d); +typedef void (GLAD_API_PTR *PFNGLCLEARSTENCILPROC)(GLint s); +typedef void (GLAD_API_PTR *PFNGLCOLORMASKPROC)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +typedef void (GLAD_API_PTR *PFNGLCOMPILESHADERPROC)(GLuint shader); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef GLuint (GLAD_API_PTR *PFNGLCREATEPROGRAMPROC)(void); +typedef GLuint (GLAD_API_PTR *PFNGLCREATESHADERPROC)(GLenum type); +typedef void (GLAD_API_PTR *PFNGLCULLFACEPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLDELETEBUFFERSPROC)(GLsizei n, const GLuint * buffers); +typedef void (GLAD_API_PTR *PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei n, const GLuint * framebuffers); +typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMPROC)(GLuint program); +typedef void (GLAD_API_PTR *PFNGLDELETERENDERBUFFERSPROC)(GLsizei n, const GLuint * renderbuffers); +typedef void (GLAD_API_PTR *PFNGLDELETESHADERPROC)(GLuint shader); +typedef void (GLAD_API_PTR *PFNGLDELETETEXTURESPROC)(GLsizei n, const GLuint * textures); +typedef void (GLAD_API_PTR *PFNGLDEPTHFUNCPROC)(GLenum func); +typedef void (GLAD_API_PTR *PFNGLDEPTHMASKPROC)(GLboolean flag); +typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEFPROC)(GLfloat n, GLfloat f); +typedef void (GLAD_API_PTR *PFNGLDETACHSHADERPROC)(GLuint program, GLuint shader); +typedef void (GLAD_API_PTR *PFNGLDISABLEPROC)(GLenum cap); +typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint index); +typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSPROC)(GLenum mode, GLint first, GLsizei count); +typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices); +typedef void (GLAD_API_PTR *PFNGLENABLEPROC)(GLenum cap); +typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint index); +typedef void (GLAD_API_PTR *PFNGLFINISHPROC)(void); +typedef void (GLAD_API_PTR *PFNGLFLUSHPROC)(void); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLFRONTFACEPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLGENBUFFERSPROC)(GLsizei n, GLuint * buffers); +typedef void (GLAD_API_PTR *PFNGLGENFRAMEBUFFERSPROC)(GLsizei n, GLuint * framebuffers); +typedef void (GLAD_API_PTR *PFNGLGENRENDERBUFFERSPROC)(GLsizei n, GLuint * renderbuffers); +typedef void (GLAD_API_PTR *PFNGLGENTEXTURESPROC)(GLsizei n, GLuint * textures); +typedef void (GLAD_API_PTR *PFNGLGENERATEMIPMAPPROC)(GLenum target); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEATTRIBPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETATTACHEDSHADERSPROC)(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders); +typedef GLint (GLAD_API_PTR *PFNGLGETATTRIBLOCATIONPROC)(GLuint program, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETBOOLEANVPROC)(GLenum pname, GLboolean * data); +typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef GLenum (GLAD_API_PTR *PFNGLGETERRORPROC)(void); +typedef void (GLAD_API_PTR *PFNGLGETFLOATVPROC)(GLenum pname, GLfloat * data); +typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum target, GLenum attachment, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETINTEGERVPROC)(GLenum pname, GLint * data); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMINFOLOGPROC)(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMIVPROC)(GLuint program, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog); +typedef void (GLAD_API_PTR *PFNGLGETSHADERPRECISIONFORMATPROC)(GLenum shadertype, GLenum precisiontype, GLint * range, GLint * precision); +typedef void (GLAD_API_PTR *PFNGLGETSHADERSOURCEPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source); +typedef void (GLAD_API_PTR *PFNGLGETSHADERIVPROC)(GLuint shader, GLenum pname, GLint * params); +typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGPROC)(GLenum name); +typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERFVPROC)(GLenum target, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef GLint (GLAD_API_PTR *PFNGLGETUNIFORMLOCATIONPROC)(GLuint program, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMFVPROC)(GLuint program, GLint location, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMIVPROC)(GLuint program, GLint location, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint index, GLenum pname, void ** pointer); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBFVPROC)(GLuint index, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIVPROC)(GLuint index, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLHINTPROC)(GLenum target, GLenum mode); +typedef GLboolean (GLAD_API_PTR *PFNGLISBUFFERPROC)(GLuint buffer); +typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDPROC)(GLenum cap); +typedef GLboolean (GLAD_API_PTR *PFNGLISFRAMEBUFFERPROC)(GLuint framebuffer); +typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMPROC)(GLuint program); +typedef GLboolean (GLAD_API_PTR *PFNGLISRENDERBUFFERPROC)(GLuint renderbuffer); +typedef GLboolean (GLAD_API_PTR *PFNGLISSHADERPROC)(GLuint shader); +typedef GLboolean (GLAD_API_PTR *PFNGLISTEXTUREPROC)(GLuint texture); +typedef void (GLAD_API_PTR *PFNGLLINEWIDTHPROC)(GLfloat width); +typedef void (GLAD_API_PTR *PFNGLLINKPROGRAMPROC)(GLuint program); +typedef void (GLAD_API_PTR *PFNGLPIXELSTOREIPROC)(GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLPOLYGONOFFSETPROC)(GLfloat factor, GLfloat units); +typedef void (GLAD_API_PTR *PFNGLREADPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels); +typedef void (GLAD_API_PTR *PFNGLRELEASESHADERCOMPILERPROC)(void); +typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLSAMPLECOVERAGEPROC)(GLfloat value, GLboolean invert); +typedef void (GLAD_API_PTR *PFNGLSCISSORPROC)(GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLSHADERBINARYPROC)(GLsizei count, const GLuint * shaders, GLenum binaryFormat, const void * binary, GLsizei length); +typedef void (GLAD_API_PTR *PFNGLSHADERSOURCEPROC)(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length); +typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCPROC)(GLenum func, GLint ref, GLuint mask); +typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCSEPARATEPROC)(GLenum face, GLenum func, GLint ref, GLuint mask); +typedef void (GLAD_API_PTR *PFNGLSTENCILMASKPROC)(GLuint mask); +typedef void (GLAD_API_PTR *PFNGLSTENCILMASKSEPARATEPROC)(GLenum face, GLuint mask); +typedef void (GLAD_API_PTR *PFNGLSTENCILOPPROC)(GLenum fail, GLenum zfail, GLenum zpass); +typedef void (GLAD_API_PTR *PFNGLSTENCILOPSEPARATEPROC)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +typedef void (GLAD_API_PTR *PFNGLTEXIMAGE2DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFPROC)(GLenum target, GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFVPROC)(GLenum target, GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIPROC)(GLenum target, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIVPROC)(GLenum target, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1FPROC)(GLint location, GLfloat v0); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1FVPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1IPROC)(GLint location, GLint v0); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1IVPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2FPROC)(GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2FVPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2IPROC)(GLint location, GLint v0, GLint v1); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2IVPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3FVPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3IPROC)(GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3IVPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4FVPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4IPROC)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4IVPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMPROC)(GLuint program); +typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMPROC)(GLuint program); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FPROC)(GLuint index, GLfloat x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FPROC)(GLuint index, GLfloat x, GLfloat y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBPOINTERPROC)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLVIEWPORTPROC)(GLint x, GLint y, GLsizei width, GLsizei height); + +typedef struct GladGLES2Context { + void* userptr; + + int ES_VERSION_2_0; + int OES_rgb8_rgba8; + + PFNGLACTIVETEXTUREPROC ActiveTexture; + PFNGLATTACHSHADERPROC AttachShader; + PFNGLBINDATTRIBLOCATIONPROC BindAttribLocation; + PFNGLBINDBUFFERPROC BindBuffer; + PFNGLBINDFRAMEBUFFERPROC BindFramebuffer; + PFNGLBINDRENDERBUFFERPROC BindRenderbuffer; + PFNGLBINDTEXTUREPROC BindTexture; + PFNGLBLENDCOLORPROC BlendColor; + PFNGLBLENDEQUATIONPROC BlendEquation; + PFNGLBLENDEQUATIONSEPARATEPROC BlendEquationSeparate; + PFNGLBLENDFUNCPROC BlendFunc; + PFNGLBLENDFUNCSEPARATEPROC BlendFuncSeparate; + PFNGLBUFFERDATAPROC BufferData; + PFNGLBUFFERSUBDATAPROC BufferSubData; + PFNGLCHECKFRAMEBUFFERSTATUSPROC CheckFramebufferStatus; + PFNGLCLEARPROC Clear; + PFNGLCLEARCOLORPROC ClearColor; + PFNGLCLEARDEPTHFPROC ClearDepthf; + PFNGLCLEARSTENCILPROC ClearStencil; + PFNGLCOLORMASKPROC ColorMask; + PFNGLCOMPILESHADERPROC CompileShader; + PFNGLCOMPRESSEDTEXIMAGE2DPROC CompressedTexImage2D; + PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC CompressedTexSubImage2D; + PFNGLCOPYTEXIMAGE2DPROC CopyTexImage2D; + PFNGLCOPYTEXSUBIMAGE2DPROC CopyTexSubImage2D; + PFNGLCREATEPROGRAMPROC CreateProgram; + PFNGLCREATESHADERPROC CreateShader; + PFNGLCULLFACEPROC CullFace; + PFNGLDELETEBUFFERSPROC DeleteBuffers; + PFNGLDELETEFRAMEBUFFERSPROC DeleteFramebuffers; + PFNGLDELETEPROGRAMPROC DeleteProgram; + PFNGLDELETERENDERBUFFERSPROC DeleteRenderbuffers; + PFNGLDELETESHADERPROC DeleteShader; + PFNGLDELETETEXTURESPROC DeleteTextures; + PFNGLDEPTHFUNCPROC DepthFunc; + PFNGLDEPTHMASKPROC DepthMask; + PFNGLDEPTHRANGEFPROC DepthRangef; + PFNGLDETACHSHADERPROC DetachShader; + PFNGLDISABLEPROC Disable; + PFNGLDISABLEVERTEXATTRIBARRAYPROC DisableVertexAttribArray; + PFNGLDRAWARRAYSPROC DrawArrays; + PFNGLDRAWELEMENTSPROC DrawElements; + PFNGLENABLEPROC Enable; + PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray; + PFNGLFINISHPROC Finish; + PFNGLFLUSHPROC Flush; + PFNGLFRAMEBUFFERRENDERBUFFERPROC FramebufferRenderbuffer; + PFNGLFRAMEBUFFERTEXTURE2DPROC FramebufferTexture2D; + PFNGLFRONTFACEPROC FrontFace; + PFNGLGENBUFFERSPROC GenBuffers; + PFNGLGENFRAMEBUFFERSPROC GenFramebuffers; + PFNGLGENRENDERBUFFERSPROC GenRenderbuffers; + PFNGLGENTEXTURESPROC GenTextures; + PFNGLGENERATEMIPMAPPROC GenerateMipmap; + PFNGLGETACTIVEATTRIBPROC GetActiveAttrib; + PFNGLGETACTIVEUNIFORMPROC GetActiveUniform; + PFNGLGETATTACHEDSHADERSPROC GetAttachedShaders; + PFNGLGETATTRIBLOCATIONPROC GetAttribLocation; + PFNGLGETBOOLEANVPROC GetBooleanv; + PFNGLGETBUFFERPARAMETERIVPROC GetBufferParameteriv; + PFNGLGETERRORPROC GetError; + PFNGLGETFLOATVPROC GetFloatv; + PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC GetFramebufferAttachmentParameteriv; + PFNGLGETINTEGERVPROC GetIntegerv; + PFNGLGETPROGRAMINFOLOGPROC GetProgramInfoLog; + PFNGLGETPROGRAMIVPROC GetProgramiv; + PFNGLGETRENDERBUFFERPARAMETERIVPROC GetRenderbufferParameteriv; + PFNGLGETSHADERINFOLOGPROC GetShaderInfoLog; + PFNGLGETSHADERPRECISIONFORMATPROC GetShaderPrecisionFormat; + PFNGLGETSHADERSOURCEPROC GetShaderSource; + PFNGLGETSHADERIVPROC GetShaderiv; + PFNGLGETSTRINGPROC GetString; + PFNGLGETTEXPARAMETERFVPROC GetTexParameterfv; + PFNGLGETTEXPARAMETERIVPROC GetTexParameteriv; + PFNGLGETUNIFORMLOCATIONPROC GetUniformLocation; + PFNGLGETUNIFORMFVPROC GetUniformfv; + PFNGLGETUNIFORMIVPROC GetUniformiv; + PFNGLGETVERTEXATTRIBPOINTERVPROC GetVertexAttribPointerv; + PFNGLGETVERTEXATTRIBFVPROC GetVertexAttribfv; + PFNGLGETVERTEXATTRIBIVPROC GetVertexAttribiv; + PFNGLHINTPROC Hint; + PFNGLISBUFFERPROC IsBuffer; + PFNGLISENABLEDPROC IsEnabled; + PFNGLISFRAMEBUFFERPROC IsFramebuffer; + PFNGLISPROGRAMPROC IsProgram; + PFNGLISRENDERBUFFERPROC IsRenderbuffer; + PFNGLISSHADERPROC IsShader; + PFNGLISTEXTUREPROC IsTexture; + PFNGLLINEWIDTHPROC LineWidth; + PFNGLLINKPROGRAMPROC LinkProgram; + PFNGLPIXELSTOREIPROC PixelStorei; + PFNGLPOLYGONOFFSETPROC PolygonOffset; + PFNGLREADPIXELSPROC ReadPixels; + PFNGLRELEASESHADERCOMPILERPROC ReleaseShaderCompiler; + PFNGLRENDERBUFFERSTORAGEPROC RenderbufferStorage; + PFNGLSAMPLECOVERAGEPROC SampleCoverage; + PFNGLSCISSORPROC Scissor; + PFNGLSHADERBINARYPROC ShaderBinary; + PFNGLSHADERSOURCEPROC ShaderSource; + PFNGLSTENCILFUNCPROC StencilFunc; + PFNGLSTENCILFUNCSEPARATEPROC StencilFuncSeparate; + PFNGLSTENCILMASKPROC StencilMask; + PFNGLSTENCILMASKSEPARATEPROC StencilMaskSeparate; + PFNGLSTENCILOPPROC StencilOp; + PFNGLSTENCILOPSEPARATEPROC StencilOpSeparate; + PFNGLTEXIMAGE2DPROC TexImage2D; + PFNGLTEXPARAMETERFPROC TexParameterf; + PFNGLTEXPARAMETERFVPROC TexParameterfv; + PFNGLTEXPARAMETERIPROC TexParameteri; + PFNGLTEXPARAMETERIVPROC TexParameteriv; + PFNGLTEXSUBIMAGE2DPROC TexSubImage2D; + PFNGLUNIFORM1FPROC Uniform1f; + PFNGLUNIFORM1FVPROC Uniform1fv; + PFNGLUNIFORM1IPROC Uniform1i; + PFNGLUNIFORM1IVPROC Uniform1iv; + PFNGLUNIFORM2FPROC Uniform2f; + PFNGLUNIFORM2FVPROC Uniform2fv; + PFNGLUNIFORM2IPROC Uniform2i; + PFNGLUNIFORM2IVPROC Uniform2iv; + PFNGLUNIFORM3FPROC Uniform3f; + PFNGLUNIFORM3FVPROC Uniform3fv; + PFNGLUNIFORM3IPROC Uniform3i; + PFNGLUNIFORM3IVPROC Uniform3iv; + PFNGLUNIFORM4FPROC Uniform4f; + PFNGLUNIFORM4FVPROC Uniform4fv; + PFNGLUNIFORM4IPROC Uniform4i; + PFNGLUNIFORM4IVPROC Uniform4iv; + PFNGLUNIFORMMATRIX2FVPROC UniformMatrix2fv; + PFNGLUNIFORMMATRIX3FVPROC UniformMatrix3fv; + PFNGLUNIFORMMATRIX4FVPROC UniformMatrix4fv; + PFNGLUSEPROGRAMPROC UseProgram; + PFNGLVALIDATEPROGRAMPROC ValidateProgram; + PFNGLVERTEXATTRIB1FPROC VertexAttrib1f; + PFNGLVERTEXATTRIB1FVPROC VertexAttrib1fv; + PFNGLVERTEXATTRIB2FPROC VertexAttrib2f; + PFNGLVERTEXATTRIB2FVPROC VertexAttrib2fv; + PFNGLVERTEXATTRIB3FPROC VertexAttrib3f; + PFNGLVERTEXATTRIB3FVPROC VertexAttrib3fv; + PFNGLVERTEXATTRIB4FPROC VertexAttrib4f; + PFNGLVERTEXATTRIB4FVPROC VertexAttrib4fv; + PFNGLVERTEXATTRIBPOINTERPROC VertexAttribPointer; + PFNGLVIEWPORTPROC Viewport; + +} GladGLES2Context; + + + + + + +GLAD_API_CALL int gladLoadGLES2ContextUserPtr(GladGLES2Context *context, GLADuserptrloadfunc load, void *userptr); +GLAD_API_CALL int gladLoadGLES2Context(GladGLES2Context *context, GLADloadfunc load); + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/thirdparty/glad/src/gl.c b/thirdparty/glad/src/gl.c new file mode 100644 index 000000000..d97b1ded4 --- /dev/null +++ b/thirdparty/glad/src/gl.c @@ -0,0 +1,2274 @@ +/** + * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0 + */ +#include +#include +#include +#include + +#ifndef GLAD_IMPL_UTIL_C_ +#define GLAD_IMPL_UTIL_C_ + +#ifdef _MSC_VER +#define GLAD_IMPL_UTIL_SSCANF sscanf_s +#else +#define GLAD_IMPL_UTIL_SSCANF sscanf +#endif + +#endif /* GLAD_IMPL_UTIL_C_ */ + +#ifdef __cplusplus +extern "C" { +#endif + + + + + + + + +static void glad_gl_load_GL_VERSION_1_0(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->VERSION_1_0) return; + context->BlendFunc = (PFNGLBLENDFUNCPROC) load(userptr, "glBlendFunc"); + context->Clear = (PFNGLCLEARPROC) load(userptr, "glClear"); + context->ClearColor = (PFNGLCLEARCOLORPROC) load(userptr, "glClearColor"); + context->ClearDepth = (PFNGLCLEARDEPTHPROC) load(userptr, "glClearDepth"); + context->ClearStencil = (PFNGLCLEARSTENCILPROC) load(userptr, "glClearStencil"); + context->ColorMask = (PFNGLCOLORMASKPROC) load(userptr, "glColorMask"); + context->CullFace = (PFNGLCULLFACEPROC) load(userptr, "glCullFace"); + context->DepthFunc = (PFNGLDEPTHFUNCPROC) load(userptr, "glDepthFunc"); + context->DepthMask = (PFNGLDEPTHMASKPROC) load(userptr, "glDepthMask"); + context->DepthRange = (PFNGLDEPTHRANGEPROC) load(userptr, "glDepthRange"); + context->Disable = (PFNGLDISABLEPROC) load(userptr, "glDisable"); + context->DrawBuffer = (PFNGLDRAWBUFFERPROC) load(userptr, "glDrawBuffer"); + context->Enable = (PFNGLENABLEPROC) load(userptr, "glEnable"); + context->Finish = (PFNGLFINISHPROC) load(userptr, "glFinish"); + context->Flush = (PFNGLFLUSHPROC) load(userptr, "glFlush"); + context->FrontFace = (PFNGLFRONTFACEPROC) load(userptr, "glFrontFace"); + context->GetBooleanv = (PFNGLGETBOOLEANVPROC) load(userptr, "glGetBooleanv"); + context->GetDoublev = (PFNGLGETDOUBLEVPROC) load(userptr, "glGetDoublev"); + context->GetError = (PFNGLGETERRORPROC) load(userptr, "glGetError"); + context->GetFloatv = (PFNGLGETFLOATVPROC) load(userptr, "glGetFloatv"); + context->GetIntegerv = (PFNGLGETINTEGERVPROC) load(userptr, "glGetIntegerv"); + context->GetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString"); + context->GetTexImage = (PFNGLGETTEXIMAGEPROC) load(userptr, "glGetTexImage"); + context->GetTexLevelParameterfv = (PFNGLGETTEXLEVELPARAMETERFVPROC) load(userptr, "glGetTexLevelParameterfv"); + context->GetTexLevelParameteriv = (PFNGLGETTEXLEVELPARAMETERIVPROC) load(userptr, "glGetTexLevelParameteriv"); + context->GetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC) load(userptr, "glGetTexParameterfv"); + context->GetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC) load(userptr, "glGetTexParameteriv"); + context->Hint = (PFNGLHINTPROC) load(userptr, "glHint"); + context->IsEnabled = (PFNGLISENABLEDPROC) load(userptr, "glIsEnabled"); + context->LineWidth = (PFNGLLINEWIDTHPROC) load(userptr, "glLineWidth"); + context->LogicOp = (PFNGLLOGICOPPROC) load(userptr, "glLogicOp"); + context->PixelStoref = (PFNGLPIXELSTOREFPROC) load(userptr, "glPixelStoref"); + context->PixelStorei = (PFNGLPIXELSTOREIPROC) load(userptr, "glPixelStorei"); + context->PointSize = (PFNGLPOINTSIZEPROC) load(userptr, "glPointSize"); + context->PolygonMode = (PFNGLPOLYGONMODEPROC) load(userptr, "glPolygonMode"); + context->ReadBuffer = (PFNGLREADBUFFERPROC) load(userptr, "glReadBuffer"); + context->ReadPixels = (PFNGLREADPIXELSPROC) load(userptr, "glReadPixels"); + context->Scissor = (PFNGLSCISSORPROC) load(userptr, "glScissor"); + context->StencilFunc = (PFNGLSTENCILFUNCPROC) load(userptr, "glStencilFunc"); + context->StencilMask = (PFNGLSTENCILMASKPROC) load(userptr, "glStencilMask"); + context->StencilOp = (PFNGLSTENCILOPPROC) load(userptr, "glStencilOp"); + context->TexImage1D = (PFNGLTEXIMAGE1DPROC) load(userptr, "glTexImage1D"); + context->TexImage2D = (PFNGLTEXIMAGE2DPROC) load(userptr, "glTexImage2D"); + context->TexParameterf = (PFNGLTEXPARAMETERFPROC) load(userptr, "glTexParameterf"); + context->TexParameterfv = (PFNGLTEXPARAMETERFVPROC) load(userptr, "glTexParameterfv"); + context->TexParameteri = (PFNGLTEXPARAMETERIPROC) load(userptr, "glTexParameteri"); + context->TexParameteriv = (PFNGLTEXPARAMETERIVPROC) load(userptr, "glTexParameteriv"); + context->Viewport = (PFNGLVIEWPORTPROC) load(userptr, "glViewport"); +} +static void glad_gl_load_GL_VERSION_1_1(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->VERSION_1_1) return; + context->BindTexture = (PFNGLBINDTEXTUREPROC) load(userptr, "glBindTexture"); + context->CopyTexImage1D = (PFNGLCOPYTEXIMAGE1DPROC) load(userptr, "glCopyTexImage1D"); + context->CopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC) load(userptr, "glCopyTexImage2D"); + context->CopyTexSubImage1D = (PFNGLCOPYTEXSUBIMAGE1DPROC) load(userptr, "glCopyTexSubImage1D"); + context->CopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC) load(userptr, "glCopyTexSubImage2D"); + context->DeleteTextures = (PFNGLDELETETEXTURESPROC) load(userptr, "glDeleteTextures"); + context->DrawArrays = (PFNGLDRAWARRAYSPROC) load(userptr, "glDrawArrays"); + context->DrawElements = (PFNGLDRAWELEMENTSPROC) load(userptr, "glDrawElements"); + context->GenTextures = (PFNGLGENTEXTURESPROC) load(userptr, "glGenTextures"); + context->IsTexture = (PFNGLISTEXTUREPROC) load(userptr, "glIsTexture"); + context->PolygonOffset = (PFNGLPOLYGONOFFSETPROC) load(userptr, "glPolygonOffset"); + context->TexSubImage1D = (PFNGLTEXSUBIMAGE1DPROC) load(userptr, "glTexSubImage1D"); + context->TexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC) load(userptr, "glTexSubImage2D"); +} +static void glad_gl_load_GL_VERSION_1_2(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->VERSION_1_2) return; + context->CopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC) load(userptr, "glCopyTexSubImage3D"); + context->DrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) load(userptr, "glDrawRangeElements"); + context->TexImage3D = (PFNGLTEXIMAGE3DPROC) load(userptr, "glTexImage3D"); + context->TexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC) load(userptr, "glTexSubImage3D"); +} +static void glad_gl_load_GL_VERSION_1_3(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->VERSION_1_3) return; + context->ActiveTexture = (PFNGLACTIVETEXTUREPROC) load(userptr, "glActiveTexture"); + context->CompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC) load(userptr, "glCompressedTexImage1D"); + context->CompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) load(userptr, "glCompressedTexImage2D"); + context->CompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC) load(userptr, "glCompressedTexImage3D"); + context->CompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) load(userptr, "glCompressedTexSubImage1D"); + context->CompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) load(userptr, "glCompressedTexSubImage2D"); + context->CompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) load(userptr, "glCompressedTexSubImage3D"); + context->GetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC) load(userptr, "glGetCompressedTexImage"); + context->SampleCoverage = (PFNGLSAMPLECOVERAGEPROC) load(userptr, "glSampleCoverage"); +} +static void glad_gl_load_GL_VERSION_1_4(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->VERSION_1_4) return; + context->BlendColor = (PFNGLBLENDCOLORPROC) load(userptr, "glBlendColor"); + context->BlendEquation = (PFNGLBLENDEQUATIONPROC) load(userptr, "glBlendEquation"); + context->BlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC) load(userptr, "glBlendFuncSeparate"); + context->MultiDrawArrays = (PFNGLMULTIDRAWARRAYSPROC) load(userptr, "glMultiDrawArrays"); + context->MultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC) load(userptr, "glMultiDrawElements"); + context->PointParameterf = (PFNGLPOINTPARAMETERFPROC) load(userptr, "glPointParameterf"); + context->PointParameterfv = (PFNGLPOINTPARAMETERFVPROC) load(userptr, "glPointParameterfv"); + context->PointParameteri = (PFNGLPOINTPARAMETERIPROC) load(userptr, "glPointParameteri"); + context->PointParameteriv = (PFNGLPOINTPARAMETERIVPROC) load(userptr, "glPointParameteriv"); +} +static void glad_gl_load_GL_VERSION_1_5(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->VERSION_1_5) return; + context->BeginQuery = (PFNGLBEGINQUERYPROC) load(userptr, "glBeginQuery"); + context->BindBuffer = (PFNGLBINDBUFFERPROC) load(userptr, "glBindBuffer"); + context->BufferData = (PFNGLBUFFERDATAPROC) load(userptr, "glBufferData"); + context->BufferSubData = (PFNGLBUFFERSUBDATAPROC) load(userptr, "glBufferSubData"); + context->DeleteBuffers = (PFNGLDELETEBUFFERSPROC) load(userptr, "glDeleteBuffers"); + context->DeleteQueries = (PFNGLDELETEQUERIESPROC) load(userptr, "glDeleteQueries"); + context->EndQuery = (PFNGLENDQUERYPROC) load(userptr, "glEndQuery"); + context->GenBuffers = (PFNGLGENBUFFERSPROC) load(userptr, "glGenBuffers"); + context->GenQueries = (PFNGLGENQUERIESPROC) load(userptr, "glGenQueries"); + context->GetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC) load(userptr, "glGetBufferParameteriv"); + context->GetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC) load(userptr, "glGetBufferPointerv"); + context->GetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC) load(userptr, "glGetBufferSubData"); + context->GetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC) load(userptr, "glGetQueryObjectiv"); + context->GetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC) load(userptr, "glGetQueryObjectuiv"); + context->GetQueryiv = (PFNGLGETQUERYIVPROC) load(userptr, "glGetQueryiv"); + context->IsBuffer = (PFNGLISBUFFERPROC) load(userptr, "glIsBuffer"); + context->IsQuery = (PFNGLISQUERYPROC) load(userptr, "glIsQuery"); + context->MapBuffer = (PFNGLMAPBUFFERPROC) load(userptr, "glMapBuffer"); + context->UnmapBuffer = (PFNGLUNMAPBUFFERPROC) load(userptr, "glUnmapBuffer"); +} +static void glad_gl_load_GL_VERSION_2_0(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->VERSION_2_0) return; + context->AttachShader = (PFNGLATTACHSHADERPROC) load(userptr, "glAttachShader"); + context->BindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC) load(userptr, "glBindAttribLocation"); + context->BlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC) load(userptr, "glBlendEquationSeparate"); + context->CompileShader = (PFNGLCOMPILESHADERPROC) load(userptr, "glCompileShader"); + context->CreateProgram = (PFNGLCREATEPROGRAMPROC) load(userptr, "glCreateProgram"); + context->CreateShader = (PFNGLCREATESHADERPROC) load(userptr, "glCreateShader"); + context->DeleteProgram = (PFNGLDELETEPROGRAMPROC) load(userptr, "glDeleteProgram"); + context->DeleteShader = (PFNGLDELETESHADERPROC) load(userptr, "glDeleteShader"); + context->DetachShader = (PFNGLDETACHSHADERPROC) load(userptr, "glDetachShader"); + context->DisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) load(userptr, "glDisableVertexAttribArray"); + context->DrawBuffers = (PFNGLDRAWBUFFERSPROC) load(userptr, "glDrawBuffers"); + context->EnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) load(userptr, "glEnableVertexAttribArray"); + context->GetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC) load(userptr, "glGetActiveAttrib"); + context->GetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC) load(userptr, "glGetActiveUniform"); + context->GetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC) load(userptr, "glGetAttachedShaders"); + context->GetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) load(userptr, "glGetAttribLocation"); + context->GetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) load(userptr, "glGetProgramInfoLog"); + context->GetProgramiv = (PFNGLGETPROGRAMIVPROC) load(userptr, "glGetProgramiv"); + context->GetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) load(userptr, "glGetShaderInfoLog"); + context->GetShaderSource = (PFNGLGETSHADERSOURCEPROC) load(userptr, "glGetShaderSource"); + context->GetShaderiv = (PFNGLGETSHADERIVPROC) load(userptr, "glGetShaderiv"); + context->GetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) load(userptr, "glGetUniformLocation"); + context->GetUniformfv = (PFNGLGETUNIFORMFVPROC) load(userptr, "glGetUniformfv"); + context->GetUniformiv = (PFNGLGETUNIFORMIVPROC) load(userptr, "glGetUniformiv"); + context->GetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC) load(userptr, "glGetVertexAttribPointerv"); + context->GetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC) load(userptr, "glGetVertexAttribdv"); + context->GetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC) load(userptr, "glGetVertexAttribfv"); + context->GetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC) load(userptr, "glGetVertexAttribiv"); + context->IsProgram = (PFNGLISPROGRAMPROC) load(userptr, "glIsProgram"); + context->IsShader = (PFNGLISSHADERPROC) load(userptr, "glIsShader"); + context->LinkProgram = (PFNGLLINKPROGRAMPROC) load(userptr, "glLinkProgram"); + context->ShaderSource = (PFNGLSHADERSOURCEPROC) load(userptr, "glShaderSource"); + context->StencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC) load(userptr, "glStencilFuncSeparate"); + context->StencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC) load(userptr, "glStencilMaskSeparate"); + context->StencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC) load(userptr, "glStencilOpSeparate"); + context->Uniform1f = (PFNGLUNIFORM1FPROC) load(userptr, "glUniform1f"); + context->Uniform1fv = (PFNGLUNIFORM1FVPROC) load(userptr, "glUniform1fv"); + context->Uniform1i = (PFNGLUNIFORM1IPROC) load(userptr, "glUniform1i"); + context->Uniform1iv = (PFNGLUNIFORM1IVPROC) load(userptr, "glUniform1iv"); + context->Uniform2f = (PFNGLUNIFORM2FPROC) load(userptr, "glUniform2f"); + context->Uniform2fv = (PFNGLUNIFORM2FVPROC) load(userptr, "glUniform2fv"); + context->Uniform2i = (PFNGLUNIFORM2IPROC) load(userptr, "glUniform2i"); + context->Uniform2iv = (PFNGLUNIFORM2IVPROC) load(userptr, "glUniform2iv"); + context->Uniform3f = (PFNGLUNIFORM3FPROC) load(userptr, "glUniform3f"); + context->Uniform3fv = (PFNGLUNIFORM3FVPROC) load(userptr, "glUniform3fv"); + context->Uniform3i = (PFNGLUNIFORM3IPROC) load(userptr, "glUniform3i"); + context->Uniform3iv = (PFNGLUNIFORM3IVPROC) load(userptr, "glUniform3iv"); + context->Uniform4f = (PFNGLUNIFORM4FPROC) load(userptr, "glUniform4f"); + context->Uniform4fv = (PFNGLUNIFORM4FVPROC) load(userptr, "glUniform4fv"); + context->Uniform4i = (PFNGLUNIFORM4IPROC) load(userptr, "glUniform4i"); + context->Uniform4iv = (PFNGLUNIFORM4IVPROC) load(userptr, "glUniform4iv"); + context->UniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC) load(userptr, "glUniformMatrix2fv"); + context->UniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC) load(userptr, "glUniformMatrix3fv"); + context->UniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) load(userptr, "glUniformMatrix4fv"); + context->UseProgram = (PFNGLUSEPROGRAMPROC) load(userptr, "glUseProgram"); + context->ValidateProgram = (PFNGLVALIDATEPROGRAMPROC) load(userptr, "glValidateProgram"); + context->VertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC) load(userptr, "glVertexAttrib1d"); + context->VertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC) load(userptr, "glVertexAttrib1dv"); + context->VertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC) load(userptr, "glVertexAttrib1f"); + context->VertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC) load(userptr, "glVertexAttrib1fv"); + context->VertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC) load(userptr, "glVertexAttrib1s"); + context->VertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC) load(userptr, "glVertexAttrib1sv"); + context->VertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC) load(userptr, "glVertexAttrib2d"); + context->VertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC) load(userptr, "glVertexAttrib2dv"); + context->VertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC) load(userptr, "glVertexAttrib2f"); + context->VertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC) load(userptr, "glVertexAttrib2fv"); + context->VertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC) load(userptr, "glVertexAttrib2s"); + context->VertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC) load(userptr, "glVertexAttrib2sv"); + context->VertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC) load(userptr, "glVertexAttrib3d"); + context->VertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC) load(userptr, "glVertexAttrib3dv"); + context->VertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC) load(userptr, "glVertexAttrib3f"); + context->VertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC) load(userptr, "glVertexAttrib3fv"); + context->VertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC) load(userptr, "glVertexAttrib3s"); + context->VertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC) load(userptr, "glVertexAttrib3sv"); + context->VertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBVPROC) load(userptr, "glVertexAttrib4Nbv"); + context->VertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIVPROC) load(userptr, "glVertexAttrib4Niv"); + context->VertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSVPROC) load(userptr, "glVertexAttrib4Nsv"); + context->VertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC) load(userptr, "glVertexAttrib4Nub"); + context->VertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC) load(userptr, "glVertexAttrib4Nubv"); + context->VertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIVPROC) load(userptr, "glVertexAttrib4Nuiv"); + context->VertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSVPROC) load(userptr, "glVertexAttrib4Nusv"); + context->VertexAttrib4bv = (PFNGLVERTEXATTRIB4BVPROC) load(userptr, "glVertexAttrib4bv"); + context->VertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC) load(userptr, "glVertexAttrib4d"); + context->VertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC) load(userptr, "glVertexAttrib4dv"); + context->VertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC) load(userptr, "glVertexAttrib4f"); + context->VertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC) load(userptr, "glVertexAttrib4fv"); + context->VertexAttrib4iv = (PFNGLVERTEXATTRIB4IVPROC) load(userptr, "glVertexAttrib4iv"); + context->VertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC) load(userptr, "glVertexAttrib4s"); + context->VertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC) load(userptr, "glVertexAttrib4sv"); + context->VertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBVPROC) load(userptr, "glVertexAttrib4ubv"); + context->VertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC) load(userptr, "glVertexAttrib4uiv"); + context->VertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC) load(userptr, "glVertexAttrib4usv"); + context->VertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) load(userptr, "glVertexAttribPointer"); +} +static void glad_gl_load_GL_VERSION_2_1(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->VERSION_2_1) return; + context->UniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC) load(userptr, "glUniformMatrix2x3fv"); + context->UniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC) load(userptr, "glUniformMatrix2x4fv"); + context->UniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC) load(userptr, "glUniformMatrix3x2fv"); + context->UniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC) load(userptr, "glUniformMatrix3x4fv"); + context->UniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC) load(userptr, "glUniformMatrix4x2fv"); + context->UniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC) load(userptr, "glUniformMatrix4x3fv"); +} +static void glad_gl_load_GL_VERSION_3_0(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->VERSION_3_0) return; + context->BeginConditionalRender = (PFNGLBEGINCONDITIONALRENDERPROC) load(userptr, "glBeginConditionalRender"); + context->BeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) load(userptr, "glBeginTransformFeedback"); + context->BindBufferBase = (PFNGLBINDBUFFERBASEPROC) load(userptr, "glBindBufferBase"); + context->BindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load(userptr, "glBindBufferRange"); + context->BindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC) load(userptr, "glBindFragDataLocation"); + context->BindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) load(userptr, "glBindFramebuffer"); + context->BindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) load(userptr, "glBindRenderbuffer"); + context->BindVertexArray = (PFNGLBINDVERTEXARRAYPROC) load(userptr, "glBindVertexArray"); + context->BlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) load(userptr, "glBlitFramebuffer"); + context->CheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) load(userptr, "glCheckFramebufferStatus"); + context->ClampColor = (PFNGLCLAMPCOLORPROC) load(userptr, "glClampColor"); + context->ClearBufferfi = (PFNGLCLEARBUFFERFIPROC) load(userptr, "glClearBufferfi"); + context->ClearBufferfv = (PFNGLCLEARBUFFERFVPROC) load(userptr, "glClearBufferfv"); + context->ClearBufferiv = (PFNGLCLEARBUFFERIVPROC) load(userptr, "glClearBufferiv"); + context->ClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC) load(userptr, "glClearBufferuiv"); + context->ColorMaski = (PFNGLCOLORMASKIPROC) load(userptr, "glColorMaski"); + context->DeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) load(userptr, "glDeleteFramebuffers"); + context->DeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) load(userptr, "glDeleteRenderbuffers"); + context->DeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) load(userptr, "glDeleteVertexArrays"); + context->Disablei = (PFNGLDISABLEIPROC) load(userptr, "glDisablei"); + context->Enablei = (PFNGLENABLEIPROC) load(userptr, "glEnablei"); + context->EndConditionalRender = (PFNGLENDCONDITIONALRENDERPROC) load(userptr, "glEndConditionalRender"); + context->EndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) load(userptr, "glEndTransformFeedback"); + context->FlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) load(userptr, "glFlushMappedBufferRange"); + context->FramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) load(userptr, "glFramebufferRenderbuffer"); + context->FramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC) load(userptr, "glFramebufferTexture1D"); + context->FramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) load(userptr, "glFramebufferTexture2D"); + context->FramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC) load(userptr, "glFramebufferTexture3D"); + context->FramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) load(userptr, "glFramebufferTextureLayer"); + context->GenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) load(userptr, "glGenFramebuffers"); + context->GenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) load(userptr, "glGenRenderbuffers"); + context->GenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) load(userptr, "glGenVertexArrays"); + context->GenerateMipmap = (PFNGLGENERATEMIPMAPPROC) load(userptr, "glGenerateMipmap"); + context->GetBooleani_v = (PFNGLGETBOOLEANI_VPROC) load(userptr, "glGetBooleani_v"); + context->GetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC) load(userptr, "glGetFragDataLocation"); + context->GetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load(userptr, "glGetFramebufferAttachmentParameteriv"); + context->GetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load(userptr, "glGetIntegeri_v"); + context->GetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) load(userptr, "glGetRenderbufferParameteriv"); + context->GetStringi = (PFNGLGETSTRINGIPROC) load(userptr, "glGetStringi"); + context->GetTexParameterIiv = (PFNGLGETTEXPARAMETERIIVPROC) load(userptr, "glGetTexParameterIiv"); + context->GetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIVPROC) load(userptr, "glGetTexParameterIuiv"); + context->GetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) load(userptr, "glGetTransformFeedbackVarying"); + context->GetUniformuiv = (PFNGLGETUNIFORMUIVPROC) load(userptr, "glGetUniformuiv"); + context->GetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC) load(userptr, "glGetVertexAttribIiv"); + context->GetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC) load(userptr, "glGetVertexAttribIuiv"); + context->IsEnabledi = (PFNGLISENABLEDIPROC) load(userptr, "glIsEnabledi"); + context->IsFramebuffer = (PFNGLISFRAMEBUFFERPROC) load(userptr, "glIsFramebuffer"); + context->IsRenderbuffer = (PFNGLISRENDERBUFFERPROC) load(userptr, "glIsRenderbuffer"); + context->IsVertexArray = (PFNGLISVERTEXARRAYPROC) load(userptr, "glIsVertexArray"); + context->MapBufferRange = (PFNGLMAPBUFFERRANGEPROC) load(userptr, "glMapBufferRange"); + context->RenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) load(userptr, "glRenderbufferStorage"); + context->RenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) load(userptr, "glRenderbufferStorageMultisample"); + context->TexParameterIiv = (PFNGLTEXPARAMETERIIVPROC) load(userptr, "glTexParameterIiv"); + context->TexParameterIuiv = (PFNGLTEXPARAMETERIUIVPROC) load(userptr, "glTexParameterIuiv"); + context->TransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) load(userptr, "glTransformFeedbackVaryings"); + context->Uniform1ui = (PFNGLUNIFORM1UIPROC) load(userptr, "glUniform1ui"); + context->Uniform1uiv = (PFNGLUNIFORM1UIVPROC) load(userptr, "glUniform1uiv"); + context->Uniform2ui = (PFNGLUNIFORM2UIPROC) load(userptr, "glUniform2ui"); + context->Uniform2uiv = (PFNGLUNIFORM2UIVPROC) load(userptr, "glUniform2uiv"); + context->Uniform3ui = (PFNGLUNIFORM3UIPROC) load(userptr, "glUniform3ui"); + context->Uniform3uiv = (PFNGLUNIFORM3UIVPROC) load(userptr, "glUniform3uiv"); + context->Uniform4ui = (PFNGLUNIFORM4UIPROC) load(userptr, "glUniform4ui"); + context->Uniform4uiv = (PFNGLUNIFORM4UIVPROC) load(userptr, "glUniform4uiv"); + context->VertexAttribI1i = (PFNGLVERTEXATTRIBI1IPROC) load(userptr, "glVertexAttribI1i"); + context->VertexAttribI1iv = (PFNGLVERTEXATTRIBI1IVPROC) load(userptr, "glVertexAttribI1iv"); + context->VertexAttribI1ui = (PFNGLVERTEXATTRIBI1UIPROC) load(userptr, "glVertexAttribI1ui"); + context->VertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIVPROC) load(userptr, "glVertexAttribI1uiv"); + context->VertexAttribI2i = (PFNGLVERTEXATTRIBI2IPROC) load(userptr, "glVertexAttribI2i"); + context->VertexAttribI2iv = (PFNGLVERTEXATTRIBI2IVPROC) load(userptr, "glVertexAttribI2iv"); + context->VertexAttribI2ui = (PFNGLVERTEXATTRIBI2UIPROC) load(userptr, "glVertexAttribI2ui"); + context->VertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIVPROC) load(userptr, "glVertexAttribI2uiv"); + context->VertexAttribI3i = (PFNGLVERTEXATTRIBI3IPROC) load(userptr, "glVertexAttribI3i"); + context->VertexAttribI3iv = (PFNGLVERTEXATTRIBI3IVPROC) load(userptr, "glVertexAttribI3iv"); + context->VertexAttribI3ui = (PFNGLVERTEXATTRIBI3UIPROC) load(userptr, "glVertexAttribI3ui"); + context->VertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIVPROC) load(userptr, "glVertexAttribI3uiv"); + context->VertexAttribI4bv = (PFNGLVERTEXATTRIBI4BVPROC) load(userptr, "glVertexAttribI4bv"); + context->VertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC) load(userptr, "glVertexAttribI4i"); + context->VertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC) load(userptr, "glVertexAttribI4iv"); + context->VertexAttribI4sv = (PFNGLVERTEXATTRIBI4SVPROC) load(userptr, "glVertexAttribI4sv"); + context->VertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBVPROC) load(userptr, "glVertexAttribI4ubv"); + context->VertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC) load(userptr, "glVertexAttribI4ui"); + context->VertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC) load(userptr, "glVertexAttribI4uiv"); + context->VertexAttribI4usv = (PFNGLVERTEXATTRIBI4USVPROC) load(userptr, "glVertexAttribI4usv"); + context->VertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) load(userptr, "glVertexAttribIPointer"); +} +static void glad_gl_load_GL_VERSION_3_1(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->VERSION_3_1) return; + context->BindBufferBase = (PFNGLBINDBUFFERBASEPROC) load(userptr, "glBindBufferBase"); + context->BindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load(userptr, "glBindBufferRange"); + context->CopyBufferSubData = (PFNGLCOPYBUFFERSUBDATAPROC) load(userptr, "glCopyBufferSubData"); + context->DrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC) load(userptr, "glDrawArraysInstanced"); + context->DrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC) load(userptr, "glDrawElementsInstanced"); + context->GetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) load(userptr, "glGetActiveUniformBlockName"); + context->GetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC) load(userptr, "glGetActiveUniformBlockiv"); + context->GetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAMEPROC) load(userptr, "glGetActiveUniformName"); + context->GetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC) load(userptr, "glGetActiveUniformsiv"); + context->GetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load(userptr, "glGetIntegeri_v"); + context->GetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC) load(userptr, "glGetUniformBlockIndex"); + context->GetUniformIndices = (PFNGLGETUNIFORMINDICESPROC) load(userptr, "glGetUniformIndices"); + context->PrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEXPROC) load(userptr, "glPrimitiveRestartIndex"); + context->TexBuffer = (PFNGLTEXBUFFERPROC) load(userptr, "glTexBuffer"); + context->UniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC) load(userptr, "glUniformBlockBinding"); +} +static void glad_gl_load_GL_VERSION_3_2(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->VERSION_3_2) return; + context->ClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) load(userptr, "glClientWaitSync"); + context->DeleteSync = (PFNGLDELETESYNCPROC) load(userptr, "glDeleteSync"); + context->DrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC) load(userptr, "glDrawElementsBaseVertex"); + context->DrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) load(userptr, "glDrawElementsInstancedBaseVertex"); + context->DrawRangeElementsBaseVertex = (PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) load(userptr, "glDrawRangeElementsBaseVertex"); + context->FenceSync = (PFNGLFENCESYNCPROC) load(userptr, "glFenceSync"); + context->FramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC) load(userptr, "glFramebufferTexture"); + context->GetBufferParameteri64v = (PFNGLGETBUFFERPARAMETERI64VPROC) load(userptr, "glGetBufferParameteri64v"); + context->GetInteger64i_v = (PFNGLGETINTEGER64I_VPROC) load(userptr, "glGetInteger64i_v"); + context->GetInteger64v = (PFNGLGETINTEGER64VPROC) load(userptr, "glGetInteger64v"); + context->GetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) load(userptr, "glGetMultisamplefv"); + context->GetSynciv = (PFNGLGETSYNCIVPROC) load(userptr, "glGetSynciv"); + context->IsSync = (PFNGLISSYNCPROC) load(userptr, "glIsSync"); + context->MultiDrawElementsBaseVertex = (PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) load(userptr, "glMultiDrawElementsBaseVertex"); + context->ProvokingVertex = (PFNGLPROVOKINGVERTEXPROC) load(userptr, "glProvokingVertex"); + context->SampleMaski = (PFNGLSAMPLEMASKIPROC) load(userptr, "glSampleMaski"); + context->TexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) load(userptr, "glTexImage2DMultisample"); + context->TexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) load(userptr, "glTexImage3DMultisample"); + context->WaitSync = (PFNGLWAITSYNCPROC) load(userptr, "glWaitSync"); +} +static void glad_gl_load_GL_APPLE_flush_buffer_range(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->APPLE_flush_buffer_range) return; + context->BufferParameteriAPPLE = (PFNGLBUFFERPARAMETERIAPPLEPROC) load(userptr, "glBufferParameteriAPPLE"); + context->FlushMappedBufferRangeAPPLE = (PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC) load(userptr, "glFlushMappedBufferRangeAPPLE"); +} +static void glad_gl_load_GL_APPLE_vertex_array_object(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->APPLE_vertex_array_object) return; + context->BindVertexArrayAPPLE = (PFNGLBINDVERTEXARRAYAPPLEPROC) load(userptr, "glBindVertexArrayAPPLE"); + context->DeleteVertexArraysAPPLE = (PFNGLDELETEVERTEXARRAYSAPPLEPROC) load(userptr, "glDeleteVertexArraysAPPLE"); + context->GenVertexArraysAPPLE = (PFNGLGENVERTEXARRAYSAPPLEPROC) load(userptr, "glGenVertexArraysAPPLE"); + context->IsVertexArrayAPPLE = (PFNGLISVERTEXARRAYAPPLEPROC) load(userptr, "glIsVertexArrayAPPLE"); +} +static void glad_gl_load_GL_ARB_color_buffer_float(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_color_buffer_float) return; + context->ClampColorARB = (PFNGLCLAMPCOLORARBPROC) load(userptr, "glClampColorARB"); +} +static void glad_gl_load_GL_ARB_copy_buffer(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_copy_buffer) return; + context->CopyBufferSubData = (PFNGLCOPYBUFFERSUBDATAPROC) load(userptr, "glCopyBufferSubData"); +} +static void glad_gl_load_GL_ARB_draw_buffers(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_draw_buffers) return; + context->DrawBuffersARB = (PFNGLDRAWBUFFERSARBPROC) load(userptr, "glDrawBuffersARB"); +} +static void glad_gl_load_GL_ARB_draw_elements_base_vertex(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_draw_elements_base_vertex) return; + context->DrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC) load(userptr, "glDrawElementsBaseVertex"); + context->DrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) load(userptr, "glDrawElementsInstancedBaseVertex"); + context->DrawRangeElementsBaseVertex = (PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) load(userptr, "glDrawRangeElementsBaseVertex"); + context->MultiDrawElementsBaseVertex = (PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) load(userptr, "glMultiDrawElementsBaseVertex"); +} +static void glad_gl_load_GL_ARB_draw_instanced(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_draw_instanced) return; + context->DrawArraysInstancedARB = (PFNGLDRAWARRAYSINSTANCEDARBPROC) load(userptr, "glDrawArraysInstancedARB"); + context->DrawElementsInstancedARB = (PFNGLDRAWELEMENTSINSTANCEDARBPROC) load(userptr, "glDrawElementsInstancedARB"); +} +static void glad_gl_load_GL_ARB_framebuffer_object(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_framebuffer_object) return; + context->BindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) load(userptr, "glBindFramebuffer"); + context->BindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) load(userptr, "glBindRenderbuffer"); + context->BlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) load(userptr, "glBlitFramebuffer"); + context->CheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) load(userptr, "glCheckFramebufferStatus"); + context->DeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) load(userptr, "glDeleteFramebuffers"); + context->DeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) load(userptr, "glDeleteRenderbuffers"); + context->FramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) load(userptr, "glFramebufferRenderbuffer"); + context->FramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC) load(userptr, "glFramebufferTexture1D"); + context->FramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) load(userptr, "glFramebufferTexture2D"); + context->FramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC) load(userptr, "glFramebufferTexture3D"); + context->FramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) load(userptr, "glFramebufferTextureLayer"); + context->GenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) load(userptr, "glGenFramebuffers"); + context->GenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) load(userptr, "glGenRenderbuffers"); + context->GenerateMipmap = (PFNGLGENERATEMIPMAPPROC) load(userptr, "glGenerateMipmap"); + context->GetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load(userptr, "glGetFramebufferAttachmentParameteriv"); + context->GetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) load(userptr, "glGetRenderbufferParameteriv"); + context->IsFramebuffer = (PFNGLISFRAMEBUFFERPROC) load(userptr, "glIsFramebuffer"); + context->IsRenderbuffer = (PFNGLISRENDERBUFFERPROC) load(userptr, "glIsRenderbuffer"); + context->RenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) load(userptr, "glRenderbufferStorage"); + context->RenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) load(userptr, "glRenderbufferStorageMultisample"); +} +static void glad_gl_load_GL_ARB_geometry_shader4(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_geometry_shader4) return; + context->FramebufferTextureARB = (PFNGLFRAMEBUFFERTEXTUREARBPROC) load(userptr, "glFramebufferTextureARB"); + context->FramebufferTextureFaceARB = (PFNGLFRAMEBUFFERTEXTUREFACEARBPROC) load(userptr, "glFramebufferTextureFaceARB"); + context->FramebufferTextureLayerARB = (PFNGLFRAMEBUFFERTEXTURELAYERARBPROC) load(userptr, "glFramebufferTextureLayerARB"); + context->ProgramParameteriARB = (PFNGLPROGRAMPARAMETERIARBPROC) load(userptr, "glProgramParameteriARB"); +} +static void glad_gl_load_GL_ARB_imaging(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_imaging) return; + context->BlendColor = (PFNGLBLENDCOLORPROC) load(userptr, "glBlendColor"); + context->BlendEquation = (PFNGLBLENDEQUATIONPROC) load(userptr, "glBlendEquation"); +} +static void glad_gl_load_GL_ARB_map_buffer_range(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_map_buffer_range) return; + context->FlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) load(userptr, "glFlushMappedBufferRange"); + context->MapBufferRange = (PFNGLMAPBUFFERRANGEPROC) load(userptr, "glMapBufferRange"); +} +static void glad_gl_load_GL_ARB_multisample(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_multisample) return; + context->SampleCoverageARB = (PFNGLSAMPLECOVERAGEARBPROC) load(userptr, "glSampleCoverageARB"); +} +static void glad_gl_load_GL_ARB_multitexture(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_multitexture) return; + context->ActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) load(userptr, "glActiveTextureARB"); + context->ClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC) load(userptr, "glClientActiveTextureARB"); + context->MultiTexCoord1dARB = (PFNGLMULTITEXCOORD1DARBPROC) load(userptr, "glMultiTexCoord1dARB"); + context->MultiTexCoord1dvARB = (PFNGLMULTITEXCOORD1DVARBPROC) load(userptr, "glMultiTexCoord1dvARB"); + context->MultiTexCoord1fARB = (PFNGLMULTITEXCOORD1FARBPROC) load(userptr, "glMultiTexCoord1fARB"); + context->MultiTexCoord1fvARB = (PFNGLMULTITEXCOORD1FVARBPROC) load(userptr, "glMultiTexCoord1fvARB"); + context->MultiTexCoord1iARB = (PFNGLMULTITEXCOORD1IARBPROC) load(userptr, "glMultiTexCoord1iARB"); + context->MultiTexCoord1ivARB = (PFNGLMULTITEXCOORD1IVARBPROC) load(userptr, "glMultiTexCoord1ivARB"); + context->MultiTexCoord1sARB = (PFNGLMULTITEXCOORD1SARBPROC) load(userptr, "glMultiTexCoord1sARB"); + context->MultiTexCoord1svARB = (PFNGLMULTITEXCOORD1SVARBPROC) load(userptr, "glMultiTexCoord1svARB"); + context->MultiTexCoord2dARB = (PFNGLMULTITEXCOORD2DARBPROC) load(userptr, "glMultiTexCoord2dARB"); + context->MultiTexCoord2dvARB = (PFNGLMULTITEXCOORD2DVARBPROC) load(userptr, "glMultiTexCoord2dvARB"); + context->MultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC) load(userptr, "glMultiTexCoord2fARB"); + context->MultiTexCoord2fvARB = (PFNGLMULTITEXCOORD2FVARBPROC) load(userptr, "glMultiTexCoord2fvARB"); + context->MultiTexCoord2iARB = (PFNGLMULTITEXCOORD2IARBPROC) load(userptr, "glMultiTexCoord2iARB"); + context->MultiTexCoord2ivARB = (PFNGLMULTITEXCOORD2IVARBPROC) load(userptr, "glMultiTexCoord2ivARB"); + context->MultiTexCoord2sARB = (PFNGLMULTITEXCOORD2SARBPROC) load(userptr, "glMultiTexCoord2sARB"); + context->MultiTexCoord2svARB = (PFNGLMULTITEXCOORD2SVARBPROC) load(userptr, "glMultiTexCoord2svARB"); + context->MultiTexCoord3dARB = (PFNGLMULTITEXCOORD3DARBPROC) load(userptr, "glMultiTexCoord3dARB"); + context->MultiTexCoord3dvARB = (PFNGLMULTITEXCOORD3DVARBPROC) load(userptr, "glMultiTexCoord3dvARB"); + context->MultiTexCoord3fARB = (PFNGLMULTITEXCOORD3FARBPROC) load(userptr, "glMultiTexCoord3fARB"); + context->MultiTexCoord3fvARB = (PFNGLMULTITEXCOORD3FVARBPROC) load(userptr, "glMultiTexCoord3fvARB"); + context->MultiTexCoord3iARB = (PFNGLMULTITEXCOORD3IARBPROC) load(userptr, "glMultiTexCoord3iARB"); + context->MultiTexCoord3ivARB = (PFNGLMULTITEXCOORD3IVARBPROC) load(userptr, "glMultiTexCoord3ivARB"); + context->MultiTexCoord3sARB = (PFNGLMULTITEXCOORD3SARBPROC) load(userptr, "glMultiTexCoord3sARB"); + context->MultiTexCoord3svARB = (PFNGLMULTITEXCOORD3SVARBPROC) load(userptr, "glMultiTexCoord3svARB"); + context->MultiTexCoord4dARB = (PFNGLMULTITEXCOORD4DARBPROC) load(userptr, "glMultiTexCoord4dARB"); + context->MultiTexCoord4dvARB = (PFNGLMULTITEXCOORD4DVARBPROC) load(userptr, "glMultiTexCoord4dvARB"); + context->MultiTexCoord4fARB = (PFNGLMULTITEXCOORD4FARBPROC) load(userptr, "glMultiTexCoord4fARB"); + context->MultiTexCoord4fvARB = (PFNGLMULTITEXCOORD4FVARBPROC) load(userptr, "glMultiTexCoord4fvARB"); + context->MultiTexCoord4iARB = (PFNGLMULTITEXCOORD4IARBPROC) load(userptr, "glMultiTexCoord4iARB"); + context->MultiTexCoord4ivARB = (PFNGLMULTITEXCOORD4IVARBPROC) load(userptr, "glMultiTexCoord4ivARB"); + context->MultiTexCoord4sARB = (PFNGLMULTITEXCOORD4SARBPROC) load(userptr, "glMultiTexCoord4sARB"); + context->MultiTexCoord4svARB = (PFNGLMULTITEXCOORD4SVARBPROC) load(userptr, "glMultiTexCoord4svARB"); +} +static void glad_gl_load_GL_ARB_occlusion_query(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_occlusion_query) return; + context->BeginQueryARB = (PFNGLBEGINQUERYARBPROC) load(userptr, "glBeginQueryARB"); + context->DeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC) load(userptr, "glDeleteQueriesARB"); + context->EndQueryARB = (PFNGLENDQUERYARBPROC) load(userptr, "glEndQueryARB"); + context->GenQueriesARB = (PFNGLGENQUERIESARBPROC) load(userptr, "glGenQueriesARB"); + context->GetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC) load(userptr, "glGetQueryObjectivARB"); + context->GetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC) load(userptr, "glGetQueryObjectuivARB"); + context->GetQueryivARB = (PFNGLGETQUERYIVARBPROC) load(userptr, "glGetQueryivARB"); + context->IsQueryARB = (PFNGLISQUERYARBPROC) load(userptr, "glIsQueryARB"); +} +static void glad_gl_load_GL_ARB_point_parameters(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_point_parameters) return; + context->PointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC) load(userptr, "glPointParameterfARB"); + context->PointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC) load(userptr, "glPointParameterfvARB"); +} +static void glad_gl_load_GL_ARB_provoking_vertex(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_provoking_vertex) return; + context->ProvokingVertex = (PFNGLPROVOKINGVERTEXPROC) load(userptr, "glProvokingVertex"); +} +static void glad_gl_load_GL_ARB_shader_objects(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_shader_objects) return; + context->AttachObjectARB = (PFNGLATTACHOBJECTARBPROC) load(userptr, "glAttachObjectARB"); + context->CompileShaderARB = (PFNGLCOMPILESHADERARBPROC) load(userptr, "glCompileShaderARB"); + context->CreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) load(userptr, "glCreateProgramObjectARB"); + context->CreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) load(userptr, "glCreateShaderObjectARB"); + context->DeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) load(userptr, "glDeleteObjectARB"); + context->DetachObjectARB = (PFNGLDETACHOBJECTARBPROC) load(userptr, "glDetachObjectARB"); + context->GetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC) load(userptr, "glGetActiveUniformARB"); + context->GetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC) load(userptr, "glGetAttachedObjectsARB"); + context->GetHandleARB = (PFNGLGETHANDLEARBPROC) load(userptr, "glGetHandleARB"); + context->GetInfoLogARB = (PFNGLGETINFOLOGARBPROC) load(userptr, "glGetInfoLogARB"); + context->GetObjectParameterfvARB = (PFNGLGETOBJECTPARAMETERFVARBPROC) load(userptr, "glGetObjectParameterfvARB"); + context->GetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) load(userptr, "glGetObjectParameterivARB"); + context->GetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC) load(userptr, "glGetShaderSourceARB"); + context->GetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) load(userptr, "glGetUniformLocationARB"); + context->GetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC) load(userptr, "glGetUniformfvARB"); + context->GetUniformivARB = (PFNGLGETUNIFORMIVARBPROC) load(userptr, "glGetUniformivARB"); + context->LinkProgramARB = (PFNGLLINKPROGRAMARBPROC) load(userptr, "glLinkProgramARB"); + context->ShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) load(userptr, "glShaderSourceARB"); + context->Uniform1fARB = (PFNGLUNIFORM1FARBPROC) load(userptr, "glUniform1fARB"); + context->Uniform1fvARB = (PFNGLUNIFORM1FVARBPROC) load(userptr, "glUniform1fvARB"); + context->Uniform1iARB = (PFNGLUNIFORM1IARBPROC) load(userptr, "glUniform1iARB"); + context->Uniform1ivARB = (PFNGLUNIFORM1IVARBPROC) load(userptr, "glUniform1ivARB"); + context->Uniform2fARB = (PFNGLUNIFORM2FARBPROC) load(userptr, "glUniform2fARB"); + context->Uniform2fvARB = (PFNGLUNIFORM2FVARBPROC) load(userptr, "glUniform2fvARB"); + context->Uniform2iARB = (PFNGLUNIFORM2IARBPROC) load(userptr, "glUniform2iARB"); + context->Uniform2ivARB = (PFNGLUNIFORM2IVARBPROC) load(userptr, "glUniform2ivARB"); + context->Uniform3fARB = (PFNGLUNIFORM3FARBPROC) load(userptr, "glUniform3fARB"); + context->Uniform3fvARB = (PFNGLUNIFORM3FVARBPROC) load(userptr, "glUniform3fvARB"); + context->Uniform3iARB = (PFNGLUNIFORM3IARBPROC) load(userptr, "glUniform3iARB"); + context->Uniform3ivARB = (PFNGLUNIFORM3IVARBPROC) load(userptr, "glUniform3ivARB"); + context->Uniform4fARB = (PFNGLUNIFORM4FARBPROC) load(userptr, "glUniform4fARB"); + context->Uniform4fvARB = (PFNGLUNIFORM4FVARBPROC) load(userptr, "glUniform4fvARB"); + context->Uniform4iARB = (PFNGLUNIFORM4IARBPROC) load(userptr, "glUniform4iARB"); + context->Uniform4ivARB = (PFNGLUNIFORM4IVARBPROC) load(userptr, "glUniform4ivARB"); + context->UniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC) load(userptr, "glUniformMatrix2fvARB"); + context->UniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC) load(userptr, "glUniformMatrix3fvARB"); + context->UniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC) load(userptr, "glUniformMatrix4fvARB"); + context->UseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) load(userptr, "glUseProgramObjectARB"); + context->ValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC) load(userptr, "glValidateProgramARB"); +} +static void glad_gl_load_GL_ARB_sync(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_sync) return; + context->ClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) load(userptr, "glClientWaitSync"); + context->DeleteSync = (PFNGLDELETESYNCPROC) load(userptr, "glDeleteSync"); + context->FenceSync = (PFNGLFENCESYNCPROC) load(userptr, "glFenceSync"); + context->GetInteger64v = (PFNGLGETINTEGER64VPROC) load(userptr, "glGetInteger64v"); + context->GetSynciv = (PFNGLGETSYNCIVPROC) load(userptr, "glGetSynciv"); + context->IsSync = (PFNGLISSYNCPROC) load(userptr, "glIsSync"); + context->WaitSync = (PFNGLWAITSYNCPROC) load(userptr, "glWaitSync"); +} +static void glad_gl_load_GL_ARB_texture_buffer_object(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_texture_buffer_object) return; + context->TexBufferARB = (PFNGLTEXBUFFERARBPROC) load(userptr, "glTexBufferARB"); +} +static void glad_gl_load_GL_ARB_texture_compression(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_texture_compression) return; + context->CompressedTexImage1DARB = (PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) load(userptr, "glCompressedTexImage1DARB"); + context->CompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) load(userptr, "glCompressedTexImage2DARB"); + context->CompressedTexImage3DARB = (PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) load(userptr, "glCompressedTexImage3DARB"); + context->CompressedTexSubImage1DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) load(userptr, "glCompressedTexSubImage1DARB"); + context->CompressedTexSubImage2DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) load(userptr, "glCompressedTexSubImage2DARB"); + context->CompressedTexSubImage3DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) load(userptr, "glCompressedTexSubImage3DARB"); + context->GetCompressedTexImageARB = (PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) load(userptr, "glGetCompressedTexImageARB"); +} +static void glad_gl_load_GL_ARB_texture_multisample(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_texture_multisample) return; + context->GetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) load(userptr, "glGetMultisamplefv"); + context->SampleMaski = (PFNGLSAMPLEMASKIPROC) load(userptr, "glSampleMaski"); + context->TexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) load(userptr, "glTexImage2DMultisample"); + context->TexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) load(userptr, "glTexImage3DMultisample"); +} +static void glad_gl_load_GL_ARB_uniform_buffer_object(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_uniform_buffer_object) return; + context->BindBufferBase = (PFNGLBINDBUFFERBASEPROC) load(userptr, "glBindBufferBase"); + context->BindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load(userptr, "glBindBufferRange"); + context->GetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) load(userptr, "glGetActiveUniformBlockName"); + context->GetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC) load(userptr, "glGetActiveUniformBlockiv"); + context->GetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAMEPROC) load(userptr, "glGetActiveUniformName"); + context->GetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC) load(userptr, "glGetActiveUniformsiv"); + context->GetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load(userptr, "glGetIntegeri_v"); + context->GetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC) load(userptr, "glGetUniformBlockIndex"); + context->GetUniformIndices = (PFNGLGETUNIFORMINDICESPROC) load(userptr, "glGetUniformIndices"); + context->UniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC) load(userptr, "glUniformBlockBinding"); +} +static void glad_gl_load_GL_ARB_vertex_array_object(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_vertex_array_object) return; + context->BindVertexArray = (PFNGLBINDVERTEXARRAYPROC) load(userptr, "glBindVertexArray"); + context->DeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) load(userptr, "glDeleteVertexArrays"); + context->GenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) load(userptr, "glGenVertexArrays"); + context->IsVertexArray = (PFNGLISVERTEXARRAYPROC) load(userptr, "glIsVertexArray"); +} +static void glad_gl_load_GL_ARB_vertex_buffer_object(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_vertex_buffer_object) return; + context->BindBufferARB = (PFNGLBINDBUFFERARBPROC) load(userptr, "glBindBufferARB"); + context->BufferDataARB = (PFNGLBUFFERDATAARBPROC) load(userptr, "glBufferDataARB"); + context->BufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC) load(userptr, "glBufferSubDataARB"); + context->DeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) load(userptr, "glDeleteBuffersARB"); + context->GenBuffersARB = (PFNGLGENBUFFERSARBPROC) load(userptr, "glGenBuffersARB"); + context->GetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC) load(userptr, "glGetBufferParameterivARB"); + context->GetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC) load(userptr, "glGetBufferPointervARB"); + context->GetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC) load(userptr, "glGetBufferSubDataARB"); + context->IsBufferARB = (PFNGLISBUFFERARBPROC) load(userptr, "glIsBufferARB"); + context->MapBufferARB = (PFNGLMAPBUFFERARBPROC) load(userptr, "glMapBufferARB"); + context->UnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC) load(userptr, "glUnmapBufferARB"); +} +static void glad_gl_load_GL_ARB_vertex_program(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_vertex_program) return; + context->BindProgramARB = (PFNGLBINDPROGRAMARBPROC) load(userptr, "glBindProgramARB"); + context->DeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC) load(userptr, "glDeleteProgramsARB"); + context->DisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) load(userptr, "glDisableVertexAttribArrayARB"); + context->EnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC) load(userptr, "glEnableVertexAttribArrayARB"); + context->GenProgramsARB = (PFNGLGENPROGRAMSARBPROC) load(userptr, "glGenProgramsARB"); + context->GetProgramEnvParameterdvARB = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC) load(userptr, "glGetProgramEnvParameterdvARB"); + context->GetProgramEnvParameterfvARB = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC) load(userptr, "glGetProgramEnvParameterfvARB"); + context->GetProgramLocalParameterdvARB = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) load(userptr, "glGetProgramLocalParameterdvARB"); + context->GetProgramLocalParameterfvARB = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) load(userptr, "glGetProgramLocalParameterfvARB"); + context->GetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC) load(userptr, "glGetProgramStringARB"); + context->GetProgramivARB = (PFNGLGETPROGRAMIVARBPROC) load(userptr, "glGetProgramivARB"); + context->GetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC) load(userptr, "glGetVertexAttribPointervARB"); + context->GetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC) load(userptr, "glGetVertexAttribdvARB"); + context->GetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) load(userptr, "glGetVertexAttribfvARB"); + context->GetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC) load(userptr, "glGetVertexAttribivARB"); + context->IsProgramARB = (PFNGLISPROGRAMARBPROC) load(userptr, "glIsProgramARB"); + context->ProgramEnvParameter4dARB = (PFNGLPROGRAMENVPARAMETER4DARBPROC) load(userptr, "glProgramEnvParameter4dARB"); + context->ProgramEnvParameter4dvARB = (PFNGLPROGRAMENVPARAMETER4DVARBPROC) load(userptr, "glProgramEnvParameter4dvARB"); + context->ProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC) load(userptr, "glProgramEnvParameter4fARB"); + context->ProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC) load(userptr, "glProgramEnvParameter4fvARB"); + context->ProgramLocalParameter4dARB = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC) load(userptr, "glProgramLocalParameter4dARB"); + context->ProgramLocalParameter4dvARB = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) load(userptr, "glProgramLocalParameter4dvARB"); + context->ProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC) load(userptr, "glProgramLocalParameter4fARB"); + context->ProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) load(userptr, "glProgramLocalParameter4fvARB"); + context->ProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) load(userptr, "glProgramStringARB"); + context->VertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC) load(userptr, "glVertexAttrib1dARB"); + context->VertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC) load(userptr, "glVertexAttrib1dvARB"); + context->VertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC) load(userptr, "glVertexAttrib1fARB"); + context->VertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC) load(userptr, "glVertexAttrib1fvARB"); + context->VertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC) load(userptr, "glVertexAttrib1sARB"); + context->VertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC) load(userptr, "glVertexAttrib1svARB"); + context->VertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC) load(userptr, "glVertexAttrib2dARB"); + context->VertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC) load(userptr, "glVertexAttrib2dvARB"); + context->VertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC) load(userptr, "glVertexAttrib2fARB"); + context->VertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC) load(userptr, "glVertexAttrib2fvARB"); + context->VertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC) load(userptr, "glVertexAttrib2sARB"); + context->VertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC) load(userptr, "glVertexAttrib2svARB"); + context->VertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC) load(userptr, "glVertexAttrib3dARB"); + context->VertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC) load(userptr, "glVertexAttrib3dvARB"); + context->VertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC) load(userptr, "glVertexAttrib3fARB"); + context->VertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC) load(userptr, "glVertexAttrib3fvARB"); + context->VertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC) load(userptr, "glVertexAttrib3sARB"); + context->VertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC) load(userptr, "glVertexAttrib3svARB"); + context->VertexAttrib4NbvARB = (PFNGLVERTEXATTRIB4NBVARBPROC) load(userptr, "glVertexAttrib4NbvARB"); + context->VertexAttrib4NivARB = (PFNGLVERTEXATTRIB4NIVARBPROC) load(userptr, "glVertexAttrib4NivARB"); + context->VertexAttrib4NsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC) load(userptr, "glVertexAttrib4NsvARB"); + context->VertexAttrib4NubARB = (PFNGLVERTEXATTRIB4NUBARBPROC) load(userptr, "glVertexAttrib4NubARB"); + context->VertexAttrib4NubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC) load(userptr, "glVertexAttrib4NubvARB"); + context->VertexAttrib4NuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC) load(userptr, "glVertexAttrib4NuivARB"); + context->VertexAttrib4NusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC) load(userptr, "glVertexAttrib4NusvARB"); + context->VertexAttrib4bvARB = (PFNGLVERTEXATTRIB4BVARBPROC) load(userptr, "glVertexAttrib4bvARB"); + context->VertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC) load(userptr, "glVertexAttrib4dARB"); + context->VertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC) load(userptr, "glVertexAttrib4dvARB"); + context->VertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC) load(userptr, "glVertexAttrib4fARB"); + context->VertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC) load(userptr, "glVertexAttrib4fvARB"); + context->VertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC) load(userptr, "glVertexAttrib4ivARB"); + context->VertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC) load(userptr, "glVertexAttrib4sARB"); + context->VertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC) load(userptr, "glVertexAttrib4svARB"); + context->VertexAttrib4ubvARB = (PFNGLVERTEXATTRIB4UBVARBPROC) load(userptr, "glVertexAttrib4ubvARB"); + context->VertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC) load(userptr, "glVertexAttrib4uivARB"); + context->VertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC) load(userptr, "glVertexAttrib4usvARB"); + context->VertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) load(userptr, "glVertexAttribPointerARB"); +} +static void glad_gl_load_GL_ARB_vertex_shader(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ARB_vertex_shader) return; + context->BindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) load(userptr, "glBindAttribLocationARB"); + context->DisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) load(userptr, "glDisableVertexAttribArrayARB"); + context->EnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC) load(userptr, "glEnableVertexAttribArrayARB"); + context->GetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC) load(userptr, "glGetActiveAttribARB"); + context->GetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) load(userptr, "glGetAttribLocationARB"); + context->GetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC) load(userptr, "glGetVertexAttribPointervARB"); + context->GetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC) load(userptr, "glGetVertexAttribdvARB"); + context->GetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) load(userptr, "glGetVertexAttribfvARB"); + context->GetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC) load(userptr, "glGetVertexAttribivARB"); + context->VertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC) load(userptr, "glVertexAttrib1dARB"); + context->VertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC) load(userptr, "glVertexAttrib1dvARB"); + context->VertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC) load(userptr, "glVertexAttrib1fARB"); + context->VertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC) load(userptr, "glVertexAttrib1fvARB"); + context->VertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC) load(userptr, "glVertexAttrib1sARB"); + context->VertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC) load(userptr, "glVertexAttrib1svARB"); + context->VertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC) load(userptr, "glVertexAttrib2dARB"); + context->VertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC) load(userptr, "glVertexAttrib2dvARB"); + context->VertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC) load(userptr, "glVertexAttrib2fARB"); + context->VertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC) load(userptr, "glVertexAttrib2fvARB"); + context->VertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC) load(userptr, "glVertexAttrib2sARB"); + context->VertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC) load(userptr, "glVertexAttrib2svARB"); + context->VertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC) load(userptr, "glVertexAttrib3dARB"); + context->VertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC) load(userptr, "glVertexAttrib3dvARB"); + context->VertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC) load(userptr, "glVertexAttrib3fARB"); + context->VertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC) load(userptr, "glVertexAttrib3fvARB"); + context->VertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC) load(userptr, "glVertexAttrib3sARB"); + context->VertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC) load(userptr, "glVertexAttrib3svARB"); + context->VertexAttrib4NbvARB = (PFNGLVERTEXATTRIB4NBVARBPROC) load(userptr, "glVertexAttrib4NbvARB"); + context->VertexAttrib4NivARB = (PFNGLVERTEXATTRIB4NIVARBPROC) load(userptr, "glVertexAttrib4NivARB"); + context->VertexAttrib4NsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC) load(userptr, "glVertexAttrib4NsvARB"); + context->VertexAttrib4NubARB = (PFNGLVERTEXATTRIB4NUBARBPROC) load(userptr, "glVertexAttrib4NubARB"); + context->VertexAttrib4NubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC) load(userptr, "glVertexAttrib4NubvARB"); + context->VertexAttrib4NuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC) load(userptr, "glVertexAttrib4NuivARB"); + context->VertexAttrib4NusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC) load(userptr, "glVertexAttrib4NusvARB"); + context->VertexAttrib4bvARB = (PFNGLVERTEXATTRIB4BVARBPROC) load(userptr, "glVertexAttrib4bvARB"); + context->VertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC) load(userptr, "glVertexAttrib4dARB"); + context->VertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC) load(userptr, "glVertexAttrib4dvARB"); + context->VertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC) load(userptr, "glVertexAttrib4fARB"); + context->VertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC) load(userptr, "glVertexAttrib4fvARB"); + context->VertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC) load(userptr, "glVertexAttrib4ivARB"); + context->VertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC) load(userptr, "glVertexAttrib4sARB"); + context->VertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC) load(userptr, "glVertexAttrib4svARB"); + context->VertexAttrib4ubvARB = (PFNGLVERTEXATTRIB4UBVARBPROC) load(userptr, "glVertexAttrib4ubvARB"); + context->VertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC) load(userptr, "glVertexAttrib4uivARB"); + context->VertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC) load(userptr, "glVertexAttrib4usvARB"); + context->VertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) load(userptr, "glVertexAttribPointerARB"); +} +static void glad_gl_load_GL_ATI_draw_buffers(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ATI_draw_buffers) return; + context->DrawBuffersATI = (PFNGLDRAWBUFFERSATIPROC) load(userptr, "glDrawBuffersATI"); +} +static void glad_gl_load_GL_ATI_separate_stencil(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ATI_separate_stencil) return; + context->StencilFuncSeparateATI = (PFNGLSTENCILFUNCSEPARATEATIPROC) load(userptr, "glStencilFuncSeparateATI"); + context->StencilOpSeparateATI = (PFNGLSTENCILOPSEPARATEATIPROC) load(userptr, "glStencilOpSeparateATI"); +} +static void glad_gl_load_GL_EXT_blend_color(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_blend_color) return; + context->BlendColorEXT = (PFNGLBLENDCOLOREXTPROC) load(userptr, "glBlendColorEXT"); +} +static void glad_gl_load_GL_EXT_blend_equation_separate(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_blend_equation_separate) return; + context->BlendEquationSeparateEXT = (PFNGLBLENDEQUATIONSEPARATEEXTPROC) load(userptr, "glBlendEquationSeparateEXT"); +} +static void glad_gl_load_GL_EXT_blend_func_separate(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_blend_func_separate) return; + context->BlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC) load(userptr, "glBlendFuncSeparateEXT"); +} +static void glad_gl_load_GL_EXT_blend_minmax(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_blend_minmax) return; + context->BlendEquationEXT = (PFNGLBLENDEQUATIONEXTPROC) load(userptr, "glBlendEquationEXT"); +} +static void glad_gl_load_GL_EXT_copy_texture(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_copy_texture) return; + context->CopyTexImage1DEXT = (PFNGLCOPYTEXIMAGE1DEXTPROC) load(userptr, "glCopyTexImage1DEXT"); + context->CopyTexImage2DEXT = (PFNGLCOPYTEXIMAGE2DEXTPROC) load(userptr, "glCopyTexImage2DEXT"); + context->CopyTexSubImage1DEXT = (PFNGLCOPYTEXSUBIMAGE1DEXTPROC) load(userptr, "glCopyTexSubImage1DEXT"); + context->CopyTexSubImage2DEXT = (PFNGLCOPYTEXSUBIMAGE2DEXTPROC) load(userptr, "glCopyTexSubImage2DEXT"); + context->CopyTexSubImage3DEXT = (PFNGLCOPYTEXSUBIMAGE3DEXTPROC) load(userptr, "glCopyTexSubImage3DEXT"); +} +static void glad_gl_load_GL_EXT_direct_state_access(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_direct_state_access) return; + context->BindMultiTextureEXT = (PFNGLBINDMULTITEXTUREEXTPROC) load(userptr, "glBindMultiTextureEXT"); + context->CheckNamedFramebufferStatusEXT = (PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) load(userptr, "glCheckNamedFramebufferStatusEXT"); + context->ClearNamedBufferDataEXT = (PFNGLCLEARNAMEDBUFFERDATAEXTPROC) load(userptr, "glClearNamedBufferDataEXT"); + context->ClearNamedBufferSubDataEXT = (PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC) load(userptr, "glClearNamedBufferSubDataEXT"); + context->ClientAttribDefaultEXT = (PFNGLCLIENTATTRIBDEFAULTEXTPROC) load(userptr, "glClientAttribDefaultEXT"); + context->CompressedMultiTexImage1DEXT = (PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) load(userptr, "glCompressedMultiTexImage1DEXT"); + context->CompressedMultiTexImage2DEXT = (PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) load(userptr, "glCompressedMultiTexImage2DEXT"); + context->CompressedMultiTexImage3DEXT = (PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) load(userptr, "glCompressedMultiTexImage3DEXT"); + context->CompressedMultiTexSubImage1DEXT = (PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) load(userptr, "glCompressedMultiTexSubImage1DEXT"); + context->CompressedMultiTexSubImage2DEXT = (PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) load(userptr, "glCompressedMultiTexSubImage2DEXT"); + context->CompressedMultiTexSubImage3DEXT = (PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) load(userptr, "glCompressedMultiTexSubImage3DEXT"); + context->CompressedTextureImage1DEXT = (PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) load(userptr, "glCompressedTextureImage1DEXT"); + context->CompressedTextureImage2DEXT = (PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) load(userptr, "glCompressedTextureImage2DEXT"); + context->CompressedTextureImage3DEXT = (PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) load(userptr, "glCompressedTextureImage3DEXT"); + context->CompressedTextureSubImage1DEXT = (PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) load(userptr, "glCompressedTextureSubImage1DEXT"); + context->CompressedTextureSubImage2DEXT = (PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) load(userptr, "glCompressedTextureSubImage2DEXT"); + context->CompressedTextureSubImage3DEXT = (PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) load(userptr, "glCompressedTextureSubImage3DEXT"); + context->CopyMultiTexImage1DEXT = (PFNGLCOPYMULTITEXIMAGE1DEXTPROC) load(userptr, "glCopyMultiTexImage1DEXT"); + context->CopyMultiTexImage2DEXT = (PFNGLCOPYMULTITEXIMAGE2DEXTPROC) load(userptr, "glCopyMultiTexImage2DEXT"); + context->CopyMultiTexSubImage1DEXT = (PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) load(userptr, "glCopyMultiTexSubImage1DEXT"); + context->CopyMultiTexSubImage2DEXT = (PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC) load(userptr, "glCopyMultiTexSubImage2DEXT"); + context->CopyMultiTexSubImage3DEXT = (PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC) load(userptr, "glCopyMultiTexSubImage3DEXT"); + context->CopyTextureImage1DEXT = (PFNGLCOPYTEXTUREIMAGE1DEXTPROC) load(userptr, "glCopyTextureImage1DEXT"); + context->CopyTextureImage2DEXT = (PFNGLCOPYTEXTUREIMAGE2DEXTPROC) load(userptr, "glCopyTextureImage2DEXT"); + context->CopyTextureSubImage1DEXT = (PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC) load(userptr, "glCopyTextureSubImage1DEXT"); + context->CopyTextureSubImage2DEXT = (PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC) load(userptr, "glCopyTextureSubImage2DEXT"); + context->CopyTextureSubImage3DEXT = (PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC) load(userptr, "glCopyTextureSubImage3DEXT"); + context->DisableClientStateIndexedEXT = (PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC) load(userptr, "glDisableClientStateIndexedEXT"); + context->DisableClientStateiEXT = (PFNGLDISABLECLIENTSTATEIEXTPROC) load(userptr, "glDisableClientStateiEXT"); + context->DisableIndexedEXT = (PFNGLDISABLEINDEXEDEXTPROC) load(userptr, "glDisableIndexedEXT"); + context->DisableVertexArrayAttribEXT = (PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC) load(userptr, "glDisableVertexArrayAttribEXT"); + context->DisableVertexArrayEXT = (PFNGLDISABLEVERTEXARRAYEXTPROC) load(userptr, "glDisableVertexArrayEXT"); + context->EnableClientStateIndexedEXT = (PFNGLENABLECLIENTSTATEINDEXEDEXTPROC) load(userptr, "glEnableClientStateIndexedEXT"); + context->EnableClientStateiEXT = (PFNGLENABLECLIENTSTATEIEXTPROC) load(userptr, "glEnableClientStateiEXT"); + context->EnableIndexedEXT = (PFNGLENABLEINDEXEDEXTPROC) load(userptr, "glEnableIndexedEXT"); + context->EnableVertexArrayAttribEXT = (PFNGLENABLEVERTEXARRAYATTRIBEXTPROC) load(userptr, "glEnableVertexArrayAttribEXT"); + context->EnableVertexArrayEXT = (PFNGLENABLEVERTEXARRAYEXTPROC) load(userptr, "glEnableVertexArrayEXT"); + context->FlushMappedNamedBufferRangeEXT = (PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC) load(userptr, "glFlushMappedNamedBufferRangeEXT"); + context->FramebufferDrawBufferEXT = (PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC) load(userptr, "glFramebufferDrawBufferEXT"); + context->FramebufferDrawBuffersEXT = (PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) load(userptr, "glFramebufferDrawBuffersEXT"); + context->FramebufferReadBufferEXT = (PFNGLFRAMEBUFFERREADBUFFEREXTPROC) load(userptr, "glFramebufferReadBufferEXT"); + context->GenerateMultiTexMipmapEXT = (PFNGLGENERATEMULTITEXMIPMAPEXTPROC) load(userptr, "glGenerateMultiTexMipmapEXT"); + context->GenerateTextureMipmapEXT = (PFNGLGENERATETEXTUREMIPMAPEXTPROC) load(userptr, "glGenerateTextureMipmapEXT"); + context->GetBooleanIndexedvEXT = (PFNGLGETBOOLEANINDEXEDVEXTPROC) load(userptr, "glGetBooleanIndexedvEXT"); + context->GetCompressedMultiTexImageEXT = (PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) load(userptr, "glGetCompressedMultiTexImageEXT"); + context->GetCompressedTextureImageEXT = (PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) load(userptr, "glGetCompressedTextureImageEXT"); + context->GetDoubleIndexedvEXT = (PFNGLGETDOUBLEINDEXEDVEXTPROC) load(userptr, "glGetDoubleIndexedvEXT"); + context->GetDoublei_vEXT = (PFNGLGETDOUBLEI_VEXTPROC) load(userptr, "glGetDoublei_vEXT"); + context->GetFloatIndexedvEXT = (PFNGLGETFLOATINDEXEDVEXTPROC) load(userptr, "glGetFloatIndexedvEXT"); + context->GetFloati_vEXT = (PFNGLGETFLOATI_VEXTPROC) load(userptr, "glGetFloati_vEXT"); + context->GetFramebufferParameterivEXT = (PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC) load(userptr, "glGetFramebufferParameterivEXT"); + context->GetIntegerIndexedvEXT = (PFNGLGETINTEGERINDEXEDVEXTPROC) load(userptr, "glGetIntegerIndexedvEXT"); + context->GetMultiTexEnvfvEXT = (PFNGLGETMULTITEXENVFVEXTPROC) load(userptr, "glGetMultiTexEnvfvEXT"); + context->GetMultiTexEnvivEXT = (PFNGLGETMULTITEXENVIVEXTPROC) load(userptr, "glGetMultiTexEnvivEXT"); + context->GetMultiTexGendvEXT = (PFNGLGETMULTITEXGENDVEXTPROC) load(userptr, "glGetMultiTexGendvEXT"); + context->GetMultiTexGenfvEXT = (PFNGLGETMULTITEXGENFVEXTPROC) load(userptr, "glGetMultiTexGenfvEXT"); + context->GetMultiTexGenivEXT = (PFNGLGETMULTITEXGENIVEXTPROC) load(userptr, "glGetMultiTexGenivEXT"); + context->GetMultiTexImageEXT = (PFNGLGETMULTITEXIMAGEEXTPROC) load(userptr, "glGetMultiTexImageEXT"); + context->GetMultiTexLevelParameterfvEXT = (PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) load(userptr, "glGetMultiTexLevelParameterfvEXT"); + context->GetMultiTexLevelParameterivEXT = (PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) load(userptr, "glGetMultiTexLevelParameterivEXT"); + context->GetMultiTexParameterIivEXT = (PFNGLGETMULTITEXPARAMETERIIVEXTPROC) load(userptr, "glGetMultiTexParameterIivEXT"); + context->GetMultiTexParameterIuivEXT = (PFNGLGETMULTITEXPARAMETERIUIVEXTPROC) load(userptr, "glGetMultiTexParameterIuivEXT"); + context->GetMultiTexParameterfvEXT = (PFNGLGETMULTITEXPARAMETERFVEXTPROC) load(userptr, "glGetMultiTexParameterfvEXT"); + context->GetMultiTexParameterivEXT = (PFNGLGETMULTITEXPARAMETERIVEXTPROC) load(userptr, "glGetMultiTexParameterivEXT"); + context->GetNamedBufferParameterivEXT = (PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) load(userptr, "glGetNamedBufferParameterivEXT"); + context->GetNamedBufferPointervEXT = (PFNGLGETNAMEDBUFFERPOINTERVEXTPROC) load(userptr, "glGetNamedBufferPointervEXT"); + context->GetNamedBufferSubDataEXT = (PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) load(userptr, "glGetNamedBufferSubDataEXT"); + context->GetNamedFramebufferAttachmentParameterivEXT = (PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) load(userptr, "glGetNamedFramebufferAttachmentParameterivEXT"); + context->GetNamedFramebufferParameterivEXT = (PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC) load(userptr, "glGetNamedFramebufferParameterivEXT"); + context->GetNamedProgramLocalParameterIivEXT = (PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) load(userptr, "glGetNamedProgramLocalParameterIivEXT"); + context->GetNamedProgramLocalParameterIuivEXT = (PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) load(userptr, "glGetNamedProgramLocalParameterIuivEXT"); + context->GetNamedProgramLocalParameterdvEXT = (PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) load(userptr, "glGetNamedProgramLocalParameterdvEXT"); + context->GetNamedProgramLocalParameterfvEXT = (PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) load(userptr, "glGetNamedProgramLocalParameterfvEXT"); + context->GetNamedProgramStringEXT = (PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) load(userptr, "glGetNamedProgramStringEXT"); + context->GetNamedProgramivEXT = (PFNGLGETNAMEDPROGRAMIVEXTPROC) load(userptr, "glGetNamedProgramivEXT"); + context->GetNamedRenderbufferParameterivEXT = (PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) load(userptr, "glGetNamedRenderbufferParameterivEXT"); + context->GetPointerIndexedvEXT = (PFNGLGETPOINTERINDEXEDVEXTPROC) load(userptr, "glGetPointerIndexedvEXT"); + context->GetPointeri_vEXT = (PFNGLGETPOINTERI_VEXTPROC) load(userptr, "glGetPointeri_vEXT"); + context->GetTextureImageEXT = (PFNGLGETTEXTUREIMAGEEXTPROC) load(userptr, "glGetTextureImageEXT"); + context->GetTextureLevelParameterfvEXT = (PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) load(userptr, "glGetTextureLevelParameterfvEXT"); + context->GetTextureLevelParameterivEXT = (PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) load(userptr, "glGetTextureLevelParameterivEXT"); + context->GetTextureParameterIivEXT = (PFNGLGETTEXTUREPARAMETERIIVEXTPROC) load(userptr, "glGetTextureParameterIivEXT"); + context->GetTextureParameterIuivEXT = (PFNGLGETTEXTUREPARAMETERIUIVEXTPROC) load(userptr, "glGetTextureParameterIuivEXT"); + context->GetTextureParameterfvEXT = (PFNGLGETTEXTUREPARAMETERFVEXTPROC) load(userptr, "glGetTextureParameterfvEXT"); + context->GetTextureParameterivEXT = (PFNGLGETTEXTUREPARAMETERIVEXTPROC) load(userptr, "glGetTextureParameterivEXT"); + context->GetVertexArrayIntegeri_vEXT = (PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) load(userptr, "glGetVertexArrayIntegeri_vEXT"); + context->GetVertexArrayIntegervEXT = (PFNGLGETVERTEXARRAYINTEGERVEXTPROC) load(userptr, "glGetVertexArrayIntegervEXT"); + context->GetVertexArrayPointeri_vEXT = (PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) load(userptr, "glGetVertexArrayPointeri_vEXT"); + context->GetVertexArrayPointervEXT = (PFNGLGETVERTEXARRAYPOINTERVEXTPROC) load(userptr, "glGetVertexArrayPointervEXT"); + context->IsEnabledIndexedEXT = (PFNGLISENABLEDINDEXEDEXTPROC) load(userptr, "glIsEnabledIndexedEXT"); + context->MapNamedBufferEXT = (PFNGLMAPNAMEDBUFFEREXTPROC) load(userptr, "glMapNamedBufferEXT"); + context->MapNamedBufferRangeEXT = (PFNGLMAPNAMEDBUFFERRANGEEXTPROC) load(userptr, "glMapNamedBufferRangeEXT"); + context->MatrixFrustumEXT = (PFNGLMATRIXFRUSTUMEXTPROC) load(userptr, "glMatrixFrustumEXT"); + context->MatrixLoadIdentityEXT = (PFNGLMATRIXLOADIDENTITYEXTPROC) load(userptr, "glMatrixLoadIdentityEXT"); + context->MatrixLoadTransposedEXT = (PFNGLMATRIXLOADTRANSPOSEDEXTPROC) load(userptr, "glMatrixLoadTransposedEXT"); + context->MatrixLoadTransposefEXT = (PFNGLMATRIXLOADTRANSPOSEFEXTPROC) load(userptr, "glMatrixLoadTransposefEXT"); + context->MatrixLoaddEXT = (PFNGLMATRIXLOADDEXTPROC) load(userptr, "glMatrixLoaddEXT"); + context->MatrixLoadfEXT = (PFNGLMATRIXLOADFEXTPROC) load(userptr, "glMatrixLoadfEXT"); + context->MatrixMultTransposedEXT = (PFNGLMATRIXMULTTRANSPOSEDEXTPROC) load(userptr, "glMatrixMultTransposedEXT"); + context->MatrixMultTransposefEXT = (PFNGLMATRIXMULTTRANSPOSEFEXTPROC) load(userptr, "glMatrixMultTransposefEXT"); + context->MatrixMultdEXT = (PFNGLMATRIXMULTDEXTPROC) load(userptr, "glMatrixMultdEXT"); + context->MatrixMultfEXT = (PFNGLMATRIXMULTFEXTPROC) load(userptr, "glMatrixMultfEXT"); + context->MatrixOrthoEXT = (PFNGLMATRIXORTHOEXTPROC) load(userptr, "glMatrixOrthoEXT"); + context->MatrixPopEXT = (PFNGLMATRIXPOPEXTPROC) load(userptr, "glMatrixPopEXT"); + context->MatrixPushEXT = (PFNGLMATRIXPUSHEXTPROC) load(userptr, "glMatrixPushEXT"); + context->MatrixRotatedEXT = (PFNGLMATRIXROTATEDEXTPROC) load(userptr, "glMatrixRotatedEXT"); + context->MatrixRotatefEXT = (PFNGLMATRIXROTATEFEXTPROC) load(userptr, "glMatrixRotatefEXT"); + context->MatrixScaledEXT = (PFNGLMATRIXSCALEDEXTPROC) load(userptr, "glMatrixScaledEXT"); + context->MatrixScalefEXT = (PFNGLMATRIXSCALEFEXTPROC) load(userptr, "glMatrixScalefEXT"); + context->MatrixTranslatedEXT = (PFNGLMATRIXTRANSLATEDEXTPROC) load(userptr, "glMatrixTranslatedEXT"); + context->MatrixTranslatefEXT = (PFNGLMATRIXTRANSLATEFEXTPROC) load(userptr, "glMatrixTranslatefEXT"); + context->MultiTexBufferEXT = (PFNGLMULTITEXBUFFEREXTPROC) load(userptr, "glMultiTexBufferEXT"); + context->MultiTexCoordPointerEXT = (PFNGLMULTITEXCOORDPOINTEREXTPROC) load(userptr, "glMultiTexCoordPointerEXT"); + context->MultiTexEnvfEXT = (PFNGLMULTITEXENVFEXTPROC) load(userptr, "glMultiTexEnvfEXT"); + context->MultiTexEnvfvEXT = (PFNGLMULTITEXENVFVEXTPROC) load(userptr, "glMultiTexEnvfvEXT"); + context->MultiTexEnviEXT = (PFNGLMULTITEXENVIEXTPROC) load(userptr, "glMultiTexEnviEXT"); + context->MultiTexEnvivEXT = (PFNGLMULTITEXENVIVEXTPROC) load(userptr, "glMultiTexEnvivEXT"); + context->MultiTexGendEXT = (PFNGLMULTITEXGENDEXTPROC) load(userptr, "glMultiTexGendEXT"); + context->MultiTexGendvEXT = (PFNGLMULTITEXGENDVEXTPROC) load(userptr, "glMultiTexGendvEXT"); + context->MultiTexGenfEXT = (PFNGLMULTITEXGENFEXTPROC) load(userptr, "glMultiTexGenfEXT"); + context->MultiTexGenfvEXT = (PFNGLMULTITEXGENFVEXTPROC) load(userptr, "glMultiTexGenfvEXT"); + context->MultiTexGeniEXT = (PFNGLMULTITEXGENIEXTPROC) load(userptr, "glMultiTexGeniEXT"); + context->MultiTexGenivEXT = (PFNGLMULTITEXGENIVEXTPROC) load(userptr, "glMultiTexGenivEXT"); + context->MultiTexImage1DEXT = (PFNGLMULTITEXIMAGE1DEXTPROC) load(userptr, "glMultiTexImage1DEXT"); + context->MultiTexImage2DEXT = (PFNGLMULTITEXIMAGE2DEXTPROC) load(userptr, "glMultiTexImage2DEXT"); + context->MultiTexImage3DEXT = (PFNGLMULTITEXIMAGE3DEXTPROC) load(userptr, "glMultiTexImage3DEXT"); + context->MultiTexParameterIivEXT = (PFNGLMULTITEXPARAMETERIIVEXTPROC) load(userptr, "glMultiTexParameterIivEXT"); + context->MultiTexParameterIuivEXT = (PFNGLMULTITEXPARAMETERIUIVEXTPROC) load(userptr, "glMultiTexParameterIuivEXT"); + context->MultiTexParameterfEXT = (PFNGLMULTITEXPARAMETERFEXTPROC) load(userptr, "glMultiTexParameterfEXT"); + context->MultiTexParameterfvEXT = (PFNGLMULTITEXPARAMETERFVEXTPROC) load(userptr, "glMultiTexParameterfvEXT"); + context->MultiTexParameteriEXT = (PFNGLMULTITEXPARAMETERIEXTPROC) load(userptr, "glMultiTexParameteriEXT"); + context->MultiTexParameterivEXT = (PFNGLMULTITEXPARAMETERIVEXTPROC) load(userptr, "glMultiTexParameterivEXT"); + context->MultiTexRenderbufferEXT = (PFNGLMULTITEXRENDERBUFFEREXTPROC) load(userptr, "glMultiTexRenderbufferEXT"); + context->MultiTexSubImage1DEXT = (PFNGLMULTITEXSUBIMAGE1DEXTPROC) load(userptr, "glMultiTexSubImage1DEXT"); + context->MultiTexSubImage2DEXT = (PFNGLMULTITEXSUBIMAGE2DEXTPROC) load(userptr, "glMultiTexSubImage2DEXT"); + context->MultiTexSubImage3DEXT = (PFNGLMULTITEXSUBIMAGE3DEXTPROC) load(userptr, "glMultiTexSubImage3DEXT"); + context->NamedBufferDataEXT = (PFNGLNAMEDBUFFERDATAEXTPROC) load(userptr, "glNamedBufferDataEXT"); + context->NamedBufferStorageEXT = (PFNGLNAMEDBUFFERSTORAGEEXTPROC) load(userptr, "glNamedBufferStorageEXT"); + context->NamedBufferSubDataEXT = (PFNGLNAMEDBUFFERSUBDATAEXTPROC) load(userptr, "glNamedBufferSubDataEXT"); + context->NamedCopyBufferSubDataEXT = (PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC) load(userptr, "glNamedCopyBufferSubDataEXT"); + context->NamedFramebufferParameteriEXT = (PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC) load(userptr, "glNamedFramebufferParameteriEXT"); + context->NamedFramebufferRenderbufferEXT = (PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) load(userptr, "glNamedFramebufferRenderbufferEXT"); + context->NamedFramebufferTexture1DEXT = (PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) load(userptr, "glNamedFramebufferTexture1DEXT"); + context->NamedFramebufferTexture2DEXT = (PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC) load(userptr, "glNamedFramebufferTexture2DEXT"); + context->NamedFramebufferTexture3DEXT = (PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC) load(userptr, "glNamedFramebufferTexture3DEXT"); + context->NamedFramebufferTextureEXT = (PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC) load(userptr, "glNamedFramebufferTextureEXT"); + context->NamedFramebufferTextureFaceEXT = (PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC) load(userptr, "glNamedFramebufferTextureFaceEXT"); + context->NamedFramebufferTextureLayerEXT = (PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC) load(userptr, "glNamedFramebufferTextureLayerEXT"); + context->NamedProgramLocalParameter4dEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC) load(userptr, "glNamedProgramLocalParameter4dEXT"); + context->NamedProgramLocalParameter4dvEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC) load(userptr, "glNamedProgramLocalParameter4dvEXT"); + context->NamedProgramLocalParameter4fEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC) load(userptr, "glNamedProgramLocalParameter4fEXT"); + context->NamedProgramLocalParameter4fvEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC) load(userptr, "glNamedProgramLocalParameter4fvEXT"); + context->NamedProgramLocalParameterI4iEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC) load(userptr, "glNamedProgramLocalParameterI4iEXT"); + context->NamedProgramLocalParameterI4ivEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC) load(userptr, "glNamedProgramLocalParameterI4ivEXT"); + context->NamedProgramLocalParameterI4uiEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC) load(userptr, "glNamedProgramLocalParameterI4uiEXT"); + context->NamedProgramLocalParameterI4uivEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) load(userptr, "glNamedProgramLocalParameterI4uivEXT"); + context->NamedProgramLocalParameters4fvEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) load(userptr, "glNamedProgramLocalParameters4fvEXT"); + context->NamedProgramLocalParametersI4ivEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) load(userptr, "glNamedProgramLocalParametersI4ivEXT"); + context->NamedProgramLocalParametersI4uivEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) load(userptr, "glNamedProgramLocalParametersI4uivEXT"); + context->NamedProgramStringEXT = (PFNGLNAMEDPROGRAMSTRINGEXTPROC) load(userptr, "glNamedProgramStringEXT"); + context->NamedRenderbufferStorageEXT = (PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) load(userptr, "glNamedRenderbufferStorageEXT"); + context->NamedRenderbufferStorageMultisampleCoverageEXT = (PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) load(userptr, "glNamedRenderbufferStorageMultisampleCoverageEXT"); + context->NamedRenderbufferStorageMultisampleEXT = (PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) load(userptr, "glNamedRenderbufferStorageMultisampleEXT"); + context->ProgramUniform1dEXT = (PFNGLPROGRAMUNIFORM1DEXTPROC) load(userptr, "glProgramUniform1dEXT"); + context->ProgramUniform1dvEXT = (PFNGLPROGRAMUNIFORM1DVEXTPROC) load(userptr, "glProgramUniform1dvEXT"); + context->ProgramUniform1fEXT = (PFNGLPROGRAMUNIFORM1FEXTPROC) load(userptr, "glProgramUniform1fEXT"); + context->ProgramUniform1fvEXT = (PFNGLPROGRAMUNIFORM1FVEXTPROC) load(userptr, "glProgramUniform1fvEXT"); + context->ProgramUniform1iEXT = (PFNGLPROGRAMUNIFORM1IEXTPROC) load(userptr, "glProgramUniform1iEXT"); + context->ProgramUniform1ivEXT = (PFNGLPROGRAMUNIFORM1IVEXTPROC) load(userptr, "glProgramUniform1ivEXT"); + context->ProgramUniform1uiEXT = (PFNGLPROGRAMUNIFORM1UIEXTPROC) load(userptr, "glProgramUniform1uiEXT"); + context->ProgramUniform1uivEXT = (PFNGLPROGRAMUNIFORM1UIVEXTPROC) load(userptr, "glProgramUniform1uivEXT"); + context->ProgramUniform2dEXT = (PFNGLPROGRAMUNIFORM2DEXTPROC) load(userptr, "glProgramUniform2dEXT"); + context->ProgramUniform2dvEXT = (PFNGLPROGRAMUNIFORM2DVEXTPROC) load(userptr, "glProgramUniform2dvEXT"); + context->ProgramUniform2fEXT = (PFNGLPROGRAMUNIFORM2FEXTPROC) load(userptr, "glProgramUniform2fEXT"); + context->ProgramUniform2fvEXT = (PFNGLPROGRAMUNIFORM2FVEXTPROC) load(userptr, "glProgramUniform2fvEXT"); + context->ProgramUniform2iEXT = (PFNGLPROGRAMUNIFORM2IEXTPROC) load(userptr, "glProgramUniform2iEXT"); + context->ProgramUniform2ivEXT = (PFNGLPROGRAMUNIFORM2IVEXTPROC) load(userptr, "glProgramUniform2ivEXT"); + context->ProgramUniform2uiEXT = (PFNGLPROGRAMUNIFORM2UIEXTPROC) load(userptr, "glProgramUniform2uiEXT"); + context->ProgramUniform2uivEXT = (PFNGLPROGRAMUNIFORM2UIVEXTPROC) load(userptr, "glProgramUniform2uivEXT"); + context->ProgramUniform3dEXT = (PFNGLPROGRAMUNIFORM3DEXTPROC) load(userptr, "glProgramUniform3dEXT"); + context->ProgramUniform3dvEXT = (PFNGLPROGRAMUNIFORM3DVEXTPROC) load(userptr, "glProgramUniform3dvEXT"); + context->ProgramUniform3fEXT = (PFNGLPROGRAMUNIFORM3FEXTPROC) load(userptr, "glProgramUniform3fEXT"); + context->ProgramUniform3fvEXT = (PFNGLPROGRAMUNIFORM3FVEXTPROC) load(userptr, "glProgramUniform3fvEXT"); + context->ProgramUniform3iEXT = (PFNGLPROGRAMUNIFORM3IEXTPROC) load(userptr, "glProgramUniform3iEXT"); + context->ProgramUniform3ivEXT = (PFNGLPROGRAMUNIFORM3IVEXTPROC) load(userptr, "glProgramUniform3ivEXT"); + context->ProgramUniform3uiEXT = (PFNGLPROGRAMUNIFORM3UIEXTPROC) load(userptr, "glProgramUniform3uiEXT"); + context->ProgramUniform3uivEXT = (PFNGLPROGRAMUNIFORM3UIVEXTPROC) load(userptr, "glProgramUniform3uivEXT"); + context->ProgramUniform4dEXT = (PFNGLPROGRAMUNIFORM4DEXTPROC) load(userptr, "glProgramUniform4dEXT"); + context->ProgramUniform4dvEXT = (PFNGLPROGRAMUNIFORM4DVEXTPROC) load(userptr, "glProgramUniform4dvEXT"); + context->ProgramUniform4fEXT = (PFNGLPROGRAMUNIFORM4FEXTPROC) load(userptr, "glProgramUniform4fEXT"); + context->ProgramUniform4fvEXT = (PFNGLPROGRAMUNIFORM4FVEXTPROC) load(userptr, "glProgramUniform4fvEXT"); + context->ProgramUniform4iEXT = (PFNGLPROGRAMUNIFORM4IEXTPROC) load(userptr, "glProgramUniform4iEXT"); + context->ProgramUniform4ivEXT = (PFNGLPROGRAMUNIFORM4IVEXTPROC) load(userptr, "glProgramUniform4ivEXT"); + context->ProgramUniform4uiEXT = (PFNGLPROGRAMUNIFORM4UIEXTPROC) load(userptr, "glProgramUniform4uiEXT"); + context->ProgramUniform4uivEXT = (PFNGLPROGRAMUNIFORM4UIVEXTPROC) load(userptr, "glProgramUniform4uivEXT"); + context->ProgramUniformMatrix2dvEXT = (PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC) load(userptr, "glProgramUniformMatrix2dvEXT"); + context->ProgramUniformMatrix2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) load(userptr, "glProgramUniformMatrix2fvEXT"); + context->ProgramUniformMatrix2x3dvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC) load(userptr, "glProgramUniformMatrix2x3dvEXT"); + context->ProgramUniformMatrix2x3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) load(userptr, "glProgramUniformMatrix2x3fvEXT"); + context->ProgramUniformMatrix2x4dvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC) load(userptr, "glProgramUniformMatrix2x4dvEXT"); + context->ProgramUniformMatrix2x4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) load(userptr, "glProgramUniformMatrix2x4fvEXT"); + context->ProgramUniformMatrix3dvEXT = (PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC) load(userptr, "glProgramUniformMatrix3dvEXT"); + context->ProgramUniformMatrix3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) load(userptr, "glProgramUniformMatrix3fvEXT"); + context->ProgramUniformMatrix3x2dvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC) load(userptr, "glProgramUniformMatrix3x2dvEXT"); + context->ProgramUniformMatrix3x2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) load(userptr, "glProgramUniformMatrix3x2fvEXT"); + context->ProgramUniformMatrix3x4dvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC) load(userptr, "glProgramUniformMatrix3x4dvEXT"); + context->ProgramUniformMatrix3x4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) load(userptr, "glProgramUniformMatrix3x4fvEXT"); + context->ProgramUniformMatrix4dvEXT = (PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC) load(userptr, "glProgramUniformMatrix4dvEXT"); + context->ProgramUniformMatrix4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) load(userptr, "glProgramUniformMatrix4fvEXT"); + context->ProgramUniformMatrix4x2dvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC) load(userptr, "glProgramUniformMatrix4x2dvEXT"); + context->ProgramUniformMatrix4x2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) load(userptr, "glProgramUniformMatrix4x2fvEXT"); + context->ProgramUniformMatrix4x3dvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC) load(userptr, "glProgramUniformMatrix4x3dvEXT"); + context->ProgramUniformMatrix4x3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) load(userptr, "glProgramUniformMatrix4x3fvEXT"); + context->PushClientAttribDefaultEXT = (PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) load(userptr, "glPushClientAttribDefaultEXT"); + context->TextureBufferEXT = (PFNGLTEXTUREBUFFEREXTPROC) load(userptr, "glTextureBufferEXT"); + context->TextureBufferRangeEXT = (PFNGLTEXTUREBUFFERRANGEEXTPROC) load(userptr, "glTextureBufferRangeEXT"); + context->TextureImage1DEXT = (PFNGLTEXTUREIMAGE1DEXTPROC) load(userptr, "glTextureImage1DEXT"); + context->TextureImage2DEXT = (PFNGLTEXTUREIMAGE2DEXTPROC) load(userptr, "glTextureImage2DEXT"); + context->TextureImage3DEXT = (PFNGLTEXTUREIMAGE3DEXTPROC) load(userptr, "glTextureImage3DEXT"); + context->TexturePageCommitmentEXT = (PFNGLTEXTUREPAGECOMMITMENTEXTPROC) load(userptr, "glTexturePageCommitmentEXT"); + context->TextureParameterIivEXT = (PFNGLTEXTUREPARAMETERIIVEXTPROC) load(userptr, "glTextureParameterIivEXT"); + context->TextureParameterIuivEXT = (PFNGLTEXTUREPARAMETERIUIVEXTPROC) load(userptr, "glTextureParameterIuivEXT"); + context->TextureParameterfEXT = (PFNGLTEXTUREPARAMETERFEXTPROC) load(userptr, "glTextureParameterfEXT"); + context->TextureParameterfvEXT = (PFNGLTEXTUREPARAMETERFVEXTPROC) load(userptr, "glTextureParameterfvEXT"); + context->TextureParameteriEXT = (PFNGLTEXTUREPARAMETERIEXTPROC) load(userptr, "glTextureParameteriEXT"); + context->TextureParameterivEXT = (PFNGLTEXTUREPARAMETERIVEXTPROC) load(userptr, "glTextureParameterivEXT"); + context->TextureRenderbufferEXT = (PFNGLTEXTURERENDERBUFFEREXTPROC) load(userptr, "glTextureRenderbufferEXT"); + context->TextureStorage1DEXT = (PFNGLTEXTURESTORAGE1DEXTPROC) load(userptr, "glTextureStorage1DEXT"); + context->TextureStorage2DEXT = (PFNGLTEXTURESTORAGE2DEXTPROC) load(userptr, "glTextureStorage2DEXT"); + context->TextureStorage2DMultisampleEXT = (PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC) load(userptr, "glTextureStorage2DMultisampleEXT"); + context->TextureStorage3DEXT = (PFNGLTEXTURESTORAGE3DEXTPROC) load(userptr, "glTextureStorage3DEXT"); + context->TextureStorage3DMultisampleEXT = (PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC) load(userptr, "glTextureStorage3DMultisampleEXT"); + context->TextureSubImage1DEXT = (PFNGLTEXTURESUBIMAGE1DEXTPROC) load(userptr, "glTextureSubImage1DEXT"); + context->TextureSubImage2DEXT = (PFNGLTEXTURESUBIMAGE2DEXTPROC) load(userptr, "glTextureSubImage2DEXT"); + context->TextureSubImage3DEXT = (PFNGLTEXTURESUBIMAGE3DEXTPROC) load(userptr, "glTextureSubImage3DEXT"); + context->UnmapNamedBufferEXT = (PFNGLUNMAPNAMEDBUFFEREXTPROC) load(userptr, "glUnmapNamedBufferEXT"); + context->VertexArrayBindVertexBufferEXT = (PFNGLVERTEXARRAYBINDVERTEXBUFFEREXTPROC) load(userptr, "glVertexArrayBindVertexBufferEXT"); + context->VertexArrayColorOffsetEXT = (PFNGLVERTEXARRAYCOLOROFFSETEXTPROC) load(userptr, "glVertexArrayColorOffsetEXT"); + context->VertexArrayEdgeFlagOffsetEXT = (PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC) load(userptr, "glVertexArrayEdgeFlagOffsetEXT"); + context->VertexArrayFogCoordOffsetEXT = (PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC) load(userptr, "glVertexArrayFogCoordOffsetEXT"); + context->VertexArrayIndexOffsetEXT = (PFNGLVERTEXARRAYINDEXOFFSETEXTPROC) load(userptr, "glVertexArrayIndexOffsetEXT"); + context->VertexArrayMultiTexCoordOffsetEXT = (PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC) load(userptr, "glVertexArrayMultiTexCoordOffsetEXT"); + context->VertexArrayNormalOffsetEXT = (PFNGLVERTEXARRAYNORMALOFFSETEXTPROC) load(userptr, "glVertexArrayNormalOffsetEXT"); + context->VertexArraySecondaryColorOffsetEXT = (PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC) load(userptr, "glVertexArraySecondaryColorOffsetEXT"); + context->VertexArrayTexCoordOffsetEXT = (PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC) load(userptr, "glVertexArrayTexCoordOffsetEXT"); + context->VertexArrayVertexAttribBindingEXT = (PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC) load(userptr, "glVertexArrayVertexAttribBindingEXT"); + context->VertexArrayVertexAttribDivisorEXT = (PFNGLVERTEXARRAYVERTEXATTRIBDIVISOREXTPROC) load(userptr, "glVertexArrayVertexAttribDivisorEXT"); + context->VertexArrayVertexAttribFormatEXT = (PFNGLVERTEXARRAYVERTEXATTRIBFORMATEXTPROC) load(userptr, "glVertexArrayVertexAttribFormatEXT"); + context->VertexArrayVertexAttribIFormatEXT = (PFNGLVERTEXARRAYVERTEXATTRIBIFORMATEXTPROC) load(userptr, "glVertexArrayVertexAttribIFormatEXT"); + context->VertexArrayVertexAttribIOffsetEXT = (PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC) load(userptr, "glVertexArrayVertexAttribIOffsetEXT"); + context->VertexArrayVertexAttribLFormatEXT = (PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC) load(userptr, "glVertexArrayVertexAttribLFormatEXT"); + context->VertexArrayVertexAttribLOffsetEXT = (PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC) load(userptr, "glVertexArrayVertexAttribLOffsetEXT"); + context->VertexArrayVertexAttribOffsetEXT = (PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC) load(userptr, "glVertexArrayVertexAttribOffsetEXT"); + context->VertexArrayVertexBindingDivisorEXT = (PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC) load(userptr, "glVertexArrayVertexBindingDivisorEXT"); + context->VertexArrayVertexOffsetEXT = (PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC) load(userptr, "glVertexArrayVertexOffsetEXT"); +} +static void glad_gl_load_GL_EXT_draw_buffers2(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_draw_buffers2) return; + context->ColorMaskIndexedEXT = (PFNGLCOLORMASKINDEXEDEXTPROC) load(userptr, "glColorMaskIndexedEXT"); + context->DisableIndexedEXT = (PFNGLDISABLEINDEXEDEXTPROC) load(userptr, "glDisableIndexedEXT"); + context->EnableIndexedEXT = (PFNGLENABLEINDEXEDEXTPROC) load(userptr, "glEnableIndexedEXT"); + context->GetBooleanIndexedvEXT = (PFNGLGETBOOLEANINDEXEDVEXTPROC) load(userptr, "glGetBooleanIndexedvEXT"); + context->GetIntegerIndexedvEXT = (PFNGLGETINTEGERINDEXEDVEXTPROC) load(userptr, "glGetIntegerIndexedvEXT"); + context->IsEnabledIndexedEXT = (PFNGLISENABLEDINDEXEDEXTPROC) load(userptr, "glIsEnabledIndexedEXT"); +} +static void glad_gl_load_GL_EXT_draw_instanced(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_draw_instanced) return; + context->DrawArraysInstancedEXT = (PFNGLDRAWARRAYSINSTANCEDEXTPROC) load(userptr, "glDrawArraysInstancedEXT"); + context->DrawElementsInstancedEXT = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC) load(userptr, "glDrawElementsInstancedEXT"); +} +static void glad_gl_load_GL_EXT_draw_range_elements(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_draw_range_elements) return; + context->DrawRangeElementsEXT = (PFNGLDRAWRANGEELEMENTSEXTPROC) load(userptr, "glDrawRangeElementsEXT"); +} +static void glad_gl_load_GL_EXT_framebuffer_blit(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_framebuffer_blit) return; + context->BlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC) load(userptr, "glBlitFramebufferEXT"); +} +static void glad_gl_load_GL_EXT_framebuffer_multisample(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_framebuffer_multisample) return; + context->RenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) load(userptr, "glRenderbufferStorageMultisampleEXT"); +} +static void glad_gl_load_GL_EXT_framebuffer_object(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_framebuffer_object) return; + context->BindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC) load(userptr, "glBindFramebufferEXT"); + context->BindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC) load(userptr, "glBindRenderbufferEXT"); + context->CheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) load(userptr, "glCheckFramebufferStatusEXT"); + context->DeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC) load(userptr, "glDeleteFramebuffersEXT"); + context->DeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC) load(userptr, "glDeleteRenderbuffersEXT"); + context->FramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) load(userptr, "glFramebufferRenderbufferEXT"); + context->FramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) load(userptr, "glFramebufferTexture1DEXT"); + context->FramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) load(userptr, "glFramebufferTexture2DEXT"); + context->FramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) load(userptr, "glFramebufferTexture3DEXT"); + context->GenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC) load(userptr, "glGenFramebuffersEXT"); + context->GenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC) load(userptr, "glGenRenderbuffersEXT"); + context->GenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC) load(userptr, "glGenerateMipmapEXT"); + context->GetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) load(userptr, "glGetFramebufferAttachmentParameterivEXT"); + context->GetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) load(userptr, "glGetRenderbufferParameterivEXT"); + context->IsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC) load(userptr, "glIsFramebufferEXT"); + context->IsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC) load(userptr, "glIsRenderbufferEXT"); + context->RenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC) load(userptr, "glRenderbufferStorageEXT"); +} +static void glad_gl_load_GL_EXT_gpu_shader4(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_gpu_shader4) return; + context->BindFragDataLocationEXT = (PFNGLBINDFRAGDATALOCATIONEXTPROC) load(userptr, "glBindFragDataLocationEXT"); + context->GetFragDataLocationEXT = (PFNGLGETFRAGDATALOCATIONEXTPROC) load(userptr, "glGetFragDataLocationEXT"); + context->GetUniformuivEXT = (PFNGLGETUNIFORMUIVEXTPROC) load(userptr, "glGetUniformuivEXT"); + context->GetVertexAttribIivEXT = (PFNGLGETVERTEXATTRIBIIVEXTPROC) load(userptr, "glGetVertexAttribIivEXT"); + context->GetVertexAttribIuivEXT = (PFNGLGETVERTEXATTRIBIUIVEXTPROC) load(userptr, "glGetVertexAttribIuivEXT"); + context->Uniform1uiEXT = (PFNGLUNIFORM1UIEXTPROC) load(userptr, "glUniform1uiEXT"); + context->Uniform1uivEXT = (PFNGLUNIFORM1UIVEXTPROC) load(userptr, "glUniform1uivEXT"); + context->Uniform2uiEXT = (PFNGLUNIFORM2UIEXTPROC) load(userptr, "glUniform2uiEXT"); + context->Uniform2uivEXT = (PFNGLUNIFORM2UIVEXTPROC) load(userptr, "glUniform2uivEXT"); + context->Uniform3uiEXT = (PFNGLUNIFORM3UIEXTPROC) load(userptr, "glUniform3uiEXT"); + context->Uniform3uivEXT = (PFNGLUNIFORM3UIVEXTPROC) load(userptr, "glUniform3uivEXT"); + context->Uniform4uiEXT = (PFNGLUNIFORM4UIEXTPROC) load(userptr, "glUniform4uiEXT"); + context->Uniform4uivEXT = (PFNGLUNIFORM4UIVEXTPROC) load(userptr, "glUniform4uivEXT"); + context->VertexAttribI1iEXT = (PFNGLVERTEXATTRIBI1IEXTPROC) load(userptr, "glVertexAttribI1iEXT"); + context->VertexAttribI1ivEXT = (PFNGLVERTEXATTRIBI1IVEXTPROC) load(userptr, "glVertexAttribI1ivEXT"); + context->VertexAttribI1uiEXT = (PFNGLVERTEXATTRIBI1UIEXTPROC) load(userptr, "glVertexAttribI1uiEXT"); + context->VertexAttribI1uivEXT = (PFNGLVERTEXATTRIBI1UIVEXTPROC) load(userptr, "glVertexAttribI1uivEXT"); + context->VertexAttribI2iEXT = (PFNGLVERTEXATTRIBI2IEXTPROC) load(userptr, "glVertexAttribI2iEXT"); + context->VertexAttribI2ivEXT = (PFNGLVERTEXATTRIBI2IVEXTPROC) load(userptr, "glVertexAttribI2ivEXT"); + context->VertexAttribI2uiEXT = (PFNGLVERTEXATTRIBI2UIEXTPROC) load(userptr, "glVertexAttribI2uiEXT"); + context->VertexAttribI2uivEXT = (PFNGLVERTEXATTRIBI2UIVEXTPROC) load(userptr, "glVertexAttribI2uivEXT"); + context->VertexAttribI3iEXT = (PFNGLVERTEXATTRIBI3IEXTPROC) load(userptr, "glVertexAttribI3iEXT"); + context->VertexAttribI3ivEXT = (PFNGLVERTEXATTRIBI3IVEXTPROC) load(userptr, "glVertexAttribI3ivEXT"); + context->VertexAttribI3uiEXT = (PFNGLVERTEXATTRIBI3UIEXTPROC) load(userptr, "glVertexAttribI3uiEXT"); + context->VertexAttribI3uivEXT = (PFNGLVERTEXATTRIBI3UIVEXTPROC) load(userptr, "glVertexAttribI3uivEXT"); + context->VertexAttribI4bvEXT = (PFNGLVERTEXATTRIBI4BVEXTPROC) load(userptr, "glVertexAttribI4bvEXT"); + context->VertexAttribI4iEXT = (PFNGLVERTEXATTRIBI4IEXTPROC) load(userptr, "glVertexAttribI4iEXT"); + context->VertexAttribI4ivEXT = (PFNGLVERTEXATTRIBI4IVEXTPROC) load(userptr, "glVertexAttribI4ivEXT"); + context->VertexAttribI4svEXT = (PFNGLVERTEXATTRIBI4SVEXTPROC) load(userptr, "glVertexAttribI4svEXT"); + context->VertexAttribI4ubvEXT = (PFNGLVERTEXATTRIBI4UBVEXTPROC) load(userptr, "glVertexAttribI4ubvEXT"); + context->VertexAttribI4uiEXT = (PFNGLVERTEXATTRIBI4UIEXTPROC) load(userptr, "glVertexAttribI4uiEXT"); + context->VertexAttribI4uivEXT = (PFNGLVERTEXATTRIBI4UIVEXTPROC) load(userptr, "glVertexAttribI4uivEXT"); + context->VertexAttribI4usvEXT = (PFNGLVERTEXATTRIBI4USVEXTPROC) load(userptr, "glVertexAttribI4usvEXT"); + context->VertexAttribIPointerEXT = (PFNGLVERTEXATTRIBIPOINTEREXTPROC) load(userptr, "glVertexAttribIPointerEXT"); +} +static void glad_gl_load_GL_EXT_multi_draw_arrays(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_multi_draw_arrays) return; + context->MultiDrawArraysEXT = (PFNGLMULTIDRAWARRAYSEXTPROC) load(userptr, "glMultiDrawArraysEXT"); + context->MultiDrawElementsEXT = (PFNGLMULTIDRAWELEMENTSEXTPROC) load(userptr, "glMultiDrawElementsEXT"); +} +static void glad_gl_load_GL_EXT_point_parameters(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_point_parameters) return; + context->PointParameterfEXT = (PFNGLPOINTPARAMETERFEXTPROC) load(userptr, "glPointParameterfEXT"); + context->PointParameterfvEXT = (PFNGLPOINTPARAMETERFVEXTPROC) load(userptr, "glPointParameterfvEXT"); +} +static void glad_gl_load_GL_EXT_provoking_vertex(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_provoking_vertex) return; + context->ProvokingVertexEXT = (PFNGLPROVOKINGVERTEXEXTPROC) load(userptr, "glProvokingVertexEXT"); +} +static void glad_gl_load_GL_EXT_subtexture(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_subtexture) return; + context->TexSubImage1DEXT = (PFNGLTEXSUBIMAGE1DEXTPROC) load(userptr, "glTexSubImage1DEXT"); + context->TexSubImage2DEXT = (PFNGLTEXSUBIMAGE2DEXTPROC) load(userptr, "glTexSubImage2DEXT"); +} +static void glad_gl_load_GL_EXT_texture3D(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_texture3D) return; + context->TexImage3DEXT = (PFNGLTEXIMAGE3DEXTPROC) load(userptr, "glTexImage3DEXT"); + context->TexSubImage3DEXT = (PFNGLTEXSUBIMAGE3DEXTPROC) load(userptr, "glTexSubImage3DEXT"); +} +static void glad_gl_load_GL_EXT_texture_array(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_texture_array) return; + context->FramebufferTextureLayerEXT = (PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) load(userptr, "glFramebufferTextureLayerEXT"); +} +static void glad_gl_load_GL_EXT_texture_buffer_object(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_texture_buffer_object) return; + context->TexBufferEXT = (PFNGLTEXBUFFEREXTPROC) load(userptr, "glTexBufferEXT"); +} +static void glad_gl_load_GL_EXT_texture_integer(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_texture_integer) return; + context->ClearColorIiEXT = (PFNGLCLEARCOLORIIEXTPROC) load(userptr, "glClearColorIiEXT"); + context->ClearColorIuiEXT = (PFNGLCLEARCOLORIUIEXTPROC) load(userptr, "glClearColorIuiEXT"); + context->GetTexParameterIivEXT = (PFNGLGETTEXPARAMETERIIVEXTPROC) load(userptr, "glGetTexParameterIivEXT"); + context->GetTexParameterIuivEXT = (PFNGLGETTEXPARAMETERIUIVEXTPROC) load(userptr, "glGetTexParameterIuivEXT"); + context->TexParameterIivEXT = (PFNGLTEXPARAMETERIIVEXTPROC) load(userptr, "glTexParameterIivEXT"); + context->TexParameterIuivEXT = (PFNGLTEXPARAMETERIUIVEXTPROC) load(userptr, "glTexParameterIuivEXT"); +} +static void glad_gl_load_GL_EXT_texture_object(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_texture_object) return; + context->AreTexturesResidentEXT = (PFNGLARETEXTURESRESIDENTEXTPROC) load(userptr, "glAreTexturesResidentEXT"); + context->BindTextureEXT = (PFNGLBINDTEXTUREEXTPROC) load(userptr, "glBindTextureEXT"); + context->DeleteTexturesEXT = (PFNGLDELETETEXTURESEXTPROC) load(userptr, "glDeleteTexturesEXT"); + context->GenTexturesEXT = (PFNGLGENTEXTURESEXTPROC) load(userptr, "glGenTexturesEXT"); + context->IsTextureEXT = (PFNGLISTEXTUREEXTPROC) load(userptr, "glIsTextureEXT"); + context->PrioritizeTexturesEXT = (PFNGLPRIORITIZETEXTURESEXTPROC) load(userptr, "glPrioritizeTexturesEXT"); +} +static void glad_gl_load_GL_EXT_transform_feedback(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_transform_feedback) return; + context->BeginTransformFeedbackEXT = (PFNGLBEGINTRANSFORMFEEDBACKEXTPROC) load(userptr, "glBeginTransformFeedbackEXT"); + context->BindBufferBaseEXT = (PFNGLBINDBUFFERBASEEXTPROC) load(userptr, "glBindBufferBaseEXT"); + context->BindBufferOffsetEXT = (PFNGLBINDBUFFEROFFSETEXTPROC) load(userptr, "glBindBufferOffsetEXT"); + context->BindBufferRangeEXT = (PFNGLBINDBUFFERRANGEEXTPROC) load(userptr, "glBindBufferRangeEXT"); + context->EndTransformFeedbackEXT = (PFNGLENDTRANSFORMFEEDBACKEXTPROC) load(userptr, "glEndTransformFeedbackEXT"); + context->GetTransformFeedbackVaryingEXT = (PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) load(userptr, "glGetTransformFeedbackVaryingEXT"); + context->TransformFeedbackVaryingsEXT = (PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) load(userptr, "glTransformFeedbackVaryingsEXT"); +} +static void glad_gl_load_GL_EXT_vertex_array(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->EXT_vertex_array) return; + context->ArrayElementEXT = (PFNGLARRAYELEMENTEXTPROC) load(userptr, "glArrayElementEXT"); + context->ColorPointerEXT = (PFNGLCOLORPOINTEREXTPROC) load(userptr, "glColorPointerEXT"); + context->DrawArraysEXT = (PFNGLDRAWARRAYSEXTPROC) load(userptr, "glDrawArraysEXT"); + context->EdgeFlagPointerEXT = (PFNGLEDGEFLAGPOINTEREXTPROC) load(userptr, "glEdgeFlagPointerEXT"); + context->GetPointervEXT = (PFNGLGETPOINTERVEXTPROC) load(userptr, "glGetPointervEXT"); + context->IndexPointerEXT = (PFNGLINDEXPOINTEREXTPROC) load(userptr, "glIndexPointerEXT"); + context->NormalPointerEXT = (PFNGLNORMALPOINTEREXTPROC) load(userptr, "glNormalPointerEXT"); + context->TexCoordPointerEXT = (PFNGLTEXCOORDPOINTEREXTPROC) load(userptr, "glTexCoordPointerEXT"); + context->VertexPointerEXT = (PFNGLVERTEXPOINTEREXTPROC) load(userptr, "glVertexPointerEXT"); +} +static void glad_gl_load_GL_INGR_blend_func_separate(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->INGR_blend_func_separate) return; + context->BlendFuncSeparateINGR = (PFNGLBLENDFUNCSEPARATEINGRPROC) load(userptr, "glBlendFuncSeparateINGR"); +} +static void glad_gl_load_GL_NVX_conditional_render(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->NVX_conditional_render) return; + context->BeginConditionalRenderNVX = (PFNGLBEGINCONDITIONALRENDERNVXPROC) load(userptr, "glBeginConditionalRenderNVX"); + context->EndConditionalRenderNVX = (PFNGLENDCONDITIONALRENDERNVXPROC) load(userptr, "glEndConditionalRenderNVX"); +} +static void glad_gl_load_GL_NV_conditional_render(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->NV_conditional_render) return; + context->BeginConditionalRenderNV = (PFNGLBEGINCONDITIONALRENDERNVPROC) load(userptr, "glBeginConditionalRenderNV"); + context->EndConditionalRenderNV = (PFNGLENDCONDITIONALRENDERNVPROC) load(userptr, "glEndConditionalRenderNV"); +} +static void glad_gl_load_GL_NV_explicit_multisample(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->NV_explicit_multisample) return; + context->GetMultisamplefvNV = (PFNGLGETMULTISAMPLEFVNVPROC) load(userptr, "glGetMultisamplefvNV"); + context->SampleMaskIndexedNV = (PFNGLSAMPLEMASKINDEXEDNVPROC) load(userptr, "glSampleMaskIndexedNV"); + context->TexRenderbufferNV = (PFNGLTEXRENDERBUFFERNVPROC) load(userptr, "glTexRenderbufferNV"); +} +static void glad_gl_load_GL_NV_geometry_program4(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->NV_geometry_program4) return; + context->FramebufferTextureEXT = (PFNGLFRAMEBUFFERTEXTUREEXTPROC) load(userptr, "glFramebufferTextureEXT"); + context->FramebufferTextureFaceEXT = (PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) load(userptr, "glFramebufferTextureFaceEXT"); + context->FramebufferTextureLayerEXT = (PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) load(userptr, "glFramebufferTextureLayerEXT"); + context->ProgramVertexLimitNV = (PFNGLPROGRAMVERTEXLIMITNVPROC) load(userptr, "glProgramVertexLimitNV"); +} +static void glad_gl_load_GL_NV_point_sprite(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->NV_point_sprite) return; + context->PointParameteriNV = (PFNGLPOINTPARAMETERINVPROC) load(userptr, "glPointParameteriNV"); + context->PointParameterivNV = (PFNGLPOINTPARAMETERIVNVPROC) load(userptr, "glPointParameterivNV"); +} +static void glad_gl_load_GL_NV_transform_feedback(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->NV_transform_feedback) return; + context->ActiveVaryingNV = (PFNGLACTIVEVARYINGNVPROC) load(userptr, "glActiveVaryingNV"); + context->BeginTransformFeedbackNV = (PFNGLBEGINTRANSFORMFEEDBACKNVPROC) load(userptr, "glBeginTransformFeedbackNV"); + context->BindBufferBaseNV = (PFNGLBINDBUFFERBASENVPROC) load(userptr, "glBindBufferBaseNV"); + context->BindBufferOffsetNV = (PFNGLBINDBUFFEROFFSETNVPROC) load(userptr, "glBindBufferOffsetNV"); + context->BindBufferRangeNV = (PFNGLBINDBUFFERRANGENVPROC) load(userptr, "glBindBufferRangeNV"); + context->EndTransformFeedbackNV = (PFNGLENDTRANSFORMFEEDBACKNVPROC) load(userptr, "glEndTransformFeedbackNV"); + context->GetActiveVaryingNV = (PFNGLGETACTIVEVARYINGNVPROC) load(userptr, "glGetActiveVaryingNV"); + context->GetTransformFeedbackVaryingNV = (PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC) load(userptr, "glGetTransformFeedbackVaryingNV"); + context->GetVaryingLocationNV = (PFNGLGETVARYINGLOCATIONNVPROC) load(userptr, "glGetVaryingLocationNV"); + context->TransformFeedbackAttribsNV = (PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) load(userptr, "glTransformFeedbackAttribsNV"); + context->TransformFeedbackStreamAttribsNV = (PFNGLTRANSFORMFEEDBACKSTREAMATTRIBSNVPROC) load(userptr, "glTransformFeedbackStreamAttribsNV"); + context->TransformFeedbackVaryingsNV = (PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) load(userptr, "glTransformFeedbackVaryingsNV"); +} +static void glad_gl_load_GL_NV_vertex_program(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->NV_vertex_program) return; + context->AreProgramsResidentNV = (PFNGLAREPROGRAMSRESIDENTNVPROC) load(userptr, "glAreProgramsResidentNV"); + context->BindProgramNV = (PFNGLBINDPROGRAMNVPROC) load(userptr, "glBindProgramNV"); + context->DeleteProgramsNV = (PFNGLDELETEPROGRAMSNVPROC) load(userptr, "glDeleteProgramsNV"); + context->ExecuteProgramNV = (PFNGLEXECUTEPROGRAMNVPROC) load(userptr, "glExecuteProgramNV"); + context->GenProgramsNV = (PFNGLGENPROGRAMSNVPROC) load(userptr, "glGenProgramsNV"); + context->GetProgramParameterdvNV = (PFNGLGETPROGRAMPARAMETERDVNVPROC) load(userptr, "glGetProgramParameterdvNV"); + context->GetProgramParameterfvNV = (PFNGLGETPROGRAMPARAMETERFVNVPROC) load(userptr, "glGetProgramParameterfvNV"); + context->GetProgramStringNV = (PFNGLGETPROGRAMSTRINGNVPROC) load(userptr, "glGetProgramStringNV"); + context->GetProgramivNV = (PFNGLGETPROGRAMIVNVPROC) load(userptr, "glGetProgramivNV"); + context->GetTrackMatrixivNV = (PFNGLGETTRACKMATRIXIVNVPROC) load(userptr, "glGetTrackMatrixivNV"); + context->GetVertexAttribPointervNV = (PFNGLGETVERTEXATTRIBPOINTERVNVPROC) load(userptr, "glGetVertexAttribPointervNV"); + context->GetVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) load(userptr, "glGetVertexAttribdvNV"); + context->GetVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) load(userptr, "glGetVertexAttribfvNV"); + context->GetVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) load(userptr, "glGetVertexAttribivNV"); + context->IsProgramNV = (PFNGLISPROGRAMNVPROC) load(userptr, "glIsProgramNV"); + context->LoadProgramNV = (PFNGLLOADPROGRAMNVPROC) load(userptr, "glLoadProgramNV"); + context->ProgramParameter4dNV = (PFNGLPROGRAMPARAMETER4DNVPROC) load(userptr, "glProgramParameter4dNV"); + context->ProgramParameter4dvNV = (PFNGLPROGRAMPARAMETER4DVNVPROC) load(userptr, "glProgramParameter4dvNV"); + context->ProgramParameter4fNV = (PFNGLPROGRAMPARAMETER4FNVPROC) load(userptr, "glProgramParameter4fNV"); + context->ProgramParameter4fvNV = (PFNGLPROGRAMPARAMETER4FVNVPROC) load(userptr, "glProgramParameter4fvNV"); + context->ProgramParameters4dvNV = (PFNGLPROGRAMPARAMETERS4DVNVPROC) load(userptr, "glProgramParameters4dvNV"); + context->ProgramParameters4fvNV = (PFNGLPROGRAMPARAMETERS4FVNVPROC) load(userptr, "glProgramParameters4fvNV"); + context->RequestResidentProgramsNV = (PFNGLREQUESTRESIDENTPROGRAMSNVPROC) load(userptr, "glRequestResidentProgramsNV"); + context->TrackMatrixNV = (PFNGLTRACKMATRIXNVPROC) load(userptr, "glTrackMatrixNV"); + context->VertexAttrib1dNV = (PFNGLVERTEXATTRIB1DNVPROC) load(userptr, "glVertexAttrib1dNV"); + context->VertexAttrib1dvNV = (PFNGLVERTEXATTRIB1DVNVPROC) load(userptr, "glVertexAttrib1dvNV"); + context->VertexAttrib1fNV = (PFNGLVERTEXATTRIB1FNVPROC) load(userptr, "glVertexAttrib1fNV"); + context->VertexAttrib1fvNV = (PFNGLVERTEXATTRIB1FVNVPROC) load(userptr, "glVertexAttrib1fvNV"); + context->VertexAttrib1sNV = (PFNGLVERTEXATTRIB1SNVPROC) load(userptr, "glVertexAttrib1sNV"); + context->VertexAttrib1svNV = (PFNGLVERTEXATTRIB1SVNVPROC) load(userptr, "glVertexAttrib1svNV"); + context->VertexAttrib2dNV = (PFNGLVERTEXATTRIB2DNVPROC) load(userptr, "glVertexAttrib2dNV"); + context->VertexAttrib2dvNV = (PFNGLVERTEXATTRIB2DVNVPROC) load(userptr, "glVertexAttrib2dvNV"); + context->VertexAttrib2fNV = (PFNGLVERTEXATTRIB2FNVPROC) load(userptr, "glVertexAttrib2fNV"); + context->VertexAttrib2fvNV = (PFNGLVERTEXATTRIB2FVNVPROC) load(userptr, "glVertexAttrib2fvNV"); + context->VertexAttrib2sNV = (PFNGLVERTEXATTRIB2SNVPROC) load(userptr, "glVertexAttrib2sNV"); + context->VertexAttrib2svNV = (PFNGLVERTEXATTRIB2SVNVPROC) load(userptr, "glVertexAttrib2svNV"); + context->VertexAttrib3dNV = (PFNGLVERTEXATTRIB3DNVPROC) load(userptr, "glVertexAttrib3dNV"); + context->VertexAttrib3dvNV = (PFNGLVERTEXATTRIB3DVNVPROC) load(userptr, "glVertexAttrib3dvNV"); + context->VertexAttrib3fNV = (PFNGLVERTEXATTRIB3FNVPROC) load(userptr, "glVertexAttrib3fNV"); + context->VertexAttrib3fvNV = (PFNGLVERTEXATTRIB3FVNVPROC) load(userptr, "glVertexAttrib3fvNV"); + context->VertexAttrib3sNV = (PFNGLVERTEXATTRIB3SNVPROC) load(userptr, "glVertexAttrib3sNV"); + context->VertexAttrib3svNV = (PFNGLVERTEXATTRIB3SVNVPROC) load(userptr, "glVertexAttrib3svNV"); + context->VertexAttrib4dNV = (PFNGLVERTEXATTRIB4DNVPROC) load(userptr, "glVertexAttrib4dNV"); + context->VertexAttrib4dvNV = (PFNGLVERTEXATTRIB4DVNVPROC) load(userptr, "glVertexAttrib4dvNV"); + context->VertexAttrib4fNV = (PFNGLVERTEXATTRIB4FNVPROC) load(userptr, "glVertexAttrib4fNV"); + context->VertexAttrib4fvNV = (PFNGLVERTEXATTRIB4FVNVPROC) load(userptr, "glVertexAttrib4fvNV"); + context->VertexAttrib4sNV = (PFNGLVERTEXATTRIB4SNVPROC) load(userptr, "glVertexAttrib4sNV"); + context->VertexAttrib4svNV = (PFNGLVERTEXATTRIB4SVNVPROC) load(userptr, "glVertexAttrib4svNV"); + context->VertexAttrib4ubNV = (PFNGLVERTEXATTRIB4UBNVPROC) load(userptr, "glVertexAttrib4ubNV"); + context->VertexAttrib4ubvNV = (PFNGLVERTEXATTRIB4UBVNVPROC) load(userptr, "glVertexAttrib4ubvNV"); + context->VertexAttribPointerNV = (PFNGLVERTEXATTRIBPOINTERNVPROC) load(userptr, "glVertexAttribPointerNV"); + context->VertexAttribs1dvNV = (PFNGLVERTEXATTRIBS1DVNVPROC) load(userptr, "glVertexAttribs1dvNV"); + context->VertexAttribs1fvNV = (PFNGLVERTEXATTRIBS1FVNVPROC) load(userptr, "glVertexAttribs1fvNV"); + context->VertexAttribs1svNV = (PFNGLVERTEXATTRIBS1SVNVPROC) load(userptr, "glVertexAttribs1svNV"); + context->VertexAttribs2dvNV = (PFNGLVERTEXATTRIBS2DVNVPROC) load(userptr, "glVertexAttribs2dvNV"); + context->VertexAttribs2fvNV = (PFNGLVERTEXATTRIBS2FVNVPROC) load(userptr, "glVertexAttribs2fvNV"); + context->VertexAttribs2svNV = (PFNGLVERTEXATTRIBS2SVNVPROC) load(userptr, "glVertexAttribs2svNV"); + context->VertexAttribs3dvNV = (PFNGLVERTEXATTRIBS3DVNVPROC) load(userptr, "glVertexAttribs3dvNV"); + context->VertexAttribs3fvNV = (PFNGLVERTEXATTRIBS3FVNVPROC) load(userptr, "glVertexAttribs3fvNV"); + context->VertexAttribs3svNV = (PFNGLVERTEXATTRIBS3SVNVPROC) load(userptr, "glVertexAttribs3svNV"); + context->VertexAttribs4dvNV = (PFNGLVERTEXATTRIBS4DVNVPROC) load(userptr, "glVertexAttribs4dvNV"); + context->VertexAttribs4fvNV = (PFNGLVERTEXATTRIBS4FVNVPROC) load(userptr, "glVertexAttribs4fvNV"); + context->VertexAttribs4svNV = (PFNGLVERTEXATTRIBS4SVNVPROC) load(userptr, "glVertexAttribs4svNV"); + context->VertexAttribs4ubvNV = (PFNGLVERTEXATTRIBS4UBVNVPROC) load(userptr, "glVertexAttribs4ubvNV"); +} +static void glad_gl_load_GL_NV_vertex_program4(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->NV_vertex_program4) return; + context->GetVertexAttribIivEXT = (PFNGLGETVERTEXATTRIBIIVEXTPROC) load(userptr, "glGetVertexAttribIivEXT"); + context->GetVertexAttribIuivEXT = (PFNGLGETVERTEXATTRIBIUIVEXTPROC) load(userptr, "glGetVertexAttribIuivEXT"); + context->VertexAttribI1iEXT = (PFNGLVERTEXATTRIBI1IEXTPROC) load(userptr, "glVertexAttribI1iEXT"); + context->VertexAttribI1ivEXT = (PFNGLVERTEXATTRIBI1IVEXTPROC) load(userptr, "glVertexAttribI1ivEXT"); + context->VertexAttribI1uiEXT = (PFNGLVERTEXATTRIBI1UIEXTPROC) load(userptr, "glVertexAttribI1uiEXT"); + context->VertexAttribI1uivEXT = (PFNGLVERTEXATTRIBI1UIVEXTPROC) load(userptr, "glVertexAttribI1uivEXT"); + context->VertexAttribI2iEXT = (PFNGLVERTEXATTRIBI2IEXTPROC) load(userptr, "glVertexAttribI2iEXT"); + context->VertexAttribI2ivEXT = (PFNGLVERTEXATTRIBI2IVEXTPROC) load(userptr, "glVertexAttribI2ivEXT"); + context->VertexAttribI2uiEXT = (PFNGLVERTEXATTRIBI2UIEXTPROC) load(userptr, "glVertexAttribI2uiEXT"); + context->VertexAttribI2uivEXT = (PFNGLVERTEXATTRIBI2UIVEXTPROC) load(userptr, "glVertexAttribI2uivEXT"); + context->VertexAttribI3iEXT = (PFNGLVERTEXATTRIBI3IEXTPROC) load(userptr, "glVertexAttribI3iEXT"); + context->VertexAttribI3ivEXT = (PFNGLVERTEXATTRIBI3IVEXTPROC) load(userptr, "glVertexAttribI3ivEXT"); + context->VertexAttribI3uiEXT = (PFNGLVERTEXATTRIBI3UIEXTPROC) load(userptr, "glVertexAttribI3uiEXT"); + context->VertexAttribI3uivEXT = (PFNGLVERTEXATTRIBI3UIVEXTPROC) load(userptr, "glVertexAttribI3uivEXT"); + context->VertexAttribI4bvEXT = (PFNGLVERTEXATTRIBI4BVEXTPROC) load(userptr, "glVertexAttribI4bvEXT"); + context->VertexAttribI4iEXT = (PFNGLVERTEXATTRIBI4IEXTPROC) load(userptr, "glVertexAttribI4iEXT"); + context->VertexAttribI4ivEXT = (PFNGLVERTEXATTRIBI4IVEXTPROC) load(userptr, "glVertexAttribI4ivEXT"); + context->VertexAttribI4svEXT = (PFNGLVERTEXATTRIBI4SVEXTPROC) load(userptr, "glVertexAttribI4svEXT"); + context->VertexAttribI4ubvEXT = (PFNGLVERTEXATTRIBI4UBVEXTPROC) load(userptr, "glVertexAttribI4ubvEXT"); + context->VertexAttribI4uiEXT = (PFNGLVERTEXATTRIBI4UIEXTPROC) load(userptr, "glVertexAttribI4uiEXT"); + context->VertexAttribI4uivEXT = (PFNGLVERTEXATTRIBI4UIVEXTPROC) load(userptr, "glVertexAttribI4uivEXT"); + context->VertexAttribI4usvEXT = (PFNGLVERTEXATTRIBI4USVEXTPROC) load(userptr, "glVertexAttribI4usvEXT"); + context->VertexAttribIPointerEXT = (PFNGLVERTEXATTRIBIPOINTEREXTPROC) load(userptr, "glVertexAttribIPointerEXT"); +} +static void glad_gl_load_GL_SGIS_point_parameters(GladGLContext *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->SGIS_point_parameters) return; + context->PointParameterfSGIS = (PFNGLPOINTPARAMETERFSGISPROC) load(userptr, "glPointParameterfSGIS"); + context->PointParameterfvSGIS = (PFNGLPOINTPARAMETERFVSGISPROC) load(userptr, "glPointParameterfvSGIS"); +} + + +static void glad_gl_resolve_aliases(GladGLContext *context) { + if (context->ActiveTexture == NULL && context->ActiveTextureARB != NULL) context->ActiveTexture = (PFNGLACTIVETEXTUREPROC)context->ActiveTextureARB; + if (context->ActiveTextureARB == NULL && context->ActiveTexture != NULL) context->ActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)context->ActiveTexture; + if (context->AttachObjectARB == NULL && context->AttachShader != NULL) context->AttachObjectARB = (PFNGLATTACHOBJECTARBPROC)context->AttachShader; + if (context->AttachShader == NULL && context->AttachObjectARB != NULL) context->AttachShader = (PFNGLATTACHSHADERPROC)context->AttachObjectARB; + if (context->BeginConditionalRender == NULL && context->BeginConditionalRenderNV != NULL) context->BeginConditionalRender = (PFNGLBEGINCONDITIONALRENDERPROC)context->BeginConditionalRenderNV; + if (context->BeginConditionalRenderNV == NULL && context->BeginConditionalRender != NULL) context->BeginConditionalRenderNV = (PFNGLBEGINCONDITIONALRENDERNVPROC)context->BeginConditionalRender; + if (context->BeginQuery == NULL && context->BeginQueryARB != NULL) context->BeginQuery = (PFNGLBEGINQUERYPROC)context->BeginQueryARB; + if (context->BeginQueryARB == NULL && context->BeginQuery != NULL) context->BeginQueryARB = (PFNGLBEGINQUERYARBPROC)context->BeginQuery; + if (context->BeginTransformFeedback == NULL && context->BeginTransformFeedbackEXT != NULL) context->BeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC)context->BeginTransformFeedbackEXT; + if (context->BeginTransformFeedback == NULL && context->BeginTransformFeedbackNV != NULL) context->BeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC)context->BeginTransformFeedbackNV; + if (context->BeginTransformFeedbackEXT == NULL && context->BeginTransformFeedback != NULL) context->BeginTransformFeedbackEXT = (PFNGLBEGINTRANSFORMFEEDBACKEXTPROC)context->BeginTransformFeedback; + if (context->BeginTransformFeedbackEXT == NULL && context->BeginTransformFeedbackNV != NULL) context->BeginTransformFeedbackEXT = (PFNGLBEGINTRANSFORMFEEDBACKEXTPROC)context->BeginTransformFeedbackNV; + if (context->BeginTransformFeedbackNV == NULL && context->BeginTransformFeedback != NULL) context->BeginTransformFeedbackNV = (PFNGLBEGINTRANSFORMFEEDBACKNVPROC)context->BeginTransformFeedback; + if (context->BeginTransformFeedbackNV == NULL && context->BeginTransformFeedbackEXT != NULL) context->BeginTransformFeedbackNV = (PFNGLBEGINTRANSFORMFEEDBACKNVPROC)context->BeginTransformFeedbackEXT; + if (context->BindAttribLocation == NULL && context->BindAttribLocationARB != NULL) context->BindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)context->BindAttribLocationARB; + if (context->BindAttribLocationARB == NULL && context->BindAttribLocation != NULL) context->BindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC)context->BindAttribLocation; + if (context->BindBuffer == NULL && context->BindBufferARB != NULL) context->BindBuffer = (PFNGLBINDBUFFERPROC)context->BindBufferARB; + if (context->BindBufferARB == NULL && context->BindBuffer != NULL) context->BindBufferARB = (PFNGLBINDBUFFERARBPROC)context->BindBuffer; + if (context->BindBufferBase == NULL && context->BindBufferBaseEXT != NULL) context->BindBufferBase = (PFNGLBINDBUFFERBASEPROC)context->BindBufferBaseEXT; + if (context->BindBufferBase == NULL && context->BindBufferBaseNV != NULL) context->BindBufferBase = (PFNGLBINDBUFFERBASEPROC)context->BindBufferBaseNV; + if (context->BindBufferBaseEXT == NULL && context->BindBufferBase != NULL) context->BindBufferBaseEXT = (PFNGLBINDBUFFERBASEEXTPROC)context->BindBufferBase; + if (context->BindBufferBaseEXT == NULL && context->BindBufferBaseNV != NULL) context->BindBufferBaseEXT = (PFNGLBINDBUFFERBASEEXTPROC)context->BindBufferBaseNV; + if (context->BindBufferBaseNV == NULL && context->BindBufferBase != NULL) context->BindBufferBaseNV = (PFNGLBINDBUFFERBASENVPROC)context->BindBufferBase; + if (context->BindBufferBaseNV == NULL && context->BindBufferBaseEXT != NULL) context->BindBufferBaseNV = (PFNGLBINDBUFFERBASENVPROC)context->BindBufferBaseEXT; + if (context->BindBufferOffsetEXT == NULL && context->BindBufferOffsetNV != NULL) context->BindBufferOffsetEXT = (PFNGLBINDBUFFEROFFSETEXTPROC)context->BindBufferOffsetNV; + if (context->BindBufferOffsetNV == NULL && context->BindBufferOffsetEXT != NULL) context->BindBufferOffsetNV = (PFNGLBINDBUFFEROFFSETNVPROC)context->BindBufferOffsetEXT; + if (context->BindBufferRange == NULL && context->BindBufferRangeEXT != NULL) context->BindBufferRange = (PFNGLBINDBUFFERRANGEPROC)context->BindBufferRangeEXT; + if (context->BindBufferRange == NULL && context->BindBufferRangeNV != NULL) context->BindBufferRange = (PFNGLBINDBUFFERRANGEPROC)context->BindBufferRangeNV; + if (context->BindBufferRangeEXT == NULL && context->BindBufferRange != NULL) context->BindBufferRangeEXT = (PFNGLBINDBUFFERRANGEEXTPROC)context->BindBufferRange; + if (context->BindBufferRangeEXT == NULL && context->BindBufferRangeNV != NULL) context->BindBufferRangeEXT = (PFNGLBINDBUFFERRANGEEXTPROC)context->BindBufferRangeNV; + if (context->BindBufferRangeNV == NULL && context->BindBufferRange != NULL) context->BindBufferRangeNV = (PFNGLBINDBUFFERRANGENVPROC)context->BindBufferRange; + if (context->BindBufferRangeNV == NULL && context->BindBufferRangeEXT != NULL) context->BindBufferRangeNV = (PFNGLBINDBUFFERRANGENVPROC)context->BindBufferRangeEXT; + if (context->BindFragDataLocation == NULL && context->BindFragDataLocationEXT != NULL) context->BindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC)context->BindFragDataLocationEXT; + if (context->BindFragDataLocationEXT == NULL && context->BindFragDataLocation != NULL) context->BindFragDataLocationEXT = (PFNGLBINDFRAGDATALOCATIONEXTPROC)context->BindFragDataLocation; + if (context->BindProgramARB == NULL && context->BindProgramNV != NULL) context->BindProgramARB = (PFNGLBINDPROGRAMARBPROC)context->BindProgramNV; + if (context->BindProgramNV == NULL && context->BindProgramARB != NULL) context->BindProgramNV = (PFNGLBINDPROGRAMNVPROC)context->BindProgramARB; + if (context->BindTexture == NULL && context->BindTextureEXT != NULL) context->BindTexture = (PFNGLBINDTEXTUREPROC)context->BindTextureEXT; + if (context->BindTextureEXT == NULL && context->BindTexture != NULL) context->BindTextureEXT = (PFNGLBINDTEXTUREEXTPROC)context->BindTexture; + if (context->BlendColor == NULL && context->BlendColorEXT != NULL) context->BlendColor = (PFNGLBLENDCOLORPROC)context->BlendColorEXT; + if (context->BlendColorEXT == NULL && context->BlendColor != NULL) context->BlendColorEXT = (PFNGLBLENDCOLOREXTPROC)context->BlendColor; + if (context->BlendEquation == NULL && context->BlendEquationEXT != NULL) context->BlendEquation = (PFNGLBLENDEQUATIONPROC)context->BlendEquationEXT; + if (context->BlendEquationEXT == NULL && context->BlendEquation != NULL) context->BlendEquationEXT = (PFNGLBLENDEQUATIONEXTPROC)context->BlendEquation; + if (context->BlendEquationSeparate == NULL && context->BlendEquationSeparateEXT != NULL) context->BlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC)context->BlendEquationSeparateEXT; + if (context->BlendEquationSeparateEXT == NULL && context->BlendEquationSeparate != NULL) context->BlendEquationSeparateEXT = (PFNGLBLENDEQUATIONSEPARATEEXTPROC)context->BlendEquationSeparate; + if (context->BlendFuncSeparate == NULL && context->BlendFuncSeparateEXT != NULL) context->BlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC)context->BlendFuncSeparateEXT; + if (context->BlendFuncSeparate == NULL && context->BlendFuncSeparateINGR != NULL) context->BlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC)context->BlendFuncSeparateINGR; + if (context->BlendFuncSeparateEXT == NULL && context->BlendFuncSeparate != NULL) context->BlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC)context->BlendFuncSeparate; + if (context->BlendFuncSeparateEXT == NULL && context->BlendFuncSeparateINGR != NULL) context->BlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC)context->BlendFuncSeparateINGR; + if (context->BlendFuncSeparateINGR == NULL && context->BlendFuncSeparate != NULL) context->BlendFuncSeparateINGR = (PFNGLBLENDFUNCSEPARATEINGRPROC)context->BlendFuncSeparate; + if (context->BlendFuncSeparateINGR == NULL && context->BlendFuncSeparateEXT != NULL) context->BlendFuncSeparateINGR = (PFNGLBLENDFUNCSEPARATEINGRPROC)context->BlendFuncSeparateEXT; + if (context->BlitFramebuffer == NULL && context->BlitFramebufferEXT != NULL) context->BlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)context->BlitFramebufferEXT; + if (context->BlitFramebufferEXT == NULL && context->BlitFramebuffer != NULL) context->BlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC)context->BlitFramebuffer; + if (context->BufferData == NULL && context->BufferDataARB != NULL) context->BufferData = (PFNGLBUFFERDATAPROC)context->BufferDataARB; + if (context->BufferDataARB == NULL && context->BufferData != NULL) context->BufferDataARB = (PFNGLBUFFERDATAARBPROC)context->BufferData; + if (context->BufferSubData == NULL && context->BufferSubDataARB != NULL) context->BufferSubData = (PFNGLBUFFERSUBDATAPROC)context->BufferSubDataARB; + if (context->BufferSubDataARB == NULL && context->BufferSubData != NULL) context->BufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC)context->BufferSubData; + if (context->CheckFramebufferStatus == NULL && context->CheckFramebufferStatusEXT != NULL) context->CheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)context->CheckFramebufferStatusEXT; + if (context->CheckFramebufferStatusEXT == NULL && context->CheckFramebufferStatus != NULL) context->CheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)context->CheckFramebufferStatus; + if (context->ClampColor == NULL && context->ClampColorARB != NULL) context->ClampColor = (PFNGLCLAMPCOLORPROC)context->ClampColorARB; + if (context->ClampColorARB == NULL && context->ClampColor != NULL) context->ClampColorARB = (PFNGLCLAMPCOLORARBPROC)context->ClampColor; + if (context->ColorMaski == NULL && context->ColorMaskIndexedEXT != NULL) context->ColorMaski = (PFNGLCOLORMASKIPROC)context->ColorMaskIndexedEXT; + if (context->ColorMaskIndexedEXT == NULL && context->ColorMaski != NULL) context->ColorMaskIndexedEXT = (PFNGLCOLORMASKINDEXEDEXTPROC)context->ColorMaski; + if (context->CompileShader == NULL && context->CompileShaderARB != NULL) context->CompileShader = (PFNGLCOMPILESHADERPROC)context->CompileShaderARB; + if (context->CompileShaderARB == NULL && context->CompileShader != NULL) context->CompileShaderARB = (PFNGLCOMPILESHADERARBPROC)context->CompileShader; + if (context->CompressedTexImage1D == NULL && context->CompressedTexImage1DARB != NULL) context->CompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC)context->CompressedTexImage1DARB; + if (context->CompressedTexImage1DARB == NULL && context->CompressedTexImage1D != NULL) context->CompressedTexImage1DARB = (PFNGLCOMPRESSEDTEXIMAGE1DARBPROC)context->CompressedTexImage1D; + if (context->CompressedTexImage2D == NULL && context->CompressedTexImage2DARB != NULL) context->CompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)context->CompressedTexImage2DARB; + if (context->CompressedTexImage2DARB == NULL && context->CompressedTexImage2D != NULL) context->CompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DARBPROC)context->CompressedTexImage2D; + if (context->CompressedTexImage3D == NULL && context->CompressedTexImage3DARB != NULL) context->CompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC)context->CompressedTexImage3DARB; + if (context->CompressedTexImage3DARB == NULL && context->CompressedTexImage3D != NULL) context->CompressedTexImage3DARB = (PFNGLCOMPRESSEDTEXIMAGE3DARBPROC)context->CompressedTexImage3D; + if (context->CompressedTexSubImage1D == NULL && context->CompressedTexSubImage1DARB != NULL) context->CompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)context->CompressedTexSubImage1DARB; + if (context->CompressedTexSubImage1DARB == NULL && context->CompressedTexSubImage1D != NULL) context->CompressedTexSubImage1DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC)context->CompressedTexSubImage1D; + if (context->CompressedTexSubImage2D == NULL && context->CompressedTexSubImage2DARB != NULL) context->CompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)context->CompressedTexSubImage2DARB; + if (context->CompressedTexSubImage2DARB == NULL && context->CompressedTexSubImage2D != NULL) context->CompressedTexSubImage2DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC)context->CompressedTexSubImage2D; + if (context->CompressedTexSubImage3D == NULL && context->CompressedTexSubImage3DARB != NULL) context->CompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)context->CompressedTexSubImage3DARB; + if (context->CompressedTexSubImage3DARB == NULL && context->CompressedTexSubImage3D != NULL) context->CompressedTexSubImage3DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC)context->CompressedTexSubImage3D; + if (context->CopyTexImage1D == NULL && context->CopyTexImage1DEXT != NULL) context->CopyTexImage1D = (PFNGLCOPYTEXIMAGE1DPROC)context->CopyTexImage1DEXT; + if (context->CopyTexImage1DEXT == NULL && context->CopyTexImage1D != NULL) context->CopyTexImage1DEXT = (PFNGLCOPYTEXIMAGE1DEXTPROC)context->CopyTexImage1D; + if (context->CopyTexImage2D == NULL && context->CopyTexImage2DEXT != NULL) context->CopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC)context->CopyTexImage2DEXT; + if (context->CopyTexImage2DEXT == NULL && context->CopyTexImage2D != NULL) context->CopyTexImage2DEXT = (PFNGLCOPYTEXIMAGE2DEXTPROC)context->CopyTexImage2D; + if (context->CopyTexSubImage1D == NULL && context->CopyTexSubImage1DEXT != NULL) context->CopyTexSubImage1D = (PFNGLCOPYTEXSUBIMAGE1DPROC)context->CopyTexSubImage1DEXT; + if (context->CopyTexSubImage1DEXT == NULL && context->CopyTexSubImage1D != NULL) context->CopyTexSubImage1DEXT = (PFNGLCOPYTEXSUBIMAGE1DEXTPROC)context->CopyTexSubImage1D; + if (context->CopyTexSubImage2D == NULL && context->CopyTexSubImage2DEXT != NULL) context->CopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC)context->CopyTexSubImage2DEXT; + if (context->CopyTexSubImage2DEXT == NULL && context->CopyTexSubImage2D != NULL) context->CopyTexSubImage2DEXT = (PFNGLCOPYTEXSUBIMAGE2DEXTPROC)context->CopyTexSubImage2D; + if (context->CopyTexSubImage3D == NULL && context->CopyTexSubImage3DEXT != NULL) context->CopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC)context->CopyTexSubImage3DEXT; + if (context->CopyTexSubImage3DEXT == NULL && context->CopyTexSubImage3D != NULL) context->CopyTexSubImage3DEXT = (PFNGLCOPYTEXSUBIMAGE3DEXTPROC)context->CopyTexSubImage3D; + if (context->CreateProgram == NULL && context->CreateProgramObjectARB != NULL) context->CreateProgram = (PFNGLCREATEPROGRAMPROC)context->CreateProgramObjectARB; + if (context->CreateProgramObjectARB == NULL && context->CreateProgram != NULL) context->CreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)context->CreateProgram; + if (context->CreateShader == NULL && context->CreateShaderObjectARB != NULL) context->CreateShader = (PFNGLCREATESHADERPROC)context->CreateShaderObjectARB; + if (context->CreateShaderObjectARB == NULL && context->CreateShader != NULL) context->CreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)context->CreateShader; + if (context->DeleteBuffers == NULL && context->DeleteBuffersARB != NULL) context->DeleteBuffers = (PFNGLDELETEBUFFERSPROC)context->DeleteBuffersARB; + if (context->DeleteBuffersARB == NULL && context->DeleteBuffers != NULL) context->DeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)context->DeleteBuffers; + if (context->DeleteFramebuffers == NULL && context->DeleteFramebuffersEXT != NULL) context->DeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)context->DeleteFramebuffersEXT; + if (context->DeleteFramebuffersEXT == NULL && context->DeleteFramebuffers != NULL) context->DeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)context->DeleteFramebuffers; + if (context->DeleteProgramsARB == NULL && context->DeleteProgramsNV != NULL) context->DeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC)context->DeleteProgramsNV; + if (context->DeleteProgramsNV == NULL && context->DeleteProgramsARB != NULL) context->DeleteProgramsNV = (PFNGLDELETEPROGRAMSNVPROC)context->DeleteProgramsARB; + if (context->DeleteQueries == NULL && context->DeleteQueriesARB != NULL) context->DeleteQueries = (PFNGLDELETEQUERIESPROC)context->DeleteQueriesARB; + if (context->DeleteQueriesARB == NULL && context->DeleteQueries != NULL) context->DeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC)context->DeleteQueries; + if (context->DeleteRenderbuffers == NULL && context->DeleteRenderbuffersEXT != NULL) context->DeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)context->DeleteRenderbuffersEXT; + if (context->DeleteRenderbuffersEXT == NULL && context->DeleteRenderbuffers != NULL) context->DeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)context->DeleteRenderbuffers; + if (context->DeleteVertexArrays == NULL && context->DeleteVertexArraysAPPLE != NULL) context->DeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)context->DeleteVertexArraysAPPLE; + if (context->DeleteVertexArraysAPPLE == NULL && context->DeleteVertexArrays != NULL) context->DeleteVertexArraysAPPLE = (PFNGLDELETEVERTEXARRAYSAPPLEPROC)context->DeleteVertexArrays; + if (context->DetachObjectARB == NULL && context->DetachShader != NULL) context->DetachObjectARB = (PFNGLDETACHOBJECTARBPROC)context->DetachShader; + if (context->DetachShader == NULL && context->DetachObjectARB != NULL) context->DetachShader = (PFNGLDETACHSHADERPROC)context->DetachObjectARB; + if (context->Disablei == NULL && context->DisableIndexedEXT != NULL) context->Disablei = (PFNGLDISABLEIPROC)context->DisableIndexedEXT; + if (context->DisableIndexedEXT == NULL && context->Disablei != NULL) context->DisableIndexedEXT = (PFNGLDISABLEINDEXEDEXTPROC)context->Disablei; + if (context->DisableVertexAttribArray == NULL && context->DisableVertexAttribArrayARB != NULL) context->DisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)context->DisableVertexAttribArrayARB; + if (context->DisableVertexAttribArrayARB == NULL && context->DisableVertexAttribArray != NULL) context->DisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC)context->DisableVertexAttribArray; + if (context->DrawArrays == NULL && context->DrawArraysEXT != NULL) context->DrawArrays = (PFNGLDRAWARRAYSPROC)context->DrawArraysEXT; + if (context->DrawArraysEXT == NULL && context->DrawArrays != NULL) context->DrawArraysEXT = (PFNGLDRAWARRAYSEXTPROC)context->DrawArrays; + if (context->DrawArraysInstanced == NULL && context->DrawArraysInstancedARB != NULL) context->DrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC)context->DrawArraysInstancedARB; + if (context->DrawArraysInstanced == NULL && context->DrawArraysInstancedEXT != NULL) context->DrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC)context->DrawArraysInstancedEXT; + if (context->DrawArraysInstancedARB == NULL && context->DrawArraysInstanced != NULL) context->DrawArraysInstancedARB = (PFNGLDRAWARRAYSINSTANCEDARBPROC)context->DrawArraysInstanced; + if (context->DrawArraysInstancedARB == NULL && context->DrawArraysInstancedEXT != NULL) context->DrawArraysInstancedARB = (PFNGLDRAWARRAYSINSTANCEDARBPROC)context->DrawArraysInstancedEXT; + if (context->DrawArraysInstancedEXT == NULL && context->DrawArraysInstanced != NULL) context->DrawArraysInstancedEXT = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)context->DrawArraysInstanced; + if (context->DrawArraysInstancedEXT == NULL && context->DrawArraysInstancedARB != NULL) context->DrawArraysInstancedEXT = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)context->DrawArraysInstancedARB; + if (context->DrawBuffers == NULL && context->DrawBuffersARB != NULL) context->DrawBuffers = (PFNGLDRAWBUFFERSPROC)context->DrawBuffersARB; + if (context->DrawBuffers == NULL && context->DrawBuffersATI != NULL) context->DrawBuffers = (PFNGLDRAWBUFFERSPROC)context->DrawBuffersATI; + if (context->DrawBuffersARB == NULL && context->DrawBuffers != NULL) context->DrawBuffersARB = (PFNGLDRAWBUFFERSARBPROC)context->DrawBuffers; + if (context->DrawBuffersARB == NULL && context->DrawBuffersATI != NULL) context->DrawBuffersARB = (PFNGLDRAWBUFFERSARBPROC)context->DrawBuffersATI; + if (context->DrawBuffersATI == NULL && context->DrawBuffers != NULL) context->DrawBuffersATI = (PFNGLDRAWBUFFERSATIPROC)context->DrawBuffers; + if (context->DrawBuffersATI == NULL && context->DrawBuffersARB != NULL) context->DrawBuffersATI = (PFNGLDRAWBUFFERSATIPROC)context->DrawBuffersARB; + if (context->DrawElementsInstanced == NULL && context->DrawElementsInstancedARB != NULL) context->DrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC)context->DrawElementsInstancedARB; + if (context->DrawElementsInstanced == NULL && context->DrawElementsInstancedEXT != NULL) context->DrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC)context->DrawElementsInstancedEXT; + if (context->DrawElementsInstancedARB == NULL && context->DrawElementsInstanced != NULL) context->DrawElementsInstancedARB = (PFNGLDRAWELEMENTSINSTANCEDARBPROC)context->DrawElementsInstanced; + if (context->DrawElementsInstancedARB == NULL && context->DrawElementsInstancedEXT != NULL) context->DrawElementsInstancedARB = (PFNGLDRAWELEMENTSINSTANCEDARBPROC)context->DrawElementsInstancedEXT; + if (context->DrawElementsInstancedEXT == NULL && context->DrawElementsInstanced != NULL) context->DrawElementsInstancedEXT = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)context->DrawElementsInstanced; + if (context->DrawElementsInstancedEXT == NULL && context->DrawElementsInstancedARB != NULL) context->DrawElementsInstancedEXT = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)context->DrawElementsInstancedARB; + if (context->DrawRangeElements == NULL && context->DrawRangeElementsEXT != NULL) context->DrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)context->DrawRangeElementsEXT; + if (context->DrawRangeElementsEXT == NULL && context->DrawRangeElements != NULL) context->DrawRangeElementsEXT = (PFNGLDRAWRANGEELEMENTSEXTPROC)context->DrawRangeElements; + if (context->Enablei == NULL && context->EnableIndexedEXT != NULL) context->Enablei = (PFNGLENABLEIPROC)context->EnableIndexedEXT; + if (context->EnableIndexedEXT == NULL && context->Enablei != NULL) context->EnableIndexedEXT = (PFNGLENABLEINDEXEDEXTPROC)context->Enablei; + if (context->EnableVertexAttribArray == NULL && context->EnableVertexAttribArrayARB != NULL) context->EnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)context->EnableVertexAttribArrayARB; + if (context->EnableVertexAttribArrayARB == NULL && context->EnableVertexAttribArray != NULL) context->EnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC)context->EnableVertexAttribArray; + if (context->EndConditionalRender == NULL && context->EndConditionalRenderNV != NULL) context->EndConditionalRender = (PFNGLENDCONDITIONALRENDERPROC)context->EndConditionalRenderNV; + if (context->EndConditionalRender == NULL && context->EndConditionalRenderNVX != NULL) context->EndConditionalRender = (PFNGLENDCONDITIONALRENDERPROC)context->EndConditionalRenderNVX; + if (context->EndConditionalRenderNV == NULL && context->EndConditionalRender != NULL) context->EndConditionalRenderNV = (PFNGLENDCONDITIONALRENDERNVPROC)context->EndConditionalRender; + if (context->EndConditionalRenderNV == NULL && context->EndConditionalRenderNVX != NULL) context->EndConditionalRenderNV = (PFNGLENDCONDITIONALRENDERNVPROC)context->EndConditionalRenderNVX; + if (context->EndConditionalRenderNVX == NULL && context->EndConditionalRender != NULL) context->EndConditionalRenderNVX = (PFNGLENDCONDITIONALRENDERNVXPROC)context->EndConditionalRender; + if (context->EndConditionalRenderNVX == NULL && context->EndConditionalRenderNV != NULL) context->EndConditionalRenderNVX = (PFNGLENDCONDITIONALRENDERNVXPROC)context->EndConditionalRenderNV; + if (context->EndQuery == NULL && context->EndQueryARB != NULL) context->EndQuery = (PFNGLENDQUERYPROC)context->EndQueryARB; + if (context->EndQueryARB == NULL && context->EndQuery != NULL) context->EndQueryARB = (PFNGLENDQUERYARBPROC)context->EndQuery; + if (context->EndTransformFeedback == NULL && context->EndTransformFeedbackEXT != NULL) context->EndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC)context->EndTransformFeedbackEXT; + if (context->EndTransformFeedback == NULL && context->EndTransformFeedbackNV != NULL) context->EndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC)context->EndTransformFeedbackNV; + if (context->EndTransformFeedbackEXT == NULL && context->EndTransformFeedback != NULL) context->EndTransformFeedbackEXT = (PFNGLENDTRANSFORMFEEDBACKEXTPROC)context->EndTransformFeedback; + if (context->EndTransformFeedbackEXT == NULL && context->EndTransformFeedbackNV != NULL) context->EndTransformFeedbackEXT = (PFNGLENDTRANSFORMFEEDBACKEXTPROC)context->EndTransformFeedbackNV; + if (context->EndTransformFeedbackNV == NULL && context->EndTransformFeedback != NULL) context->EndTransformFeedbackNV = (PFNGLENDTRANSFORMFEEDBACKNVPROC)context->EndTransformFeedback; + if (context->EndTransformFeedbackNV == NULL && context->EndTransformFeedbackEXT != NULL) context->EndTransformFeedbackNV = (PFNGLENDTRANSFORMFEEDBACKNVPROC)context->EndTransformFeedbackEXT; + if (context->FlushMappedBufferRange == NULL && context->FlushMappedBufferRangeAPPLE != NULL) context->FlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC)context->FlushMappedBufferRangeAPPLE; + if (context->FlushMappedBufferRangeAPPLE == NULL && context->FlushMappedBufferRange != NULL) context->FlushMappedBufferRangeAPPLE = (PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC)context->FlushMappedBufferRange; + if (context->FramebufferRenderbuffer == NULL && context->FramebufferRenderbufferEXT != NULL) context->FramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)context->FramebufferRenderbufferEXT; + if (context->FramebufferRenderbufferEXT == NULL && context->FramebufferRenderbuffer != NULL) context->FramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)context->FramebufferRenderbuffer; + if (context->FramebufferTexture == NULL && context->FramebufferTextureARB != NULL) context->FramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC)context->FramebufferTextureARB; + if (context->FramebufferTexture == NULL && context->FramebufferTextureEXT != NULL) context->FramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC)context->FramebufferTextureEXT; + if (context->FramebufferTexture1D == NULL && context->FramebufferTexture1DEXT != NULL) context->FramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)context->FramebufferTexture1DEXT; + if (context->FramebufferTexture1DEXT == NULL && context->FramebufferTexture1D != NULL) context->FramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)context->FramebufferTexture1D; + if (context->FramebufferTexture2D == NULL && context->FramebufferTexture2DEXT != NULL) context->FramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)context->FramebufferTexture2DEXT; + if (context->FramebufferTexture2DEXT == NULL && context->FramebufferTexture2D != NULL) context->FramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)context->FramebufferTexture2D; + if (context->FramebufferTexture3D == NULL && context->FramebufferTexture3DEXT != NULL) context->FramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)context->FramebufferTexture3DEXT; + if (context->FramebufferTexture3DEXT == NULL && context->FramebufferTexture3D != NULL) context->FramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)context->FramebufferTexture3D; + if (context->FramebufferTextureARB == NULL && context->FramebufferTexture != NULL) context->FramebufferTextureARB = (PFNGLFRAMEBUFFERTEXTUREARBPROC)context->FramebufferTexture; + if (context->FramebufferTextureARB == NULL && context->FramebufferTextureEXT != NULL) context->FramebufferTextureARB = (PFNGLFRAMEBUFFERTEXTUREARBPROC)context->FramebufferTextureEXT; + if (context->FramebufferTextureEXT == NULL && context->FramebufferTexture != NULL) context->FramebufferTextureEXT = (PFNGLFRAMEBUFFERTEXTUREEXTPROC)context->FramebufferTexture; + if (context->FramebufferTextureEXT == NULL && context->FramebufferTextureARB != NULL) context->FramebufferTextureEXT = (PFNGLFRAMEBUFFERTEXTUREEXTPROC)context->FramebufferTextureARB; + if (context->FramebufferTextureFaceARB == NULL && context->FramebufferTextureFaceEXT != NULL) context->FramebufferTextureFaceARB = (PFNGLFRAMEBUFFERTEXTUREFACEARBPROC)context->FramebufferTextureFaceEXT; + if (context->FramebufferTextureFaceEXT == NULL && context->FramebufferTextureFaceARB != NULL) context->FramebufferTextureFaceEXT = (PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC)context->FramebufferTextureFaceARB; + if (context->FramebufferTextureLayer == NULL && context->FramebufferTextureLayerARB != NULL) context->FramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)context->FramebufferTextureLayerARB; + if (context->FramebufferTextureLayer == NULL && context->FramebufferTextureLayerEXT != NULL) context->FramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)context->FramebufferTextureLayerEXT; + if (context->FramebufferTextureLayerARB == NULL && context->FramebufferTextureLayer != NULL) context->FramebufferTextureLayerARB = (PFNGLFRAMEBUFFERTEXTURELAYERARBPROC)context->FramebufferTextureLayer; + if (context->FramebufferTextureLayerARB == NULL && context->FramebufferTextureLayerEXT != NULL) context->FramebufferTextureLayerARB = (PFNGLFRAMEBUFFERTEXTURELAYERARBPROC)context->FramebufferTextureLayerEXT; + if (context->FramebufferTextureLayerEXT == NULL && context->FramebufferTextureLayer != NULL) context->FramebufferTextureLayerEXT = (PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC)context->FramebufferTextureLayer; + if (context->FramebufferTextureLayerEXT == NULL && context->FramebufferTextureLayerARB != NULL) context->FramebufferTextureLayerEXT = (PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC)context->FramebufferTextureLayerARB; + if (context->GenBuffers == NULL && context->GenBuffersARB != NULL) context->GenBuffers = (PFNGLGENBUFFERSPROC)context->GenBuffersARB; + if (context->GenBuffersARB == NULL && context->GenBuffers != NULL) context->GenBuffersARB = (PFNGLGENBUFFERSARBPROC)context->GenBuffers; + if (context->GenerateMipmap == NULL && context->GenerateMipmapEXT != NULL) context->GenerateMipmap = (PFNGLGENERATEMIPMAPPROC)context->GenerateMipmapEXT; + if (context->GenerateMipmapEXT == NULL && context->GenerateMipmap != NULL) context->GenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC)context->GenerateMipmap; + if (context->GenFramebuffers == NULL && context->GenFramebuffersEXT != NULL) context->GenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)context->GenFramebuffersEXT; + if (context->GenFramebuffersEXT == NULL && context->GenFramebuffers != NULL) context->GenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)context->GenFramebuffers; + if (context->GenProgramsARB == NULL && context->GenProgramsNV != NULL) context->GenProgramsARB = (PFNGLGENPROGRAMSARBPROC)context->GenProgramsNV; + if (context->GenProgramsNV == NULL && context->GenProgramsARB != NULL) context->GenProgramsNV = (PFNGLGENPROGRAMSNVPROC)context->GenProgramsARB; + if (context->GenQueries == NULL && context->GenQueriesARB != NULL) context->GenQueries = (PFNGLGENQUERIESPROC)context->GenQueriesARB; + if (context->GenQueriesARB == NULL && context->GenQueries != NULL) context->GenQueriesARB = (PFNGLGENQUERIESARBPROC)context->GenQueries; + if (context->GenRenderbuffers == NULL && context->GenRenderbuffersEXT != NULL) context->GenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)context->GenRenderbuffersEXT; + if (context->GenRenderbuffersEXT == NULL && context->GenRenderbuffers != NULL) context->GenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)context->GenRenderbuffers; + if (context->GenVertexArrays == NULL && context->GenVertexArraysAPPLE != NULL) context->GenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)context->GenVertexArraysAPPLE; + if (context->GenVertexArraysAPPLE == NULL && context->GenVertexArrays != NULL) context->GenVertexArraysAPPLE = (PFNGLGENVERTEXARRAYSAPPLEPROC)context->GenVertexArrays; + if (context->GetActiveAttrib == NULL && context->GetActiveAttribARB != NULL) context->GetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC)context->GetActiveAttribARB; + if (context->GetActiveAttribARB == NULL && context->GetActiveAttrib != NULL) context->GetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC)context->GetActiveAttrib; + if (context->GetActiveUniform == NULL && context->GetActiveUniformARB != NULL) context->GetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC)context->GetActiveUniformARB; + if (context->GetActiveUniformARB == NULL && context->GetActiveUniform != NULL) context->GetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC)context->GetActiveUniform; + if (context->GetAttribLocation == NULL && context->GetAttribLocationARB != NULL) context->GetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)context->GetAttribLocationARB; + if (context->GetAttribLocationARB == NULL && context->GetAttribLocation != NULL) context->GetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC)context->GetAttribLocation; + if (context->GetBooleani_v == NULL && context->GetBooleanIndexedvEXT != NULL) context->GetBooleani_v = (PFNGLGETBOOLEANI_VPROC)context->GetBooleanIndexedvEXT; + if (context->GetBooleanIndexedvEXT == NULL && context->GetBooleani_v != NULL) context->GetBooleanIndexedvEXT = (PFNGLGETBOOLEANINDEXEDVEXTPROC)context->GetBooleani_v; + if (context->GetBufferParameteriv == NULL && context->GetBufferParameterivARB != NULL) context->GetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC)context->GetBufferParameterivARB; + if (context->GetBufferParameterivARB == NULL && context->GetBufferParameteriv != NULL) context->GetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC)context->GetBufferParameteriv; + if (context->GetBufferPointerv == NULL && context->GetBufferPointervARB != NULL) context->GetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC)context->GetBufferPointervARB; + if (context->GetBufferPointervARB == NULL && context->GetBufferPointerv != NULL) context->GetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC)context->GetBufferPointerv; + if (context->GetBufferSubData == NULL && context->GetBufferSubDataARB != NULL) context->GetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC)context->GetBufferSubDataARB; + if (context->GetBufferSubDataARB == NULL && context->GetBufferSubData != NULL) context->GetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC)context->GetBufferSubData; + if (context->GetCompressedTexImage == NULL && context->GetCompressedTexImageARB != NULL) context->GetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC)context->GetCompressedTexImageARB; + if (context->GetCompressedTexImageARB == NULL && context->GetCompressedTexImage != NULL) context->GetCompressedTexImageARB = (PFNGLGETCOMPRESSEDTEXIMAGEARBPROC)context->GetCompressedTexImage; + if (context->GetFragDataLocation == NULL && context->GetFragDataLocationEXT != NULL) context->GetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC)context->GetFragDataLocationEXT; + if (context->GetFragDataLocationEXT == NULL && context->GetFragDataLocation != NULL) context->GetFragDataLocationEXT = (PFNGLGETFRAGDATALOCATIONEXTPROC)context->GetFragDataLocation; + if (context->GetFramebufferAttachmentParameteriv == NULL && context->GetFramebufferAttachmentParameterivEXT != NULL) context->GetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)context->GetFramebufferAttachmentParameterivEXT; + if (context->GetFramebufferAttachmentParameterivEXT == NULL && context->GetFramebufferAttachmentParameteriv != NULL) context->GetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)context->GetFramebufferAttachmentParameteriv; + if (context->GetIntegeri_v == NULL && context->GetIntegerIndexedvEXT != NULL) context->GetIntegeri_v = (PFNGLGETINTEGERI_VPROC)context->GetIntegerIndexedvEXT; + if (context->GetIntegerIndexedvEXT == NULL && context->GetIntegeri_v != NULL) context->GetIntegerIndexedvEXT = (PFNGLGETINTEGERINDEXEDVEXTPROC)context->GetIntegeri_v; + if (context->GetMultisamplefv == NULL && context->GetMultisamplefvNV != NULL) context->GetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC)context->GetMultisamplefvNV; + if (context->GetMultisamplefvNV == NULL && context->GetMultisamplefv != NULL) context->GetMultisamplefvNV = (PFNGLGETMULTISAMPLEFVNVPROC)context->GetMultisamplefv; + if (context->GetQueryiv == NULL && context->GetQueryivARB != NULL) context->GetQueryiv = (PFNGLGETQUERYIVPROC)context->GetQueryivARB; + if (context->GetQueryivARB == NULL && context->GetQueryiv != NULL) context->GetQueryivARB = (PFNGLGETQUERYIVARBPROC)context->GetQueryiv; + if (context->GetQueryObjectiv == NULL && context->GetQueryObjectivARB != NULL) context->GetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC)context->GetQueryObjectivARB; + if (context->GetQueryObjectivARB == NULL && context->GetQueryObjectiv != NULL) context->GetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC)context->GetQueryObjectiv; + if (context->GetQueryObjectuiv == NULL && context->GetQueryObjectuivARB != NULL) context->GetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC)context->GetQueryObjectuivARB; + if (context->GetQueryObjectuivARB == NULL && context->GetQueryObjectuiv != NULL) context->GetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC)context->GetQueryObjectuiv; + if (context->GetRenderbufferParameteriv == NULL && context->GetRenderbufferParameterivEXT != NULL) context->GetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)context->GetRenderbufferParameterivEXT; + if (context->GetRenderbufferParameterivEXT == NULL && context->GetRenderbufferParameteriv != NULL) context->GetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)context->GetRenderbufferParameteriv; + if (context->GetShaderSource == NULL && context->GetShaderSourceARB != NULL) context->GetShaderSource = (PFNGLGETSHADERSOURCEPROC)context->GetShaderSourceARB; + if (context->GetShaderSourceARB == NULL && context->GetShaderSource != NULL) context->GetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC)context->GetShaderSource; + if (context->GetTexParameterIiv == NULL && context->GetTexParameterIivEXT != NULL) context->GetTexParameterIiv = (PFNGLGETTEXPARAMETERIIVPROC)context->GetTexParameterIivEXT; + if (context->GetTexParameterIivEXT == NULL && context->GetTexParameterIiv != NULL) context->GetTexParameterIivEXT = (PFNGLGETTEXPARAMETERIIVEXTPROC)context->GetTexParameterIiv; + if (context->GetTexParameterIuiv == NULL && context->GetTexParameterIuivEXT != NULL) context->GetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIVPROC)context->GetTexParameterIuivEXT; + if (context->GetTexParameterIuivEXT == NULL && context->GetTexParameterIuiv != NULL) context->GetTexParameterIuivEXT = (PFNGLGETTEXPARAMETERIUIVEXTPROC)context->GetTexParameterIuiv; + if (context->GetTransformFeedbackVarying == NULL && context->GetTransformFeedbackVaryingEXT != NULL) context->GetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)context->GetTransformFeedbackVaryingEXT; + if (context->GetTransformFeedbackVaryingEXT == NULL && context->GetTransformFeedbackVarying != NULL) context->GetTransformFeedbackVaryingEXT = (PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC)context->GetTransformFeedbackVarying; + if (context->GetUniformfv == NULL && context->GetUniformfvARB != NULL) context->GetUniformfv = (PFNGLGETUNIFORMFVPROC)context->GetUniformfvARB; + if (context->GetUniformfvARB == NULL && context->GetUniformfv != NULL) context->GetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC)context->GetUniformfv; + if (context->GetUniformiv == NULL && context->GetUniformivARB != NULL) context->GetUniformiv = (PFNGLGETUNIFORMIVPROC)context->GetUniformivARB; + if (context->GetUniformivARB == NULL && context->GetUniformiv != NULL) context->GetUniformivARB = (PFNGLGETUNIFORMIVARBPROC)context->GetUniformiv; + if (context->GetUniformLocation == NULL && context->GetUniformLocationARB != NULL) context->GetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)context->GetUniformLocationARB; + if (context->GetUniformLocationARB == NULL && context->GetUniformLocation != NULL) context->GetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)context->GetUniformLocation; + if (context->GetUniformuiv == NULL && context->GetUniformuivEXT != NULL) context->GetUniformuiv = (PFNGLGETUNIFORMUIVPROC)context->GetUniformuivEXT; + if (context->GetUniformuivEXT == NULL && context->GetUniformuiv != NULL) context->GetUniformuivEXT = (PFNGLGETUNIFORMUIVEXTPROC)context->GetUniformuiv; + if (context->GetVertexAttribdv == NULL && context->GetVertexAttribdvARB != NULL) context->GetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC)context->GetVertexAttribdvARB; + if (context->GetVertexAttribdv == NULL && context->GetVertexAttribdvNV != NULL) context->GetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC)context->GetVertexAttribdvNV; + if (context->GetVertexAttribdvARB == NULL && context->GetVertexAttribdv != NULL) context->GetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC)context->GetVertexAttribdv; + if (context->GetVertexAttribdvARB == NULL && context->GetVertexAttribdvNV != NULL) context->GetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC)context->GetVertexAttribdvNV; + if (context->GetVertexAttribdvNV == NULL && context->GetVertexAttribdv != NULL) context->GetVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC)context->GetVertexAttribdv; + if (context->GetVertexAttribdvNV == NULL && context->GetVertexAttribdvARB != NULL) context->GetVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC)context->GetVertexAttribdvARB; + if (context->GetVertexAttribfv == NULL && context->GetVertexAttribfvARB != NULL) context->GetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC)context->GetVertexAttribfvARB; + if (context->GetVertexAttribfv == NULL && context->GetVertexAttribfvNV != NULL) context->GetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC)context->GetVertexAttribfvNV; + if (context->GetVertexAttribfvARB == NULL && context->GetVertexAttribfv != NULL) context->GetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC)context->GetVertexAttribfv; + if (context->GetVertexAttribfvARB == NULL && context->GetVertexAttribfvNV != NULL) context->GetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC)context->GetVertexAttribfvNV; + if (context->GetVertexAttribfvNV == NULL && context->GetVertexAttribfv != NULL) context->GetVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC)context->GetVertexAttribfv; + if (context->GetVertexAttribfvNV == NULL && context->GetVertexAttribfvARB != NULL) context->GetVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC)context->GetVertexAttribfvARB; + if (context->GetVertexAttribIiv == NULL && context->GetVertexAttribIivEXT != NULL) context->GetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC)context->GetVertexAttribIivEXT; + if (context->GetVertexAttribIivEXT == NULL && context->GetVertexAttribIiv != NULL) context->GetVertexAttribIivEXT = (PFNGLGETVERTEXATTRIBIIVEXTPROC)context->GetVertexAttribIiv; + if (context->GetVertexAttribIuiv == NULL && context->GetVertexAttribIuivEXT != NULL) context->GetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC)context->GetVertexAttribIuivEXT; + if (context->GetVertexAttribIuivEXT == NULL && context->GetVertexAttribIuiv != NULL) context->GetVertexAttribIuivEXT = (PFNGLGETVERTEXATTRIBIUIVEXTPROC)context->GetVertexAttribIuiv; + if (context->GetVertexAttribiv == NULL && context->GetVertexAttribivARB != NULL) context->GetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC)context->GetVertexAttribivARB; + if (context->GetVertexAttribiv == NULL && context->GetVertexAttribivNV != NULL) context->GetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC)context->GetVertexAttribivNV; + if (context->GetVertexAttribivARB == NULL && context->GetVertexAttribiv != NULL) context->GetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC)context->GetVertexAttribiv; + if (context->GetVertexAttribivARB == NULL && context->GetVertexAttribivNV != NULL) context->GetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC)context->GetVertexAttribivNV; + if (context->GetVertexAttribivNV == NULL && context->GetVertexAttribiv != NULL) context->GetVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC)context->GetVertexAttribiv; + if (context->GetVertexAttribivNV == NULL && context->GetVertexAttribivARB != NULL) context->GetVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC)context->GetVertexAttribivARB; + if (context->GetVertexAttribPointerv == NULL && context->GetVertexAttribPointervARB != NULL) context->GetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC)context->GetVertexAttribPointervARB; + if (context->GetVertexAttribPointerv == NULL && context->GetVertexAttribPointervNV != NULL) context->GetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC)context->GetVertexAttribPointervNV; + if (context->GetVertexAttribPointervARB == NULL && context->GetVertexAttribPointerv != NULL) context->GetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC)context->GetVertexAttribPointerv; + if (context->GetVertexAttribPointervARB == NULL && context->GetVertexAttribPointervNV != NULL) context->GetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC)context->GetVertexAttribPointervNV; + if (context->GetVertexAttribPointervNV == NULL && context->GetVertexAttribPointerv != NULL) context->GetVertexAttribPointervNV = (PFNGLGETVERTEXATTRIBPOINTERVNVPROC)context->GetVertexAttribPointerv; + if (context->GetVertexAttribPointervNV == NULL && context->GetVertexAttribPointervARB != NULL) context->GetVertexAttribPointervNV = (PFNGLGETVERTEXATTRIBPOINTERVNVPROC)context->GetVertexAttribPointervARB; + if (context->IsBuffer == NULL && context->IsBufferARB != NULL) context->IsBuffer = (PFNGLISBUFFERPROC)context->IsBufferARB; + if (context->IsBufferARB == NULL && context->IsBuffer != NULL) context->IsBufferARB = (PFNGLISBUFFERARBPROC)context->IsBuffer; + if (context->IsEnabledi == NULL && context->IsEnabledIndexedEXT != NULL) context->IsEnabledi = (PFNGLISENABLEDIPROC)context->IsEnabledIndexedEXT; + if (context->IsEnabledIndexedEXT == NULL && context->IsEnabledi != NULL) context->IsEnabledIndexedEXT = (PFNGLISENABLEDINDEXEDEXTPROC)context->IsEnabledi; + if (context->IsFramebuffer == NULL && context->IsFramebufferEXT != NULL) context->IsFramebuffer = (PFNGLISFRAMEBUFFERPROC)context->IsFramebufferEXT; + if (context->IsFramebufferEXT == NULL && context->IsFramebuffer != NULL) context->IsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC)context->IsFramebuffer; + if (context->IsProgramARB == NULL && context->IsProgramNV != NULL) context->IsProgramARB = (PFNGLISPROGRAMARBPROC)context->IsProgramNV; + if (context->IsProgramNV == NULL && context->IsProgramARB != NULL) context->IsProgramNV = (PFNGLISPROGRAMNVPROC)context->IsProgramARB; + if (context->IsQuery == NULL && context->IsQueryARB != NULL) context->IsQuery = (PFNGLISQUERYPROC)context->IsQueryARB; + if (context->IsQueryARB == NULL && context->IsQuery != NULL) context->IsQueryARB = (PFNGLISQUERYARBPROC)context->IsQuery; + if (context->IsRenderbuffer == NULL && context->IsRenderbufferEXT != NULL) context->IsRenderbuffer = (PFNGLISRENDERBUFFERPROC)context->IsRenderbufferEXT; + if (context->IsRenderbufferEXT == NULL && context->IsRenderbuffer != NULL) context->IsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC)context->IsRenderbuffer; + if (context->IsVertexArray == NULL && context->IsVertexArrayAPPLE != NULL) context->IsVertexArray = (PFNGLISVERTEXARRAYPROC)context->IsVertexArrayAPPLE; + if (context->IsVertexArrayAPPLE == NULL && context->IsVertexArray != NULL) context->IsVertexArrayAPPLE = (PFNGLISVERTEXARRAYAPPLEPROC)context->IsVertexArray; + if (context->LinkProgram == NULL && context->LinkProgramARB != NULL) context->LinkProgram = (PFNGLLINKPROGRAMPROC)context->LinkProgramARB; + if (context->LinkProgramARB == NULL && context->LinkProgram != NULL) context->LinkProgramARB = (PFNGLLINKPROGRAMARBPROC)context->LinkProgram; + if (context->MapBuffer == NULL && context->MapBufferARB != NULL) context->MapBuffer = (PFNGLMAPBUFFERPROC)context->MapBufferARB; + if (context->MapBufferARB == NULL && context->MapBuffer != NULL) context->MapBufferARB = (PFNGLMAPBUFFERARBPROC)context->MapBuffer; + if (context->MultiDrawArrays == NULL && context->MultiDrawArraysEXT != NULL) context->MultiDrawArrays = (PFNGLMULTIDRAWARRAYSPROC)context->MultiDrawArraysEXT; + if (context->MultiDrawArraysEXT == NULL && context->MultiDrawArrays != NULL) context->MultiDrawArraysEXT = (PFNGLMULTIDRAWARRAYSEXTPROC)context->MultiDrawArrays; + if (context->MultiDrawElements == NULL && context->MultiDrawElementsEXT != NULL) context->MultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC)context->MultiDrawElementsEXT; + if (context->MultiDrawElementsEXT == NULL && context->MultiDrawElements != NULL) context->MultiDrawElementsEXT = (PFNGLMULTIDRAWELEMENTSEXTPROC)context->MultiDrawElements; + if (context->PointParameterf == NULL && context->PointParameterfARB != NULL) context->PointParameterf = (PFNGLPOINTPARAMETERFPROC)context->PointParameterfARB; + if (context->PointParameterf == NULL && context->PointParameterfEXT != NULL) context->PointParameterf = (PFNGLPOINTPARAMETERFPROC)context->PointParameterfEXT; + if (context->PointParameterf == NULL && context->PointParameterfSGIS != NULL) context->PointParameterf = (PFNGLPOINTPARAMETERFPROC)context->PointParameterfSGIS; + if (context->PointParameterfARB == NULL && context->PointParameterf != NULL) context->PointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC)context->PointParameterf; + if (context->PointParameterfARB == NULL && context->PointParameterfEXT != NULL) context->PointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC)context->PointParameterfEXT; + if (context->PointParameterfARB == NULL && context->PointParameterfSGIS != NULL) context->PointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC)context->PointParameterfSGIS; + if (context->PointParameterfEXT == NULL && context->PointParameterf != NULL) context->PointParameterfEXT = (PFNGLPOINTPARAMETERFEXTPROC)context->PointParameterf; + if (context->PointParameterfEXT == NULL && context->PointParameterfARB != NULL) context->PointParameterfEXT = (PFNGLPOINTPARAMETERFEXTPROC)context->PointParameterfARB; + if (context->PointParameterfEXT == NULL && context->PointParameterfSGIS != NULL) context->PointParameterfEXT = (PFNGLPOINTPARAMETERFEXTPROC)context->PointParameterfSGIS; + if (context->PointParameterfSGIS == NULL && context->PointParameterf != NULL) context->PointParameterfSGIS = (PFNGLPOINTPARAMETERFSGISPROC)context->PointParameterf; + if (context->PointParameterfSGIS == NULL && context->PointParameterfARB != NULL) context->PointParameterfSGIS = (PFNGLPOINTPARAMETERFSGISPROC)context->PointParameterfARB; + if (context->PointParameterfSGIS == NULL && context->PointParameterfEXT != NULL) context->PointParameterfSGIS = (PFNGLPOINTPARAMETERFSGISPROC)context->PointParameterfEXT; + if (context->PointParameterfv == NULL && context->PointParameterfvARB != NULL) context->PointParameterfv = (PFNGLPOINTPARAMETERFVPROC)context->PointParameterfvARB; + if (context->PointParameterfv == NULL && context->PointParameterfvEXT != NULL) context->PointParameterfv = (PFNGLPOINTPARAMETERFVPROC)context->PointParameterfvEXT; + if (context->PointParameterfv == NULL && context->PointParameterfvSGIS != NULL) context->PointParameterfv = (PFNGLPOINTPARAMETERFVPROC)context->PointParameterfvSGIS; + if (context->PointParameterfvARB == NULL && context->PointParameterfv != NULL) context->PointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC)context->PointParameterfv; + if (context->PointParameterfvARB == NULL && context->PointParameterfvEXT != NULL) context->PointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC)context->PointParameterfvEXT; + if (context->PointParameterfvARB == NULL && context->PointParameterfvSGIS != NULL) context->PointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC)context->PointParameterfvSGIS; + if (context->PointParameterfvEXT == NULL && context->PointParameterfv != NULL) context->PointParameterfvEXT = (PFNGLPOINTPARAMETERFVEXTPROC)context->PointParameterfv; + if (context->PointParameterfvEXT == NULL && context->PointParameterfvARB != NULL) context->PointParameterfvEXT = (PFNGLPOINTPARAMETERFVEXTPROC)context->PointParameterfvARB; + if (context->PointParameterfvEXT == NULL && context->PointParameterfvSGIS != NULL) context->PointParameterfvEXT = (PFNGLPOINTPARAMETERFVEXTPROC)context->PointParameterfvSGIS; + if (context->PointParameterfvSGIS == NULL && context->PointParameterfv != NULL) context->PointParameterfvSGIS = (PFNGLPOINTPARAMETERFVSGISPROC)context->PointParameterfv; + if (context->PointParameterfvSGIS == NULL && context->PointParameterfvARB != NULL) context->PointParameterfvSGIS = (PFNGLPOINTPARAMETERFVSGISPROC)context->PointParameterfvARB; + if (context->PointParameterfvSGIS == NULL && context->PointParameterfvEXT != NULL) context->PointParameterfvSGIS = (PFNGLPOINTPARAMETERFVSGISPROC)context->PointParameterfvEXT; + if (context->PointParameteri == NULL && context->PointParameteriNV != NULL) context->PointParameteri = (PFNGLPOINTPARAMETERIPROC)context->PointParameteriNV; + if (context->PointParameteriNV == NULL && context->PointParameteri != NULL) context->PointParameteriNV = (PFNGLPOINTPARAMETERINVPROC)context->PointParameteri; + if (context->PointParameteriv == NULL && context->PointParameterivNV != NULL) context->PointParameteriv = (PFNGLPOINTPARAMETERIVPROC)context->PointParameterivNV; + if (context->PointParameterivNV == NULL && context->PointParameteriv != NULL) context->PointParameterivNV = (PFNGLPOINTPARAMETERIVNVPROC)context->PointParameteriv; + if (context->ProvokingVertex == NULL && context->ProvokingVertexEXT != NULL) context->ProvokingVertex = (PFNGLPROVOKINGVERTEXPROC)context->ProvokingVertexEXT; + if (context->ProvokingVertexEXT == NULL && context->ProvokingVertex != NULL) context->ProvokingVertexEXT = (PFNGLPROVOKINGVERTEXEXTPROC)context->ProvokingVertex; + if (context->RenderbufferStorage == NULL && context->RenderbufferStorageEXT != NULL) context->RenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)context->RenderbufferStorageEXT; + if (context->RenderbufferStorageEXT == NULL && context->RenderbufferStorage != NULL) context->RenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)context->RenderbufferStorage; + if (context->RenderbufferStorageMultisample == NULL && context->RenderbufferStorageMultisampleEXT != NULL) context->RenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)context->RenderbufferStorageMultisampleEXT; + if (context->RenderbufferStorageMultisampleEXT == NULL && context->RenderbufferStorageMultisample != NULL) context->RenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)context->RenderbufferStorageMultisample; + if (context->SampleCoverage == NULL && context->SampleCoverageARB != NULL) context->SampleCoverage = (PFNGLSAMPLECOVERAGEPROC)context->SampleCoverageARB; + if (context->SampleCoverageARB == NULL && context->SampleCoverage != NULL) context->SampleCoverageARB = (PFNGLSAMPLECOVERAGEARBPROC)context->SampleCoverage; + if (context->ShaderSource == NULL && context->ShaderSourceARB != NULL) context->ShaderSource = (PFNGLSHADERSOURCEPROC)context->ShaderSourceARB; + if (context->ShaderSourceARB == NULL && context->ShaderSource != NULL) context->ShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)context->ShaderSource; + if (context->StencilOpSeparate == NULL && context->StencilOpSeparateATI != NULL) context->StencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)context->StencilOpSeparateATI; + if (context->StencilOpSeparateATI == NULL && context->StencilOpSeparate != NULL) context->StencilOpSeparateATI = (PFNGLSTENCILOPSEPARATEATIPROC)context->StencilOpSeparate; + if (context->TexBuffer == NULL && context->TexBufferARB != NULL) context->TexBuffer = (PFNGLTEXBUFFERPROC)context->TexBufferARB; + if (context->TexBuffer == NULL && context->TexBufferEXT != NULL) context->TexBuffer = (PFNGLTEXBUFFERPROC)context->TexBufferEXT; + if (context->TexBufferARB == NULL && context->TexBuffer != NULL) context->TexBufferARB = (PFNGLTEXBUFFERARBPROC)context->TexBuffer; + if (context->TexBufferARB == NULL && context->TexBufferEXT != NULL) context->TexBufferARB = (PFNGLTEXBUFFERARBPROC)context->TexBufferEXT; + if (context->TexBufferEXT == NULL && context->TexBuffer != NULL) context->TexBufferEXT = (PFNGLTEXBUFFEREXTPROC)context->TexBuffer; + if (context->TexBufferEXT == NULL && context->TexBufferARB != NULL) context->TexBufferEXT = (PFNGLTEXBUFFEREXTPROC)context->TexBufferARB; + if (context->TexImage3D == NULL && context->TexImage3DEXT != NULL) context->TexImage3D = (PFNGLTEXIMAGE3DPROC)context->TexImage3DEXT; + if (context->TexImage3DEXT == NULL && context->TexImage3D != NULL) context->TexImage3DEXT = (PFNGLTEXIMAGE3DEXTPROC)context->TexImage3D; + if (context->TexParameterIiv == NULL && context->TexParameterIivEXT != NULL) context->TexParameterIiv = (PFNGLTEXPARAMETERIIVPROC)context->TexParameterIivEXT; + if (context->TexParameterIivEXT == NULL && context->TexParameterIiv != NULL) context->TexParameterIivEXT = (PFNGLTEXPARAMETERIIVEXTPROC)context->TexParameterIiv; + if (context->TexParameterIuiv == NULL && context->TexParameterIuivEXT != NULL) context->TexParameterIuiv = (PFNGLTEXPARAMETERIUIVPROC)context->TexParameterIuivEXT; + if (context->TexParameterIuivEXT == NULL && context->TexParameterIuiv != NULL) context->TexParameterIuivEXT = (PFNGLTEXPARAMETERIUIVEXTPROC)context->TexParameterIuiv; + if (context->TexSubImage1D == NULL && context->TexSubImage1DEXT != NULL) context->TexSubImage1D = (PFNGLTEXSUBIMAGE1DPROC)context->TexSubImage1DEXT; + if (context->TexSubImage1DEXT == NULL && context->TexSubImage1D != NULL) context->TexSubImage1DEXT = (PFNGLTEXSUBIMAGE1DEXTPROC)context->TexSubImage1D; + if (context->TexSubImage2D == NULL && context->TexSubImage2DEXT != NULL) context->TexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC)context->TexSubImage2DEXT; + if (context->TexSubImage2DEXT == NULL && context->TexSubImage2D != NULL) context->TexSubImage2DEXT = (PFNGLTEXSUBIMAGE2DEXTPROC)context->TexSubImage2D; + if (context->TexSubImage3D == NULL && context->TexSubImage3DEXT != NULL) context->TexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC)context->TexSubImage3DEXT; + if (context->TexSubImage3DEXT == NULL && context->TexSubImage3D != NULL) context->TexSubImage3DEXT = (PFNGLTEXSUBIMAGE3DEXTPROC)context->TexSubImage3D; + if (context->TransformFeedbackVaryings == NULL && context->TransformFeedbackVaryingsEXT != NULL) context->TransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC)context->TransformFeedbackVaryingsEXT; + if (context->TransformFeedbackVaryingsEXT == NULL && context->TransformFeedbackVaryings != NULL) context->TransformFeedbackVaryingsEXT = (PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC)context->TransformFeedbackVaryings; + if (context->Uniform1f == NULL && context->Uniform1fARB != NULL) context->Uniform1f = (PFNGLUNIFORM1FPROC)context->Uniform1fARB; + if (context->Uniform1fARB == NULL && context->Uniform1f != NULL) context->Uniform1fARB = (PFNGLUNIFORM1FARBPROC)context->Uniform1f; + if (context->Uniform1fv == NULL && context->Uniform1fvARB != NULL) context->Uniform1fv = (PFNGLUNIFORM1FVPROC)context->Uniform1fvARB; + if (context->Uniform1fvARB == NULL && context->Uniform1fv != NULL) context->Uniform1fvARB = (PFNGLUNIFORM1FVARBPROC)context->Uniform1fv; + if (context->Uniform1i == NULL && context->Uniform1iARB != NULL) context->Uniform1i = (PFNGLUNIFORM1IPROC)context->Uniform1iARB; + if (context->Uniform1iARB == NULL && context->Uniform1i != NULL) context->Uniform1iARB = (PFNGLUNIFORM1IARBPROC)context->Uniform1i; + if (context->Uniform1iv == NULL && context->Uniform1ivARB != NULL) context->Uniform1iv = (PFNGLUNIFORM1IVPROC)context->Uniform1ivARB; + if (context->Uniform1ivARB == NULL && context->Uniform1iv != NULL) context->Uniform1ivARB = (PFNGLUNIFORM1IVARBPROC)context->Uniform1iv; + if (context->Uniform1ui == NULL && context->Uniform1uiEXT != NULL) context->Uniform1ui = (PFNGLUNIFORM1UIPROC)context->Uniform1uiEXT; + if (context->Uniform1uiEXT == NULL && context->Uniform1ui != NULL) context->Uniform1uiEXT = (PFNGLUNIFORM1UIEXTPROC)context->Uniform1ui; + if (context->Uniform1uiv == NULL && context->Uniform1uivEXT != NULL) context->Uniform1uiv = (PFNGLUNIFORM1UIVPROC)context->Uniform1uivEXT; + if (context->Uniform1uivEXT == NULL && context->Uniform1uiv != NULL) context->Uniform1uivEXT = (PFNGLUNIFORM1UIVEXTPROC)context->Uniform1uiv; + if (context->Uniform2f == NULL && context->Uniform2fARB != NULL) context->Uniform2f = (PFNGLUNIFORM2FPROC)context->Uniform2fARB; + if (context->Uniform2fARB == NULL && context->Uniform2f != NULL) context->Uniform2fARB = (PFNGLUNIFORM2FARBPROC)context->Uniform2f; + if (context->Uniform2fv == NULL && context->Uniform2fvARB != NULL) context->Uniform2fv = (PFNGLUNIFORM2FVPROC)context->Uniform2fvARB; + if (context->Uniform2fvARB == NULL && context->Uniform2fv != NULL) context->Uniform2fvARB = (PFNGLUNIFORM2FVARBPROC)context->Uniform2fv; + if (context->Uniform2i == NULL && context->Uniform2iARB != NULL) context->Uniform2i = (PFNGLUNIFORM2IPROC)context->Uniform2iARB; + if (context->Uniform2iARB == NULL && context->Uniform2i != NULL) context->Uniform2iARB = (PFNGLUNIFORM2IARBPROC)context->Uniform2i; + if (context->Uniform2iv == NULL && context->Uniform2ivARB != NULL) context->Uniform2iv = (PFNGLUNIFORM2IVPROC)context->Uniform2ivARB; + if (context->Uniform2ivARB == NULL && context->Uniform2iv != NULL) context->Uniform2ivARB = (PFNGLUNIFORM2IVARBPROC)context->Uniform2iv; + if (context->Uniform2ui == NULL && context->Uniform2uiEXT != NULL) context->Uniform2ui = (PFNGLUNIFORM2UIPROC)context->Uniform2uiEXT; + if (context->Uniform2uiEXT == NULL && context->Uniform2ui != NULL) context->Uniform2uiEXT = (PFNGLUNIFORM2UIEXTPROC)context->Uniform2ui; + if (context->Uniform2uiv == NULL && context->Uniform2uivEXT != NULL) context->Uniform2uiv = (PFNGLUNIFORM2UIVPROC)context->Uniform2uivEXT; + if (context->Uniform2uivEXT == NULL && context->Uniform2uiv != NULL) context->Uniform2uivEXT = (PFNGLUNIFORM2UIVEXTPROC)context->Uniform2uiv; + if (context->Uniform3f == NULL && context->Uniform3fARB != NULL) context->Uniform3f = (PFNGLUNIFORM3FPROC)context->Uniform3fARB; + if (context->Uniform3fARB == NULL && context->Uniform3f != NULL) context->Uniform3fARB = (PFNGLUNIFORM3FARBPROC)context->Uniform3f; + if (context->Uniform3fv == NULL && context->Uniform3fvARB != NULL) context->Uniform3fv = (PFNGLUNIFORM3FVPROC)context->Uniform3fvARB; + if (context->Uniform3fvARB == NULL && context->Uniform3fv != NULL) context->Uniform3fvARB = (PFNGLUNIFORM3FVARBPROC)context->Uniform3fv; + if (context->Uniform3i == NULL && context->Uniform3iARB != NULL) context->Uniform3i = (PFNGLUNIFORM3IPROC)context->Uniform3iARB; + if (context->Uniform3iARB == NULL && context->Uniform3i != NULL) context->Uniform3iARB = (PFNGLUNIFORM3IARBPROC)context->Uniform3i; + if (context->Uniform3iv == NULL && context->Uniform3ivARB != NULL) context->Uniform3iv = (PFNGLUNIFORM3IVPROC)context->Uniform3ivARB; + if (context->Uniform3ivARB == NULL && context->Uniform3iv != NULL) context->Uniform3ivARB = (PFNGLUNIFORM3IVARBPROC)context->Uniform3iv; + if (context->Uniform3ui == NULL && context->Uniform3uiEXT != NULL) context->Uniform3ui = (PFNGLUNIFORM3UIPROC)context->Uniform3uiEXT; + if (context->Uniform3uiEXT == NULL && context->Uniform3ui != NULL) context->Uniform3uiEXT = (PFNGLUNIFORM3UIEXTPROC)context->Uniform3ui; + if (context->Uniform3uiv == NULL && context->Uniform3uivEXT != NULL) context->Uniform3uiv = (PFNGLUNIFORM3UIVPROC)context->Uniform3uivEXT; + if (context->Uniform3uivEXT == NULL && context->Uniform3uiv != NULL) context->Uniform3uivEXT = (PFNGLUNIFORM3UIVEXTPROC)context->Uniform3uiv; + if (context->Uniform4f == NULL && context->Uniform4fARB != NULL) context->Uniform4f = (PFNGLUNIFORM4FPROC)context->Uniform4fARB; + if (context->Uniform4fARB == NULL && context->Uniform4f != NULL) context->Uniform4fARB = (PFNGLUNIFORM4FARBPROC)context->Uniform4f; + if (context->Uniform4fv == NULL && context->Uniform4fvARB != NULL) context->Uniform4fv = (PFNGLUNIFORM4FVPROC)context->Uniform4fvARB; + if (context->Uniform4fvARB == NULL && context->Uniform4fv != NULL) context->Uniform4fvARB = (PFNGLUNIFORM4FVARBPROC)context->Uniform4fv; + if (context->Uniform4i == NULL && context->Uniform4iARB != NULL) context->Uniform4i = (PFNGLUNIFORM4IPROC)context->Uniform4iARB; + if (context->Uniform4iARB == NULL && context->Uniform4i != NULL) context->Uniform4iARB = (PFNGLUNIFORM4IARBPROC)context->Uniform4i; + if (context->Uniform4iv == NULL && context->Uniform4ivARB != NULL) context->Uniform4iv = (PFNGLUNIFORM4IVPROC)context->Uniform4ivARB; + if (context->Uniform4ivARB == NULL && context->Uniform4iv != NULL) context->Uniform4ivARB = (PFNGLUNIFORM4IVARBPROC)context->Uniform4iv; + if (context->Uniform4ui == NULL && context->Uniform4uiEXT != NULL) context->Uniform4ui = (PFNGLUNIFORM4UIPROC)context->Uniform4uiEXT; + if (context->Uniform4uiEXT == NULL && context->Uniform4ui != NULL) context->Uniform4uiEXT = (PFNGLUNIFORM4UIEXTPROC)context->Uniform4ui; + if (context->Uniform4uiv == NULL && context->Uniform4uivEXT != NULL) context->Uniform4uiv = (PFNGLUNIFORM4UIVPROC)context->Uniform4uivEXT; + if (context->Uniform4uivEXT == NULL && context->Uniform4uiv != NULL) context->Uniform4uivEXT = (PFNGLUNIFORM4UIVEXTPROC)context->Uniform4uiv; + if (context->UniformMatrix2fv == NULL && context->UniformMatrix2fvARB != NULL) context->UniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC)context->UniformMatrix2fvARB; + if (context->UniformMatrix2fvARB == NULL && context->UniformMatrix2fv != NULL) context->UniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC)context->UniformMatrix2fv; + if (context->UniformMatrix3fv == NULL && context->UniformMatrix3fvARB != NULL) context->UniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC)context->UniformMatrix3fvARB; + if (context->UniformMatrix3fvARB == NULL && context->UniformMatrix3fv != NULL) context->UniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC)context->UniformMatrix3fv; + if (context->UniformMatrix4fv == NULL && context->UniformMatrix4fvARB != NULL) context->UniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)context->UniformMatrix4fvARB; + if (context->UniformMatrix4fvARB == NULL && context->UniformMatrix4fv != NULL) context->UniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC)context->UniformMatrix4fv; + if (context->UnmapBuffer == NULL && context->UnmapBufferARB != NULL) context->UnmapBuffer = (PFNGLUNMAPBUFFERPROC)context->UnmapBufferARB; + if (context->UnmapBufferARB == NULL && context->UnmapBuffer != NULL) context->UnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)context->UnmapBuffer; + if (context->UseProgram == NULL && context->UseProgramObjectARB != NULL) context->UseProgram = (PFNGLUSEPROGRAMPROC)context->UseProgramObjectARB; + if (context->UseProgramObjectARB == NULL && context->UseProgram != NULL) context->UseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)context->UseProgram; + if (context->ValidateProgram == NULL && context->ValidateProgramARB != NULL) context->ValidateProgram = (PFNGLVALIDATEPROGRAMPROC)context->ValidateProgramARB; + if (context->ValidateProgramARB == NULL && context->ValidateProgram != NULL) context->ValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC)context->ValidateProgram; + if (context->VertexAttrib1d == NULL && context->VertexAttrib1dARB != NULL) context->VertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC)context->VertexAttrib1dARB; + if (context->VertexAttrib1d == NULL && context->VertexAttrib1dNV != NULL) context->VertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC)context->VertexAttrib1dNV; + if (context->VertexAttrib1dARB == NULL && context->VertexAttrib1d != NULL) context->VertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC)context->VertexAttrib1d; + if (context->VertexAttrib1dARB == NULL && context->VertexAttrib1dNV != NULL) context->VertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC)context->VertexAttrib1dNV; + if (context->VertexAttrib1dNV == NULL && context->VertexAttrib1d != NULL) context->VertexAttrib1dNV = (PFNGLVERTEXATTRIB1DNVPROC)context->VertexAttrib1d; + if (context->VertexAttrib1dNV == NULL && context->VertexAttrib1dARB != NULL) context->VertexAttrib1dNV = (PFNGLVERTEXATTRIB1DNVPROC)context->VertexAttrib1dARB; + if (context->VertexAttrib1dv == NULL && context->VertexAttrib1dvARB != NULL) context->VertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC)context->VertexAttrib1dvARB; + if (context->VertexAttrib1dv == NULL && context->VertexAttrib1dvNV != NULL) context->VertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC)context->VertexAttrib1dvNV; + if (context->VertexAttrib1dvARB == NULL && context->VertexAttrib1dv != NULL) context->VertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC)context->VertexAttrib1dv; + if (context->VertexAttrib1dvARB == NULL && context->VertexAttrib1dvNV != NULL) context->VertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC)context->VertexAttrib1dvNV; + if (context->VertexAttrib1dvNV == NULL && context->VertexAttrib1dv != NULL) context->VertexAttrib1dvNV = (PFNGLVERTEXATTRIB1DVNVPROC)context->VertexAttrib1dv; + if (context->VertexAttrib1dvNV == NULL && context->VertexAttrib1dvARB != NULL) context->VertexAttrib1dvNV = (PFNGLVERTEXATTRIB1DVNVPROC)context->VertexAttrib1dvARB; + if (context->VertexAttrib1f == NULL && context->VertexAttrib1fARB != NULL) context->VertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC)context->VertexAttrib1fARB; + if (context->VertexAttrib1f == NULL && context->VertexAttrib1fNV != NULL) context->VertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC)context->VertexAttrib1fNV; + if (context->VertexAttrib1fARB == NULL && context->VertexAttrib1f != NULL) context->VertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC)context->VertexAttrib1f; + if (context->VertexAttrib1fARB == NULL && context->VertexAttrib1fNV != NULL) context->VertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC)context->VertexAttrib1fNV; + if (context->VertexAttrib1fNV == NULL && context->VertexAttrib1f != NULL) context->VertexAttrib1fNV = (PFNGLVERTEXATTRIB1FNVPROC)context->VertexAttrib1f; + if (context->VertexAttrib1fNV == NULL && context->VertexAttrib1fARB != NULL) context->VertexAttrib1fNV = (PFNGLVERTEXATTRIB1FNVPROC)context->VertexAttrib1fARB; + if (context->VertexAttrib1fv == NULL && context->VertexAttrib1fvARB != NULL) context->VertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC)context->VertexAttrib1fvARB; + if (context->VertexAttrib1fv == NULL && context->VertexAttrib1fvNV != NULL) context->VertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC)context->VertexAttrib1fvNV; + if (context->VertexAttrib1fvARB == NULL && context->VertexAttrib1fv != NULL) context->VertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC)context->VertexAttrib1fv; + if (context->VertexAttrib1fvARB == NULL && context->VertexAttrib1fvNV != NULL) context->VertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC)context->VertexAttrib1fvNV; + if (context->VertexAttrib1fvNV == NULL && context->VertexAttrib1fv != NULL) context->VertexAttrib1fvNV = (PFNGLVERTEXATTRIB1FVNVPROC)context->VertexAttrib1fv; + if (context->VertexAttrib1fvNV == NULL && context->VertexAttrib1fvARB != NULL) context->VertexAttrib1fvNV = (PFNGLVERTEXATTRIB1FVNVPROC)context->VertexAttrib1fvARB; + if (context->VertexAttrib1s == NULL && context->VertexAttrib1sARB != NULL) context->VertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC)context->VertexAttrib1sARB; + if (context->VertexAttrib1s == NULL && context->VertexAttrib1sNV != NULL) context->VertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC)context->VertexAttrib1sNV; + if (context->VertexAttrib1sARB == NULL && context->VertexAttrib1s != NULL) context->VertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC)context->VertexAttrib1s; + if (context->VertexAttrib1sARB == NULL && context->VertexAttrib1sNV != NULL) context->VertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC)context->VertexAttrib1sNV; + if (context->VertexAttrib1sNV == NULL && context->VertexAttrib1s != NULL) context->VertexAttrib1sNV = (PFNGLVERTEXATTRIB1SNVPROC)context->VertexAttrib1s; + if (context->VertexAttrib1sNV == NULL && context->VertexAttrib1sARB != NULL) context->VertexAttrib1sNV = (PFNGLVERTEXATTRIB1SNVPROC)context->VertexAttrib1sARB; + if (context->VertexAttrib1sv == NULL && context->VertexAttrib1svARB != NULL) context->VertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC)context->VertexAttrib1svARB; + if (context->VertexAttrib1sv == NULL && context->VertexAttrib1svNV != NULL) context->VertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC)context->VertexAttrib1svNV; + if (context->VertexAttrib1svARB == NULL && context->VertexAttrib1sv != NULL) context->VertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC)context->VertexAttrib1sv; + if (context->VertexAttrib1svARB == NULL && context->VertexAttrib1svNV != NULL) context->VertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC)context->VertexAttrib1svNV; + if (context->VertexAttrib1svNV == NULL && context->VertexAttrib1sv != NULL) context->VertexAttrib1svNV = (PFNGLVERTEXATTRIB1SVNVPROC)context->VertexAttrib1sv; + if (context->VertexAttrib1svNV == NULL && context->VertexAttrib1svARB != NULL) context->VertexAttrib1svNV = (PFNGLVERTEXATTRIB1SVNVPROC)context->VertexAttrib1svARB; + if (context->VertexAttrib2d == NULL && context->VertexAttrib2dARB != NULL) context->VertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC)context->VertexAttrib2dARB; + if (context->VertexAttrib2d == NULL && context->VertexAttrib2dNV != NULL) context->VertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC)context->VertexAttrib2dNV; + if (context->VertexAttrib2dARB == NULL && context->VertexAttrib2d != NULL) context->VertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC)context->VertexAttrib2d; + if (context->VertexAttrib2dARB == NULL && context->VertexAttrib2dNV != NULL) context->VertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC)context->VertexAttrib2dNV; + if (context->VertexAttrib2dNV == NULL && context->VertexAttrib2d != NULL) context->VertexAttrib2dNV = (PFNGLVERTEXATTRIB2DNVPROC)context->VertexAttrib2d; + if (context->VertexAttrib2dNV == NULL && context->VertexAttrib2dARB != NULL) context->VertexAttrib2dNV = (PFNGLVERTEXATTRIB2DNVPROC)context->VertexAttrib2dARB; + if (context->VertexAttrib2dv == NULL && context->VertexAttrib2dvARB != NULL) context->VertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC)context->VertexAttrib2dvARB; + if (context->VertexAttrib2dv == NULL && context->VertexAttrib2dvNV != NULL) context->VertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC)context->VertexAttrib2dvNV; + if (context->VertexAttrib2dvARB == NULL && context->VertexAttrib2dv != NULL) context->VertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC)context->VertexAttrib2dv; + if (context->VertexAttrib2dvARB == NULL && context->VertexAttrib2dvNV != NULL) context->VertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC)context->VertexAttrib2dvNV; + if (context->VertexAttrib2dvNV == NULL && context->VertexAttrib2dv != NULL) context->VertexAttrib2dvNV = (PFNGLVERTEXATTRIB2DVNVPROC)context->VertexAttrib2dv; + if (context->VertexAttrib2dvNV == NULL && context->VertexAttrib2dvARB != NULL) context->VertexAttrib2dvNV = (PFNGLVERTEXATTRIB2DVNVPROC)context->VertexAttrib2dvARB; + if (context->VertexAttrib2f == NULL && context->VertexAttrib2fARB != NULL) context->VertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC)context->VertexAttrib2fARB; + if (context->VertexAttrib2f == NULL && context->VertexAttrib2fNV != NULL) context->VertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC)context->VertexAttrib2fNV; + if (context->VertexAttrib2fARB == NULL && context->VertexAttrib2f != NULL) context->VertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC)context->VertexAttrib2f; + if (context->VertexAttrib2fARB == NULL && context->VertexAttrib2fNV != NULL) context->VertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC)context->VertexAttrib2fNV; + if (context->VertexAttrib2fNV == NULL && context->VertexAttrib2f != NULL) context->VertexAttrib2fNV = (PFNGLVERTEXATTRIB2FNVPROC)context->VertexAttrib2f; + if (context->VertexAttrib2fNV == NULL && context->VertexAttrib2fARB != NULL) context->VertexAttrib2fNV = (PFNGLVERTEXATTRIB2FNVPROC)context->VertexAttrib2fARB; + if (context->VertexAttrib2fv == NULL && context->VertexAttrib2fvARB != NULL) context->VertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC)context->VertexAttrib2fvARB; + if (context->VertexAttrib2fv == NULL && context->VertexAttrib2fvNV != NULL) context->VertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC)context->VertexAttrib2fvNV; + if (context->VertexAttrib2fvARB == NULL && context->VertexAttrib2fv != NULL) context->VertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC)context->VertexAttrib2fv; + if (context->VertexAttrib2fvARB == NULL && context->VertexAttrib2fvNV != NULL) context->VertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC)context->VertexAttrib2fvNV; + if (context->VertexAttrib2fvNV == NULL && context->VertexAttrib2fv != NULL) context->VertexAttrib2fvNV = (PFNGLVERTEXATTRIB2FVNVPROC)context->VertexAttrib2fv; + if (context->VertexAttrib2fvNV == NULL && context->VertexAttrib2fvARB != NULL) context->VertexAttrib2fvNV = (PFNGLVERTEXATTRIB2FVNVPROC)context->VertexAttrib2fvARB; + if (context->VertexAttrib2s == NULL && context->VertexAttrib2sARB != NULL) context->VertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC)context->VertexAttrib2sARB; + if (context->VertexAttrib2s == NULL && context->VertexAttrib2sNV != NULL) context->VertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC)context->VertexAttrib2sNV; + if (context->VertexAttrib2sARB == NULL && context->VertexAttrib2s != NULL) context->VertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC)context->VertexAttrib2s; + if (context->VertexAttrib2sARB == NULL && context->VertexAttrib2sNV != NULL) context->VertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC)context->VertexAttrib2sNV; + if (context->VertexAttrib2sNV == NULL && context->VertexAttrib2s != NULL) context->VertexAttrib2sNV = (PFNGLVERTEXATTRIB2SNVPROC)context->VertexAttrib2s; + if (context->VertexAttrib2sNV == NULL && context->VertexAttrib2sARB != NULL) context->VertexAttrib2sNV = (PFNGLVERTEXATTRIB2SNVPROC)context->VertexAttrib2sARB; + if (context->VertexAttrib2sv == NULL && context->VertexAttrib2svARB != NULL) context->VertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC)context->VertexAttrib2svARB; + if (context->VertexAttrib2sv == NULL && context->VertexAttrib2svNV != NULL) context->VertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC)context->VertexAttrib2svNV; + if (context->VertexAttrib2svARB == NULL && context->VertexAttrib2sv != NULL) context->VertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC)context->VertexAttrib2sv; + if (context->VertexAttrib2svARB == NULL && context->VertexAttrib2svNV != NULL) context->VertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC)context->VertexAttrib2svNV; + if (context->VertexAttrib2svNV == NULL && context->VertexAttrib2sv != NULL) context->VertexAttrib2svNV = (PFNGLVERTEXATTRIB2SVNVPROC)context->VertexAttrib2sv; + if (context->VertexAttrib2svNV == NULL && context->VertexAttrib2svARB != NULL) context->VertexAttrib2svNV = (PFNGLVERTEXATTRIB2SVNVPROC)context->VertexAttrib2svARB; + if (context->VertexAttrib3d == NULL && context->VertexAttrib3dARB != NULL) context->VertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC)context->VertexAttrib3dARB; + if (context->VertexAttrib3d == NULL && context->VertexAttrib3dNV != NULL) context->VertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC)context->VertexAttrib3dNV; + if (context->VertexAttrib3dARB == NULL && context->VertexAttrib3d != NULL) context->VertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC)context->VertexAttrib3d; + if (context->VertexAttrib3dARB == NULL && context->VertexAttrib3dNV != NULL) context->VertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC)context->VertexAttrib3dNV; + if (context->VertexAttrib3dNV == NULL && context->VertexAttrib3d != NULL) context->VertexAttrib3dNV = (PFNGLVERTEXATTRIB3DNVPROC)context->VertexAttrib3d; + if (context->VertexAttrib3dNV == NULL && context->VertexAttrib3dARB != NULL) context->VertexAttrib3dNV = (PFNGLVERTEXATTRIB3DNVPROC)context->VertexAttrib3dARB; + if (context->VertexAttrib3dv == NULL && context->VertexAttrib3dvARB != NULL) context->VertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC)context->VertexAttrib3dvARB; + if (context->VertexAttrib3dv == NULL && context->VertexAttrib3dvNV != NULL) context->VertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC)context->VertexAttrib3dvNV; + if (context->VertexAttrib3dvARB == NULL && context->VertexAttrib3dv != NULL) context->VertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC)context->VertexAttrib3dv; + if (context->VertexAttrib3dvARB == NULL && context->VertexAttrib3dvNV != NULL) context->VertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC)context->VertexAttrib3dvNV; + if (context->VertexAttrib3dvNV == NULL && context->VertexAttrib3dv != NULL) context->VertexAttrib3dvNV = (PFNGLVERTEXATTRIB3DVNVPROC)context->VertexAttrib3dv; + if (context->VertexAttrib3dvNV == NULL && context->VertexAttrib3dvARB != NULL) context->VertexAttrib3dvNV = (PFNGLVERTEXATTRIB3DVNVPROC)context->VertexAttrib3dvARB; + if (context->VertexAttrib3f == NULL && context->VertexAttrib3fARB != NULL) context->VertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC)context->VertexAttrib3fARB; + if (context->VertexAttrib3f == NULL && context->VertexAttrib3fNV != NULL) context->VertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC)context->VertexAttrib3fNV; + if (context->VertexAttrib3fARB == NULL && context->VertexAttrib3f != NULL) context->VertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC)context->VertexAttrib3f; + if (context->VertexAttrib3fARB == NULL && context->VertexAttrib3fNV != NULL) context->VertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC)context->VertexAttrib3fNV; + if (context->VertexAttrib3fNV == NULL && context->VertexAttrib3f != NULL) context->VertexAttrib3fNV = (PFNGLVERTEXATTRIB3FNVPROC)context->VertexAttrib3f; + if (context->VertexAttrib3fNV == NULL && context->VertexAttrib3fARB != NULL) context->VertexAttrib3fNV = (PFNGLVERTEXATTRIB3FNVPROC)context->VertexAttrib3fARB; + if (context->VertexAttrib3fv == NULL && context->VertexAttrib3fvARB != NULL) context->VertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC)context->VertexAttrib3fvARB; + if (context->VertexAttrib3fv == NULL && context->VertexAttrib3fvNV != NULL) context->VertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC)context->VertexAttrib3fvNV; + if (context->VertexAttrib3fvARB == NULL && context->VertexAttrib3fv != NULL) context->VertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC)context->VertexAttrib3fv; + if (context->VertexAttrib3fvARB == NULL && context->VertexAttrib3fvNV != NULL) context->VertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC)context->VertexAttrib3fvNV; + if (context->VertexAttrib3fvNV == NULL && context->VertexAttrib3fv != NULL) context->VertexAttrib3fvNV = (PFNGLVERTEXATTRIB3FVNVPROC)context->VertexAttrib3fv; + if (context->VertexAttrib3fvNV == NULL && context->VertexAttrib3fvARB != NULL) context->VertexAttrib3fvNV = (PFNGLVERTEXATTRIB3FVNVPROC)context->VertexAttrib3fvARB; + if (context->VertexAttrib3s == NULL && context->VertexAttrib3sARB != NULL) context->VertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC)context->VertexAttrib3sARB; + if (context->VertexAttrib3s == NULL && context->VertexAttrib3sNV != NULL) context->VertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC)context->VertexAttrib3sNV; + if (context->VertexAttrib3sARB == NULL && context->VertexAttrib3s != NULL) context->VertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC)context->VertexAttrib3s; + if (context->VertexAttrib3sARB == NULL && context->VertexAttrib3sNV != NULL) context->VertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC)context->VertexAttrib3sNV; + if (context->VertexAttrib3sNV == NULL && context->VertexAttrib3s != NULL) context->VertexAttrib3sNV = (PFNGLVERTEXATTRIB3SNVPROC)context->VertexAttrib3s; + if (context->VertexAttrib3sNV == NULL && context->VertexAttrib3sARB != NULL) context->VertexAttrib3sNV = (PFNGLVERTEXATTRIB3SNVPROC)context->VertexAttrib3sARB; + if (context->VertexAttrib3sv == NULL && context->VertexAttrib3svARB != NULL) context->VertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC)context->VertexAttrib3svARB; + if (context->VertexAttrib3sv == NULL && context->VertexAttrib3svNV != NULL) context->VertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC)context->VertexAttrib3svNV; + if (context->VertexAttrib3svARB == NULL && context->VertexAttrib3sv != NULL) context->VertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC)context->VertexAttrib3sv; + if (context->VertexAttrib3svARB == NULL && context->VertexAttrib3svNV != NULL) context->VertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC)context->VertexAttrib3svNV; + if (context->VertexAttrib3svNV == NULL && context->VertexAttrib3sv != NULL) context->VertexAttrib3svNV = (PFNGLVERTEXATTRIB3SVNVPROC)context->VertexAttrib3sv; + if (context->VertexAttrib3svNV == NULL && context->VertexAttrib3svARB != NULL) context->VertexAttrib3svNV = (PFNGLVERTEXATTRIB3SVNVPROC)context->VertexAttrib3svARB; + if (context->VertexAttrib4bv == NULL && context->VertexAttrib4bvARB != NULL) context->VertexAttrib4bv = (PFNGLVERTEXATTRIB4BVPROC)context->VertexAttrib4bvARB; + if (context->VertexAttrib4bvARB == NULL && context->VertexAttrib4bv != NULL) context->VertexAttrib4bvARB = (PFNGLVERTEXATTRIB4BVARBPROC)context->VertexAttrib4bv; + if (context->VertexAttrib4d == NULL && context->VertexAttrib4dARB != NULL) context->VertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC)context->VertexAttrib4dARB; + if (context->VertexAttrib4d == NULL && context->VertexAttrib4dNV != NULL) context->VertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC)context->VertexAttrib4dNV; + if (context->VertexAttrib4dARB == NULL && context->VertexAttrib4d != NULL) context->VertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC)context->VertexAttrib4d; + if (context->VertexAttrib4dARB == NULL && context->VertexAttrib4dNV != NULL) context->VertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC)context->VertexAttrib4dNV; + if (context->VertexAttrib4dNV == NULL && context->VertexAttrib4d != NULL) context->VertexAttrib4dNV = (PFNGLVERTEXATTRIB4DNVPROC)context->VertexAttrib4d; + if (context->VertexAttrib4dNV == NULL && context->VertexAttrib4dARB != NULL) context->VertexAttrib4dNV = (PFNGLVERTEXATTRIB4DNVPROC)context->VertexAttrib4dARB; + if (context->VertexAttrib4dv == NULL && context->VertexAttrib4dvARB != NULL) context->VertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC)context->VertexAttrib4dvARB; + if (context->VertexAttrib4dv == NULL && context->VertexAttrib4dvNV != NULL) context->VertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC)context->VertexAttrib4dvNV; + if (context->VertexAttrib4dvARB == NULL && context->VertexAttrib4dv != NULL) context->VertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC)context->VertexAttrib4dv; + if (context->VertexAttrib4dvARB == NULL && context->VertexAttrib4dvNV != NULL) context->VertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC)context->VertexAttrib4dvNV; + if (context->VertexAttrib4dvNV == NULL && context->VertexAttrib4dv != NULL) context->VertexAttrib4dvNV = (PFNGLVERTEXATTRIB4DVNVPROC)context->VertexAttrib4dv; + if (context->VertexAttrib4dvNV == NULL && context->VertexAttrib4dvARB != NULL) context->VertexAttrib4dvNV = (PFNGLVERTEXATTRIB4DVNVPROC)context->VertexAttrib4dvARB; + if (context->VertexAttrib4f == NULL && context->VertexAttrib4fARB != NULL) context->VertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC)context->VertexAttrib4fARB; + if (context->VertexAttrib4f == NULL && context->VertexAttrib4fNV != NULL) context->VertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC)context->VertexAttrib4fNV; + if (context->VertexAttrib4fARB == NULL && context->VertexAttrib4f != NULL) context->VertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC)context->VertexAttrib4f; + if (context->VertexAttrib4fARB == NULL && context->VertexAttrib4fNV != NULL) context->VertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC)context->VertexAttrib4fNV; + if (context->VertexAttrib4fNV == NULL && context->VertexAttrib4f != NULL) context->VertexAttrib4fNV = (PFNGLVERTEXATTRIB4FNVPROC)context->VertexAttrib4f; + if (context->VertexAttrib4fNV == NULL && context->VertexAttrib4fARB != NULL) context->VertexAttrib4fNV = (PFNGLVERTEXATTRIB4FNVPROC)context->VertexAttrib4fARB; + if (context->VertexAttrib4fv == NULL && context->VertexAttrib4fvARB != NULL) context->VertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC)context->VertexAttrib4fvARB; + if (context->VertexAttrib4fv == NULL && context->VertexAttrib4fvNV != NULL) context->VertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC)context->VertexAttrib4fvNV; + if (context->VertexAttrib4fvARB == NULL && context->VertexAttrib4fv != NULL) context->VertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC)context->VertexAttrib4fv; + if (context->VertexAttrib4fvARB == NULL && context->VertexAttrib4fvNV != NULL) context->VertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC)context->VertexAttrib4fvNV; + if (context->VertexAttrib4fvNV == NULL && context->VertexAttrib4fv != NULL) context->VertexAttrib4fvNV = (PFNGLVERTEXATTRIB4FVNVPROC)context->VertexAttrib4fv; + if (context->VertexAttrib4fvNV == NULL && context->VertexAttrib4fvARB != NULL) context->VertexAttrib4fvNV = (PFNGLVERTEXATTRIB4FVNVPROC)context->VertexAttrib4fvARB; + if (context->VertexAttrib4iv == NULL && context->VertexAttrib4ivARB != NULL) context->VertexAttrib4iv = (PFNGLVERTEXATTRIB4IVPROC)context->VertexAttrib4ivARB; + if (context->VertexAttrib4ivARB == NULL && context->VertexAttrib4iv != NULL) context->VertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC)context->VertexAttrib4iv; + if (context->VertexAttrib4Nbv == NULL && context->VertexAttrib4NbvARB != NULL) context->VertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBVPROC)context->VertexAttrib4NbvARB; + if (context->VertexAttrib4NbvARB == NULL && context->VertexAttrib4Nbv != NULL) context->VertexAttrib4NbvARB = (PFNGLVERTEXATTRIB4NBVARBPROC)context->VertexAttrib4Nbv; + if (context->VertexAttrib4Niv == NULL && context->VertexAttrib4NivARB != NULL) context->VertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIVPROC)context->VertexAttrib4NivARB; + if (context->VertexAttrib4NivARB == NULL && context->VertexAttrib4Niv != NULL) context->VertexAttrib4NivARB = (PFNGLVERTEXATTRIB4NIVARBPROC)context->VertexAttrib4Niv; + if (context->VertexAttrib4Nsv == NULL && context->VertexAttrib4NsvARB != NULL) context->VertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSVPROC)context->VertexAttrib4NsvARB; + if (context->VertexAttrib4NsvARB == NULL && context->VertexAttrib4Nsv != NULL) context->VertexAttrib4NsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC)context->VertexAttrib4Nsv; + if (context->VertexAttrib4Nub == NULL && context->VertexAttrib4NubARB != NULL) context->VertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC)context->VertexAttrib4NubARB; + if (context->VertexAttrib4Nub == NULL && context->VertexAttrib4ubNV != NULL) context->VertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC)context->VertexAttrib4ubNV; + if (context->VertexAttrib4NubARB == NULL && context->VertexAttrib4Nub != NULL) context->VertexAttrib4NubARB = (PFNGLVERTEXATTRIB4NUBARBPROC)context->VertexAttrib4Nub; + if (context->VertexAttrib4NubARB == NULL && context->VertexAttrib4ubNV != NULL) context->VertexAttrib4NubARB = (PFNGLVERTEXATTRIB4NUBARBPROC)context->VertexAttrib4ubNV; + if (context->VertexAttrib4Nubv == NULL && context->VertexAttrib4NubvARB != NULL) context->VertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC)context->VertexAttrib4NubvARB; + if (context->VertexAttrib4Nubv == NULL && context->VertexAttrib4ubvNV != NULL) context->VertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC)context->VertexAttrib4ubvNV; + if (context->VertexAttrib4NubvARB == NULL && context->VertexAttrib4Nubv != NULL) context->VertexAttrib4NubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC)context->VertexAttrib4Nubv; + if (context->VertexAttrib4NubvARB == NULL && context->VertexAttrib4ubvNV != NULL) context->VertexAttrib4NubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC)context->VertexAttrib4ubvNV; + if (context->VertexAttrib4Nuiv == NULL && context->VertexAttrib4NuivARB != NULL) context->VertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIVPROC)context->VertexAttrib4NuivARB; + if (context->VertexAttrib4NuivARB == NULL && context->VertexAttrib4Nuiv != NULL) context->VertexAttrib4NuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC)context->VertexAttrib4Nuiv; + if (context->VertexAttrib4Nusv == NULL && context->VertexAttrib4NusvARB != NULL) context->VertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSVPROC)context->VertexAttrib4NusvARB; + if (context->VertexAttrib4NusvARB == NULL && context->VertexAttrib4Nusv != NULL) context->VertexAttrib4NusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC)context->VertexAttrib4Nusv; + if (context->VertexAttrib4s == NULL && context->VertexAttrib4sARB != NULL) context->VertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC)context->VertexAttrib4sARB; + if (context->VertexAttrib4s == NULL && context->VertexAttrib4sNV != NULL) context->VertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC)context->VertexAttrib4sNV; + if (context->VertexAttrib4sARB == NULL && context->VertexAttrib4s != NULL) context->VertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC)context->VertexAttrib4s; + if (context->VertexAttrib4sARB == NULL && context->VertexAttrib4sNV != NULL) context->VertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC)context->VertexAttrib4sNV; + if (context->VertexAttrib4sNV == NULL && context->VertexAttrib4s != NULL) context->VertexAttrib4sNV = (PFNGLVERTEXATTRIB4SNVPROC)context->VertexAttrib4s; + if (context->VertexAttrib4sNV == NULL && context->VertexAttrib4sARB != NULL) context->VertexAttrib4sNV = (PFNGLVERTEXATTRIB4SNVPROC)context->VertexAttrib4sARB; + if (context->VertexAttrib4sv == NULL && context->VertexAttrib4svARB != NULL) context->VertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC)context->VertexAttrib4svARB; + if (context->VertexAttrib4sv == NULL && context->VertexAttrib4svNV != NULL) context->VertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC)context->VertexAttrib4svNV; + if (context->VertexAttrib4svARB == NULL && context->VertexAttrib4sv != NULL) context->VertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC)context->VertexAttrib4sv; + if (context->VertexAttrib4svARB == NULL && context->VertexAttrib4svNV != NULL) context->VertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC)context->VertexAttrib4svNV; + if (context->VertexAttrib4svNV == NULL && context->VertexAttrib4sv != NULL) context->VertexAttrib4svNV = (PFNGLVERTEXATTRIB4SVNVPROC)context->VertexAttrib4sv; + if (context->VertexAttrib4svNV == NULL && context->VertexAttrib4svARB != NULL) context->VertexAttrib4svNV = (PFNGLVERTEXATTRIB4SVNVPROC)context->VertexAttrib4svARB; + if (context->VertexAttrib4ubNV == NULL && context->VertexAttrib4Nub != NULL) context->VertexAttrib4ubNV = (PFNGLVERTEXATTRIB4UBNVPROC)context->VertexAttrib4Nub; + if (context->VertexAttrib4ubNV == NULL && context->VertexAttrib4NubARB != NULL) context->VertexAttrib4ubNV = (PFNGLVERTEXATTRIB4UBNVPROC)context->VertexAttrib4NubARB; + if (context->VertexAttrib4ubv == NULL && context->VertexAttrib4ubvARB != NULL) context->VertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBVPROC)context->VertexAttrib4ubvARB; + if (context->VertexAttrib4ubvARB == NULL && context->VertexAttrib4ubv != NULL) context->VertexAttrib4ubvARB = (PFNGLVERTEXATTRIB4UBVARBPROC)context->VertexAttrib4ubv; + if (context->VertexAttrib4ubvNV == NULL && context->VertexAttrib4Nubv != NULL) context->VertexAttrib4ubvNV = (PFNGLVERTEXATTRIB4UBVNVPROC)context->VertexAttrib4Nubv; + if (context->VertexAttrib4ubvNV == NULL && context->VertexAttrib4NubvARB != NULL) context->VertexAttrib4ubvNV = (PFNGLVERTEXATTRIB4UBVNVPROC)context->VertexAttrib4NubvARB; + if (context->VertexAttrib4uiv == NULL && context->VertexAttrib4uivARB != NULL) context->VertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC)context->VertexAttrib4uivARB; + if (context->VertexAttrib4uivARB == NULL && context->VertexAttrib4uiv != NULL) context->VertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC)context->VertexAttrib4uiv; + if (context->VertexAttrib4usv == NULL && context->VertexAttrib4usvARB != NULL) context->VertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC)context->VertexAttrib4usvARB; + if (context->VertexAttrib4usvARB == NULL && context->VertexAttrib4usv != NULL) context->VertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC)context->VertexAttrib4usv; + if (context->VertexAttribI1i == NULL && context->VertexAttribI1iEXT != NULL) context->VertexAttribI1i = (PFNGLVERTEXATTRIBI1IPROC)context->VertexAttribI1iEXT; + if (context->VertexAttribI1iEXT == NULL && context->VertexAttribI1i != NULL) context->VertexAttribI1iEXT = (PFNGLVERTEXATTRIBI1IEXTPROC)context->VertexAttribI1i; + if (context->VertexAttribI1iv == NULL && context->VertexAttribI1ivEXT != NULL) context->VertexAttribI1iv = (PFNGLVERTEXATTRIBI1IVPROC)context->VertexAttribI1ivEXT; + if (context->VertexAttribI1ivEXT == NULL && context->VertexAttribI1iv != NULL) context->VertexAttribI1ivEXT = (PFNGLVERTEXATTRIBI1IVEXTPROC)context->VertexAttribI1iv; + if (context->VertexAttribI1ui == NULL && context->VertexAttribI1uiEXT != NULL) context->VertexAttribI1ui = (PFNGLVERTEXATTRIBI1UIPROC)context->VertexAttribI1uiEXT; + if (context->VertexAttribI1uiEXT == NULL && context->VertexAttribI1ui != NULL) context->VertexAttribI1uiEXT = (PFNGLVERTEXATTRIBI1UIEXTPROC)context->VertexAttribI1ui; + if (context->VertexAttribI1uiv == NULL && context->VertexAttribI1uivEXT != NULL) context->VertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIVPROC)context->VertexAttribI1uivEXT; + if (context->VertexAttribI1uivEXT == NULL && context->VertexAttribI1uiv != NULL) context->VertexAttribI1uivEXT = (PFNGLVERTEXATTRIBI1UIVEXTPROC)context->VertexAttribI1uiv; + if (context->VertexAttribI2i == NULL && context->VertexAttribI2iEXT != NULL) context->VertexAttribI2i = (PFNGLVERTEXATTRIBI2IPROC)context->VertexAttribI2iEXT; + if (context->VertexAttribI2iEXT == NULL && context->VertexAttribI2i != NULL) context->VertexAttribI2iEXT = (PFNGLVERTEXATTRIBI2IEXTPROC)context->VertexAttribI2i; + if (context->VertexAttribI2iv == NULL && context->VertexAttribI2ivEXT != NULL) context->VertexAttribI2iv = (PFNGLVERTEXATTRIBI2IVPROC)context->VertexAttribI2ivEXT; + if (context->VertexAttribI2ivEXT == NULL && context->VertexAttribI2iv != NULL) context->VertexAttribI2ivEXT = (PFNGLVERTEXATTRIBI2IVEXTPROC)context->VertexAttribI2iv; + if (context->VertexAttribI2ui == NULL && context->VertexAttribI2uiEXT != NULL) context->VertexAttribI2ui = (PFNGLVERTEXATTRIBI2UIPROC)context->VertexAttribI2uiEXT; + if (context->VertexAttribI2uiEXT == NULL && context->VertexAttribI2ui != NULL) context->VertexAttribI2uiEXT = (PFNGLVERTEXATTRIBI2UIEXTPROC)context->VertexAttribI2ui; + if (context->VertexAttribI2uiv == NULL && context->VertexAttribI2uivEXT != NULL) context->VertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIVPROC)context->VertexAttribI2uivEXT; + if (context->VertexAttribI2uivEXT == NULL && context->VertexAttribI2uiv != NULL) context->VertexAttribI2uivEXT = (PFNGLVERTEXATTRIBI2UIVEXTPROC)context->VertexAttribI2uiv; + if (context->VertexAttribI3i == NULL && context->VertexAttribI3iEXT != NULL) context->VertexAttribI3i = (PFNGLVERTEXATTRIBI3IPROC)context->VertexAttribI3iEXT; + if (context->VertexAttribI3iEXT == NULL && context->VertexAttribI3i != NULL) context->VertexAttribI3iEXT = (PFNGLVERTEXATTRIBI3IEXTPROC)context->VertexAttribI3i; + if (context->VertexAttribI3iv == NULL && context->VertexAttribI3ivEXT != NULL) context->VertexAttribI3iv = (PFNGLVERTEXATTRIBI3IVPROC)context->VertexAttribI3ivEXT; + if (context->VertexAttribI3ivEXT == NULL && context->VertexAttribI3iv != NULL) context->VertexAttribI3ivEXT = (PFNGLVERTEXATTRIBI3IVEXTPROC)context->VertexAttribI3iv; + if (context->VertexAttribI3ui == NULL && context->VertexAttribI3uiEXT != NULL) context->VertexAttribI3ui = (PFNGLVERTEXATTRIBI3UIPROC)context->VertexAttribI3uiEXT; + if (context->VertexAttribI3uiEXT == NULL && context->VertexAttribI3ui != NULL) context->VertexAttribI3uiEXT = (PFNGLVERTEXATTRIBI3UIEXTPROC)context->VertexAttribI3ui; + if (context->VertexAttribI3uiv == NULL && context->VertexAttribI3uivEXT != NULL) context->VertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIVPROC)context->VertexAttribI3uivEXT; + if (context->VertexAttribI3uivEXT == NULL && context->VertexAttribI3uiv != NULL) context->VertexAttribI3uivEXT = (PFNGLVERTEXATTRIBI3UIVEXTPROC)context->VertexAttribI3uiv; + if (context->VertexAttribI4bv == NULL && context->VertexAttribI4bvEXT != NULL) context->VertexAttribI4bv = (PFNGLVERTEXATTRIBI4BVPROC)context->VertexAttribI4bvEXT; + if (context->VertexAttribI4bvEXT == NULL && context->VertexAttribI4bv != NULL) context->VertexAttribI4bvEXT = (PFNGLVERTEXATTRIBI4BVEXTPROC)context->VertexAttribI4bv; + if (context->VertexAttribI4i == NULL && context->VertexAttribI4iEXT != NULL) context->VertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC)context->VertexAttribI4iEXT; + if (context->VertexAttribI4iEXT == NULL && context->VertexAttribI4i != NULL) context->VertexAttribI4iEXT = (PFNGLVERTEXATTRIBI4IEXTPROC)context->VertexAttribI4i; + if (context->VertexAttribI4iv == NULL && context->VertexAttribI4ivEXT != NULL) context->VertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC)context->VertexAttribI4ivEXT; + if (context->VertexAttribI4ivEXT == NULL && context->VertexAttribI4iv != NULL) context->VertexAttribI4ivEXT = (PFNGLVERTEXATTRIBI4IVEXTPROC)context->VertexAttribI4iv; + if (context->VertexAttribI4sv == NULL && context->VertexAttribI4svEXT != NULL) context->VertexAttribI4sv = (PFNGLVERTEXATTRIBI4SVPROC)context->VertexAttribI4svEXT; + if (context->VertexAttribI4svEXT == NULL && context->VertexAttribI4sv != NULL) context->VertexAttribI4svEXT = (PFNGLVERTEXATTRIBI4SVEXTPROC)context->VertexAttribI4sv; + if (context->VertexAttribI4ubv == NULL && context->VertexAttribI4ubvEXT != NULL) context->VertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBVPROC)context->VertexAttribI4ubvEXT; + if (context->VertexAttribI4ubvEXT == NULL && context->VertexAttribI4ubv != NULL) context->VertexAttribI4ubvEXT = (PFNGLVERTEXATTRIBI4UBVEXTPROC)context->VertexAttribI4ubv; + if (context->VertexAttribI4ui == NULL && context->VertexAttribI4uiEXT != NULL) context->VertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC)context->VertexAttribI4uiEXT; + if (context->VertexAttribI4uiEXT == NULL && context->VertexAttribI4ui != NULL) context->VertexAttribI4uiEXT = (PFNGLVERTEXATTRIBI4UIEXTPROC)context->VertexAttribI4ui; + if (context->VertexAttribI4uiv == NULL && context->VertexAttribI4uivEXT != NULL) context->VertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC)context->VertexAttribI4uivEXT; + if (context->VertexAttribI4uivEXT == NULL && context->VertexAttribI4uiv != NULL) context->VertexAttribI4uivEXT = (PFNGLVERTEXATTRIBI4UIVEXTPROC)context->VertexAttribI4uiv; + if (context->VertexAttribI4usv == NULL && context->VertexAttribI4usvEXT != NULL) context->VertexAttribI4usv = (PFNGLVERTEXATTRIBI4USVPROC)context->VertexAttribI4usvEXT; + if (context->VertexAttribI4usvEXT == NULL && context->VertexAttribI4usv != NULL) context->VertexAttribI4usvEXT = (PFNGLVERTEXATTRIBI4USVEXTPROC)context->VertexAttribI4usv; + if (context->VertexAttribIPointer == NULL && context->VertexAttribIPointerEXT != NULL) context->VertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC)context->VertexAttribIPointerEXT; + if (context->VertexAttribIPointerEXT == NULL && context->VertexAttribIPointer != NULL) context->VertexAttribIPointerEXT = (PFNGLVERTEXATTRIBIPOINTEREXTPROC)context->VertexAttribIPointer; + if (context->VertexAttribPointer == NULL && context->VertexAttribPointerARB != NULL) context->VertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)context->VertexAttribPointerARB; + if (context->VertexAttribPointerARB == NULL && context->VertexAttribPointer != NULL) context->VertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC)context->VertexAttribPointer; +} + +#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0) +#define GLAD_GL_IS_SOME_NEW_VERSION 1 +#else +#define GLAD_GL_IS_SOME_NEW_VERSION 0 +#endif + +static int glad_gl_get_extensions(GladGLContext *context, int version, const char **out_exts, unsigned int *out_num_exts_i, char ***out_exts_i) { +#if GLAD_GL_IS_SOME_NEW_VERSION + if(GLAD_VERSION_MAJOR(version) < 3) { +#else + GLAD_UNUSED(version); + GLAD_UNUSED(out_num_exts_i); + GLAD_UNUSED(out_exts_i); +#endif + if (context->GetString == NULL) { + return 0; + } + *out_exts = (const char *)context->GetString(GL_EXTENSIONS); +#if GLAD_GL_IS_SOME_NEW_VERSION + } else { + unsigned int index = 0; + unsigned int num_exts_i = 0; + char **exts_i = NULL; + if (context->GetStringi == NULL || context->GetIntegerv == NULL) { + return 0; + } + context->GetIntegerv(GL_NUM_EXTENSIONS, (int*) &num_exts_i); + if (num_exts_i > 0) { + exts_i = (char **) malloc(num_exts_i * (sizeof *exts_i)); + } + if (exts_i == NULL) { + return 0; + } + for(index = 0; index < num_exts_i; index++) { + const char *gl_str_tmp = (const char*) context->GetStringi(GL_EXTENSIONS, index); + size_t len = strlen(gl_str_tmp) + 1; + + char *local_str = (char*) malloc(len * sizeof(char)); + if(local_str != NULL) { + memcpy(local_str, gl_str_tmp, len * sizeof(char)); + } + + exts_i[index] = local_str; + } + + *out_num_exts_i = num_exts_i; + *out_exts_i = exts_i; + } +#endif + return 1; +} +static void glad_gl_free_extensions(char **exts_i, unsigned int num_exts_i) { + if (exts_i != NULL) { + unsigned int index; + for(index = 0; index < num_exts_i; index++) { + free((void *) (exts_i[index])); + } + free((void *)exts_i); + exts_i = NULL; + } +} +static int glad_gl_has_extension(int version, const char *exts, unsigned int num_exts_i, char **exts_i, const char *ext) { + if(GLAD_VERSION_MAJOR(version) < 3 || !GLAD_GL_IS_SOME_NEW_VERSION) { + const char *extensions; + const char *loc; + const char *terminator; + extensions = exts; + if(extensions == NULL || ext == NULL) { + return 0; + } + while(1) { + loc = strstr(extensions, ext); + if(loc == NULL) { + return 0; + } + terminator = loc + strlen(ext); + if((loc == extensions || *(loc - 1) == ' ') && + (*terminator == ' ' || *terminator == '\0')) { + return 1; + } + extensions = terminator; + } + } else { + unsigned int index; + for(index = 0; index < num_exts_i; index++) { + const char *e = exts_i[index]; + if(strcmp(e, ext) == 0) { + return 1; + } + } + } + return 0; +} + +static GLADapiproc glad_gl_get_proc_from_userptr(void *userptr, const char* name) { + return (GLAD_GNUC_EXTENSION (GLADapiproc (*)(const char *name)) userptr)(name); +} + +static int glad_gl_find_extensions_gl(GladGLContext *context, int version) { + const char *exts = NULL; + unsigned int num_exts_i = 0; + char **exts_i = NULL; + if (!glad_gl_get_extensions(context, version, &exts, &num_exts_i, &exts_i)) return 0; + + context->APPLE_flush_buffer_range = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_APPLE_flush_buffer_range"); + context->APPLE_vertex_array_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_APPLE_vertex_array_object"); + context->ARB_color_buffer_float = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_color_buffer_float"); + context->ARB_copy_buffer = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_copy_buffer"); + context->ARB_draw_buffers = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_draw_buffers"); + context->ARB_draw_elements_base_vertex = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_draw_elements_base_vertex"); + context->ARB_draw_instanced = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_draw_instanced"); + context->ARB_framebuffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_framebuffer_object"); + context->ARB_geometry_shader4 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_geometry_shader4"); + context->ARB_imaging = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_imaging"); + context->ARB_map_buffer_range = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_map_buffer_range"); + context->ARB_multisample = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_multisample"); + context->ARB_multitexture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_multitexture"); + context->ARB_occlusion_query = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_occlusion_query"); + context->ARB_point_parameters = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_point_parameters"); + context->ARB_provoking_vertex = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_provoking_vertex"); + context->ARB_shader_objects = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_shader_objects"); + context->ARB_sync = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_sync"); + context->ARB_texture_buffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_buffer_object"); + context->ARB_texture_compression = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_compression"); + context->ARB_texture_multisample = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_multisample"); + context->ARB_uniform_buffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_uniform_buffer_object"); + context->ARB_vertex_array_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_vertex_array_object"); + context->ARB_vertex_buffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_vertex_buffer_object"); + context->ARB_vertex_program = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_vertex_program"); + context->ARB_vertex_shader = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_vertex_shader"); + context->ATI_draw_buffers = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ATI_draw_buffers"); + context->ATI_separate_stencil = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ATI_separate_stencil"); + context->EXT_blend_color = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_blend_color"); + context->EXT_blend_equation_separate = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_blend_equation_separate"); + context->EXT_blend_func_separate = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_blend_func_separate"); + context->EXT_blend_minmax = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_blend_minmax"); + context->EXT_copy_texture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_copy_texture"); + context->EXT_direct_state_access = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_direct_state_access"); + context->EXT_draw_buffers2 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_draw_buffers2"); + context->EXT_draw_instanced = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_draw_instanced"); + context->EXT_draw_range_elements = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_draw_range_elements"); + context->EXT_framebuffer_blit = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_framebuffer_blit"); + context->EXT_framebuffer_multisample = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_framebuffer_multisample"); + context->EXT_framebuffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_framebuffer_object"); + context->EXT_gpu_shader4 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_gpu_shader4"); + context->EXT_multi_draw_arrays = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_multi_draw_arrays"); + context->EXT_point_parameters = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_point_parameters"); + context->EXT_provoking_vertex = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_provoking_vertex"); + context->EXT_subtexture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_subtexture"); + context->EXT_texture3D = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture3D"); + context->EXT_texture_array = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_array"); + context->EXT_texture_buffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_buffer_object"); + context->EXT_texture_integer = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_integer"); + context->EXT_texture_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_object"); + context->EXT_transform_feedback = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_transform_feedback"); + context->EXT_vertex_array = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_vertex_array"); + context->INGR_blend_func_separate = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_INGR_blend_func_separate"); + context->NVX_conditional_render = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_NVX_conditional_render"); + context->NV_conditional_render = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_NV_conditional_render"); + context->NV_explicit_multisample = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_NV_explicit_multisample"); + context->NV_geometry_program4 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_NV_geometry_program4"); + context->NV_point_sprite = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_NV_point_sprite"); + context->NV_transform_feedback = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_NV_transform_feedback"); + context->NV_vertex_program = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_NV_vertex_program"); + context->NV_vertex_program4 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_NV_vertex_program4"); + context->SGIS_point_parameters = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_SGIS_point_parameters"); + + glad_gl_free_extensions(exts_i, num_exts_i); + + return 1; +} + +static int glad_gl_find_core_gl(GladGLContext *context) { + int i; + const char* version; + const char* prefixes[] = { + "OpenGL ES-CM ", + "OpenGL ES-CL ", + "OpenGL ES ", + "OpenGL SC ", + NULL + }; + int major = 0; + int minor = 0; + version = (const char*) context->GetString(GL_VERSION); + if (!version) return 0; + for (i = 0; prefixes[i]; i++) { + const size_t length = strlen(prefixes[i]); + if (strncmp(version, prefixes[i], length) == 0) { + version += length; + break; + } + } + + GLAD_IMPL_UTIL_SSCANF(version, "%d.%d", &major, &minor); + + context->VERSION_1_0 = (major == 1 && minor >= 0) || major > 1; + context->VERSION_1_1 = (major == 1 && minor >= 1) || major > 1; + context->VERSION_1_2 = (major == 1 && minor >= 2) || major > 1; + context->VERSION_1_3 = (major == 1 && minor >= 3) || major > 1; + context->VERSION_1_4 = (major == 1 && minor >= 4) || major > 1; + context->VERSION_1_5 = (major == 1 && minor >= 5) || major > 1; + context->VERSION_2_0 = (major == 2 && minor >= 0) || major > 2; + context->VERSION_2_1 = (major == 2 && minor >= 1) || major > 2; + context->VERSION_3_0 = (major == 3 && minor >= 0) || major > 3; + context->VERSION_3_1 = (major == 3 && minor >= 1) || major > 3; + context->VERSION_3_2 = (major == 3 && minor >= 2) || major > 3; + + return GLAD_MAKE_VERSION(major, minor); +} + +int gladLoadGLContextUserPtr(GladGLContext *context, GLADuserptrloadfunc load, void *userptr) { + int version; + + context->GetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString"); + if(context->GetString == NULL) return 0; + if(context->GetString(GL_VERSION) == NULL) return 0; + version = glad_gl_find_core_gl(context); + + glad_gl_load_GL_VERSION_1_0(context, load, userptr); + glad_gl_load_GL_VERSION_1_1(context, load, userptr); + glad_gl_load_GL_VERSION_1_2(context, load, userptr); + glad_gl_load_GL_VERSION_1_3(context, load, userptr); + glad_gl_load_GL_VERSION_1_4(context, load, userptr); + glad_gl_load_GL_VERSION_1_5(context, load, userptr); + glad_gl_load_GL_VERSION_2_0(context, load, userptr); + glad_gl_load_GL_VERSION_2_1(context, load, userptr); + glad_gl_load_GL_VERSION_3_0(context, load, userptr); + glad_gl_load_GL_VERSION_3_1(context, load, userptr); + glad_gl_load_GL_VERSION_3_2(context, load, userptr); + + if (!glad_gl_find_extensions_gl(context, version)) return 0; + glad_gl_load_GL_APPLE_flush_buffer_range(context, load, userptr); + glad_gl_load_GL_APPLE_vertex_array_object(context, load, userptr); + glad_gl_load_GL_ARB_color_buffer_float(context, load, userptr); + glad_gl_load_GL_ARB_copy_buffer(context, load, userptr); + glad_gl_load_GL_ARB_draw_buffers(context, load, userptr); + glad_gl_load_GL_ARB_draw_elements_base_vertex(context, load, userptr); + glad_gl_load_GL_ARB_draw_instanced(context, load, userptr); + glad_gl_load_GL_ARB_framebuffer_object(context, load, userptr); + glad_gl_load_GL_ARB_geometry_shader4(context, load, userptr); + glad_gl_load_GL_ARB_imaging(context, load, userptr); + glad_gl_load_GL_ARB_map_buffer_range(context, load, userptr); + glad_gl_load_GL_ARB_multisample(context, load, userptr); + glad_gl_load_GL_ARB_multitexture(context, load, userptr); + glad_gl_load_GL_ARB_occlusion_query(context, load, userptr); + glad_gl_load_GL_ARB_point_parameters(context, load, userptr); + glad_gl_load_GL_ARB_provoking_vertex(context, load, userptr); + glad_gl_load_GL_ARB_shader_objects(context, load, userptr); + glad_gl_load_GL_ARB_sync(context, load, userptr); + glad_gl_load_GL_ARB_texture_buffer_object(context, load, userptr); + glad_gl_load_GL_ARB_texture_compression(context, load, userptr); + glad_gl_load_GL_ARB_texture_multisample(context, load, userptr); + glad_gl_load_GL_ARB_uniform_buffer_object(context, load, userptr); + glad_gl_load_GL_ARB_vertex_array_object(context, load, userptr); + glad_gl_load_GL_ARB_vertex_buffer_object(context, load, userptr); + glad_gl_load_GL_ARB_vertex_program(context, load, userptr); + glad_gl_load_GL_ARB_vertex_shader(context, load, userptr); + glad_gl_load_GL_ATI_draw_buffers(context, load, userptr); + glad_gl_load_GL_ATI_separate_stencil(context, load, userptr); + glad_gl_load_GL_EXT_blend_color(context, load, userptr); + glad_gl_load_GL_EXT_blend_equation_separate(context, load, userptr); + glad_gl_load_GL_EXT_blend_func_separate(context, load, userptr); + glad_gl_load_GL_EXT_blend_minmax(context, load, userptr); + glad_gl_load_GL_EXT_copy_texture(context, load, userptr); + glad_gl_load_GL_EXT_direct_state_access(context, load, userptr); + glad_gl_load_GL_EXT_draw_buffers2(context, load, userptr); + glad_gl_load_GL_EXT_draw_instanced(context, load, userptr); + glad_gl_load_GL_EXT_draw_range_elements(context, load, userptr); + glad_gl_load_GL_EXT_framebuffer_blit(context, load, userptr); + glad_gl_load_GL_EXT_framebuffer_multisample(context, load, userptr); + glad_gl_load_GL_EXT_framebuffer_object(context, load, userptr); + glad_gl_load_GL_EXT_gpu_shader4(context, load, userptr); + glad_gl_load_GL_EXT_multi_draw_arrays(context, load, userptr); + glad_gl_load_GL_EXT_point_parameters(context, load, userptr); + glad_gl_load_GL_EXT_provoking_vertex(context, load, userptr); + glad_gl_load_GL_EXT_subtexture(context, load, userptr); + glad_gl_load_GL_EXT_texture3D(context, load, userptr); + glad_gl_load_GL_EXT_texture_array(context, load, userptr); + glad_gl_load_GL_EXT_texture_buffer_object(context, load, userptr); + glad_gl_load_GL_EXT_texture_integer(context, load, userptr); + glad_gl_load_GL_EXT_texture_object(context, load, userptr); + glad_gl_load_GL_EXT_transform_feedback(context, load, userptr); + glad_gl_load_GL_EXT_vertex_array(context, load, userptr); + glad_gl_load_GL_INGR_blend_func_separate(context, load, userptr); + glad_gl_load_GL_NVX_conditional_render(context, load, userptr); + glad_gl_load_GL_NV_conditional_render(context, load, userptr); + glad_gl_load_GL_NV_explicit_multisample(context, load, userptr); + glad_gl_load_GL_NV_geometry_program4(context, load, userptr); + glad_gl_load_GL_NV_point_sprite(context, load, userptr); + glad_gl_load_GL_NV_transform_feedback(context, load, userptr); + glad_gl_load_GL_NV_vertex_program(context, load, userptr); + glad_gl_load_GL_NV_vertex_program4(context, load, userptr); + glad_gl_load_GL_SGIS_point_parameters(context, load, userptr); + + + glad_gl_resolve_aliases(context); + + return version; +} + + +int gladLoadGLContext(GladGLContext *context, GLADloadfunc load) { + return gladLoadGLContextUserPtr(context, glad_gl_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load); +} + + + + + + +#ifdef __cplusplus +} +#endif diff --git a/thirdparty/glad/src/gles2.c b/thirdparty/glad/src/gles2.c new file mode 100644 index 000000000..5157bf288 --- /dev/null +++ b/thirdparty/glad/src/gles2.c @@ -0,0 +1,351 @@ +/** + * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0 + */ +#include +#include +#include +#include + +#ifndef GLAD_IMPL_UTIL_C_ +#define GLAD_IMPL_UTIL_C_ + +#ifdef _MSC_VER +#define GLAD_IMPL_UTIL_SSCANF sscanf_s +#else +#define GLAD_IMPL_UTIL_SSCANF sscanf +#endif + +#endif /* GLAD_IMPL_UTIL_C_ */ + +#ifdef __cplusplus +extern "C" { +#endif + + + + + + + + +static void glad_gl_load_GL_ES_VERSION_2_0(GladGLES2Context *context, GLADuserptrloadfunc load, void* userptr) { + if(!context->ES_VERSION_2_0) return; + context->ActiveTexture = (PFNGLACTIVETEXTUREPROC) load(userptr, "glActiveTexture"); + context->AttachShader = (PFNGLATTACHSHADERPROC) load(userptr, "glAttachShader"); + context->BindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC) load(userptr, "glBindAttribLocation"); + context->BindBuffer = (PFNGLBINDBUFFERPROC) load(userptr, "glBindBuffer"); + context->BindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) load(userptr, "glBindFramebuffer"); + context->BindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) load(userptr, "glBindRenderbuffer"); + context->BindTexture = (PFNGLBINDTEXTUREPROC) load(userptr, "glBindTexture"); + context->BlendColor = (PFNGLBLENDCOLORPROC) load(userptr, "glBlendColor"); + context->BlendEquation = (PFNGLBLENDEQUATIONPROC) load(userptr, "glBlendEquation"); + context->BlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC) load(userptr, "glBlendEquationSeparate"); + context->BlendFunc = (PFNGLBLENDFUNCPROC) load(userptr, "glBlendFunc"); + context->BlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC) load(userptr, "glBlendFuncSeparate"); + context->BufferData = (PFNGLBUFFERDATAPROC) load(userptr, "glBufferData"); + context->BufferSubData = (PFNGLBUFFERSUBDATAPROC) load(userptr, "glBufferSubData"); + context->CheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) load(userptr, "glCheckFramebufferStatus"); + context->Clear = (PFNGLCLEARPROC) load(userptr, "glClear"); + context->ClearColor = (PFNGLCLEARCOLORPROC) load(userptr, "glClearColor"); + context->ClearDepthf = (PFNGLCLEARDEPTHFPROC) load(userptr, "glClearDepthf"); + context->ClearStencil = (PFNGLCLEARSTENCILPROC) load(userptr, "glClearStencil"); + context->ColorMask = (PFNGLCOLORMASKPROC) load(userptr, "glColorMask"); + context->CompileShader = (PFNGLCOMPILESHADERPROC) load(userptr, "glCompileShader"); + context->CompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) load(userptr, "glCompressedTexImage2D"); + context->CompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) load(userptr, "glCompressedTexSubImage2D"); + context->CopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC) load(userptr, "glCopyTexImage2D"); + context->CopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC) load(userptr, "glCopyTexSubImage2D"); + context->CreateProgram = (PFNGLCREATEPROGRAMPROC) load(userptr, "glCreateProgram"); + context->CreateShader = (PFNGLCREATESHADERPROC) load(userptr, "glCreateShader"); + context->CullFace = (PFNGLCULLFACEPROC) load(userptr, "glCullFace"); + context->DeleteBuffers = (PFNGLDELETEBUFFERSPROC) load(userptr, "glDeleteBuffers"); + context->DeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) load(userptr, "glDeleteFramebuffers"); + context->DeleteProgram = (PFNGLDELETEPROGRAMPROC) load(userptr, "glDeleteProgram"); + context->DeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) load(userptr, "glDeleteRenderbuffers"); + context->DeleteShader = (PFNGLDELETESHADERPROC) load(userptr, "glDeleteShader"); + context->DeleteTextures = (PFNGLDELETETEXTURESPROC) load(userptr, "glDeleteTextures"); + context->DepthFunc = (PFNGLDEPTHFUNCPROC) load(userptr, "glDepthFunc"); + context->DepthMask = (PFNGLDEPTHMASKPROC) load(userptr, "glDepthMask"); + context->DepthRangef = (PFNGLDEPTHRANGEFPROC) load(userptr, "glDepthRangef"); + context->DetachShader = (PFNGLDETACHSHADERPROC) load(userptr, "glDetachShader"); + context->Disable = (PFNGLDISABLEPROC) load(userptr, "glDisable"); + context->DisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) load(userptr, "glDisableVertexAttribArray"); + context->DrawArrays = (PFNGLDRAWARRAYSPROC) load(userptr, "glDrawArrays"); + context->DrawElements = (PFNGLDRAWELEMENTSPROC) load(userptr, "glDrawElements"); + context->Enable = (PFNGLENABLEPROC) load(userptr, "glEnable"); + context->EnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) load(userptr, "glEnableVertexAttribArray"); + context->Finish = (PFNGLFINISHPROC) load(userptr, "glFinish"); + context->Flush = (PFNGLFLUSHPROC) load(userptr, "glFlush"); + context->FramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) load(userptr, "glFramebufferRenderbuffer"); + context->FramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) load(userptr, "glFramebufferTexture2D"); + context->FrontFace = (PFNGLFRONTFACEPROC) load(userptr, "glFrontFace"); + context->GenBuffers = (PFNGLGENBUFFERSPROC) load(userptr, "glGenBuffers"); + context->GenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) load(userptr, "glGenFramebuffers"); + context->GenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) load(userptr, "glGenRenderbuffers"); + context->GenTextures = (PFNGLGENTEXTURESPROC) load(userptr, "glGenTextures"); + context->GenerateMipmap = (PFNGLGENERATEMIPMAPPROC) load(userptr, "glGenerateMipmap"); + context->GetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC) load(userptr, "glGetActiveAttrib"); + context->GetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC) load(userptr, "glGetActiveUniform"); + context->GetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC) load(userptr, "glGetAttachedShaders"); + context->GetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) load(userptr, "glGetAttribLocation"); + context->GetBooleanv = (PFNGLGETBOOLEANVPROC) load(userptr, "glGetBooleanv"); + context->GetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC) load(userptr, "glGetBufferParameteriv"); + context->GetError = (PFNGLGETERRORPROC) load(userptr, "glGetError"); + context->GetFloatv = (PFNGLGETFLOATVPROC) load(userptr, "glGetFloatv"); + context->GetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load(userptr, "glGetFramebufferAttachmentParameteriv"); + context->GetIntegerv = (PFNGLGETINTEGERVPROC) load(userptr, "glGetIntegerv"); + context->GetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) load(userptr, "glGetProgramInfoLog"); + context->GetProgramiv = (PFNGLGETPROGRAMIVPROC) load(userptr, "glGetProgramiv"); + context->GetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) load(userptr, "glGetRenderbufferParameteriv"); + context->GetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) load(userptr, "glGetShaderInfoLog"); + context->GetShaderPrecisionFormat = (PFNGLGETSHADERPRECISIONFORMATPROC) load(userptr, "glGetShaderPrecisionFormat"); + context->GetShaderSource = (PFNGLGETSHADERSOURCEPROC) load(userptr, "glGetShaderSource"); + context->GetShaderiv = (PFNGLGETSHADERIVPROC) load(userptr, "glGetShaderiv"); + context->GetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString"); + context->GetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC) load(userptr, "glGetTexParameterfv"); + context->GetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC) load(userptr, "glGetTexParameteriv"); + context->GetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) load(userptr, "glGetUniformLocation"); + context->GetUniformfv = (PFNGLGETUNIFORMFVPROC) load(userptr, "glGetUniformfv"); + context->GetUniformiv = (PFNGLGETUNIFORMIVPROC) load(userptr, "glGetUniformiv"); + context->GetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC) load(userptr, "glGetVertexAttribPointerv"); + context->GetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC) load(userptr, "glGetVertexAttribfv"); + context->GetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC) load(userptr, "glGetVertexAttribiv"); + context->Hint = (PFNGLHINTPROC) load(userptr, "glHint"); + context->IsBuffer = (PFNGLISBUFFERPROC) load(userptr, "glIsBuffer"); + context->IsEnabled = (PFNGLISENABLEDPROC) load(userptr, "glIsEnabled"); + context->IsFramebuffer = (PFNGLISFRAMEBUFFERPROC) load(userptr, "glIsFramebuffer"); + context->IsProgram = (PFNGLISPROGRAMPROC) load(userptr, "glIsProgram"); + context->IsRenderbuffer = (PFNGLISRENDERBUFFERPROC) load(userptr, "glIsRenderbuffer"); + context->IsShader = (PFNGLISSHADERPROC) load(userptr, "glIsShader"); + context->IsTexture = (PFNGLISTEXTUREPROC) load(userptr, "glIsTexture"); + context->LineWidth = (PFNGLLINEWIDTHPROC) load(userptr, "glLineWidth"); + context->LinkProgram = (PFNGLLINKPROGRAMPROC) load(userptr, "glLinkProgram"); + context->PixelStorei = (PFNGLPIXELSTOREIPROC) load(userptr, "glPixelStorei"); + context->PolygonOffset = (PFNGLPOLYGONOFFSETPROC) load(userptr, "glPolygonOffset"); + context->ReadPixels = (PFNGLREADPIXELSPROC) load(userptr, "glReadPixels"); + context->ReleaseShaderCompiler = (PFNGLRELEASESHADERCOMPILERPROC) load(userptr, "glReleaseShaderCompiler"); + context->RenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) load(userptr, "glRenderbufferStorage"); + context->SampleCoverage = (PFNGLSAMPLECOVERAGEPROC) load(userptr, "glSampleCoverage"); + context->Scissor = (PFNGLSCISSORPROC) load(userptr, "glScissor"); + context->ShaderBinary = (PFNGLSHADERBINARYPROC) load(userptr, "glShaderBinary"); + context->ShaderSource = (PFNGLSHADERSOURCEPROC) load(userptr, "glShaderSource"); + context->StencilFunc = (PFNGLSTENCILFUNCPROC) load(userptr, "glStencilFunc"); + context->StencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC) load(userptr, "glStencilFuncSeparate"); + context->StencilMask = (PFNGLSTENCILMASKPROC) load(userptr, "glStencilMask"); + context->StencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC) load(userptr, "glStencilMaskSeparate"); + context->StencilOp = (PFNGLSTENCILOPPROC) load(userptr, "glStencilOp"); + context->StencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC) load(userptr, "glStencilOpSeparate"); + context->TexImage2D = (PFNGLTEXIMAGE2DPROC) load(userptr, "glTexImage2D"); + context->TexParameterf = (PFNGLTEXPARAMETERFPROC) load(userptr, "glTexParameterf"); + context->TexParameterfv = (PFNGLTEXPARAMETERFVPROC) load(userptr, "glTexParameterfv"); + context->TexParameteri = (PFNGLTEXPARAMETERIPROC) load(userptr, "glTexParameteri"); + context->TexParameteriv = (PFNGLTEXPARAMETERIVPROC) load(userptr, "glTexParameteriv"); + context->TexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC) load(userptr, "glTexSubImage2D"); + context->Uniform1f = (PFNGLUNIFORM1FPROC) load(userptr, "glUniform1f"); + context->Uniform1fv = (PFNGLUNIFORM1FVPROC) load(userptr, "glUniform1fv"); + context->Uniform1i = (PFNGLUNIFORM1IPROC) load(userptr, "glUniform1i"); + context->Uniform1iv = (PFNGLUNIFORM1IVPROC) load(userptr, "glUniform1iv"); + context->Uniform2f = (PFNGLUNIFORM2FPROC) load(userptr, "glUniform2f"); + context->Uniform2fv = (PFNGLUNIFORM2FVPROC) load(userptr, "glUniform2fv"); + context->Uniform2i = (PFNGLUNIFORM2IPROC) load(userptr, "glUniform2i"); + context->Uniform2iv = (PFNGLUNIFORM2IVPROC) load(userptr, "glUniform2iv"); + context->Uniform3f = (PFNGLUNIFORM3FPROC) load(userptr, "glUniform3f"); + context->Uniform3fv = (PFNGLUNIFORM3FVPROC) load(userptr, "glUniform3fv"); + context->Uniform3i = (PFNGLUNIFORM3IPROC) load(userptr, "glUniform3i"); + context->Uniform3iv = (PFNGLUNIFORM3IVPROC) load(userptr, "glUniform3iv"); + context->Uniform4f = (PFNGLUNIFORM4FPROC) load(userptr, "glUniform4f"); + context->Uniform4fv = (PFNGLUNIFORM4FVPROC) load(userptr, "glUniform4fv"); + context->Uniform4i = (PFNGLUNIFORM4IPROC) load(userptr, "glUniform4i"); + context->Uniform4iv = (PFNGLUNIFORM4IVPROC) load(userptr, "glUniform4iv"); + context->UniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC) load(userptr, "glUniformMatrix2fv"); + context->UniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC) load(userptr, "glUniformMatrix3fv"); + context->UniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) load(userptr, "glUniformMatrix4fv"); + context->UseProgram = (PFNGLUSEPROGRAMPROC) load(userptr, "glUseProgram"); + context->ValidateProgram = (PFNGLVALIDATEPROGRAMPROC) load(userptr, "glValidateProgram"); + context->VertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC) load(userptr, "glVertexAttrib1f"); + context->VertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC) load(userptr, "glVertexAttrib1fv"); + context->VertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC) load(userptr, "glVertexAttrib2f"); + context->VertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC) load(userptr, "glVertexAttrib2fv"); + context->VertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC) load(userptr, "glVertexAttrib3f"); + context->VertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC) load(userptr, "glVertexAttrib3fv"); + context->VertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC) load(userptr, "glVertexAttrib4f"); + context->VertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC) load(userptr, "glVertexAttrib4fv"); + context->VertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) load(userptr, "glVertexAttribPointer"); + context->Viewport = (PFNGLVIEWPORTPROC) load(userptr, "glViewport"); +} + + +static void glad_gl_resolve_aliases(GladGLES2Context *context) { +} + +#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0) +#define GLAD_GL_IS_SOME_NEW_VERSION 1 +#else +#define GLAD_GL_IS_SOME_NEW_VERSION 0 +#endif + +static int glad_gl_get_extensions(GladGLES2Context *context, int version, const char **out_exts, unsigned int *out_num_exts_i, char ***out_exts_i) { +#if GLAD_GL_IS_SOME_NEW_VERSION + if(GLAD_VERSION_MAJOR(version) < 3) { +#else + GLAD_UNUSED(version); + GLAD_UNUSED(out_num_exts_i); + GLAD_UNUSED(out_exts_i); +#endif + if (context->GetString == NULL) { + return 0; + } + *out_exts = (const char *)context->GetString(GL_EXTENSIONS); +#if GLAD_GL_IS_SOME_NEW_VERSION + } else { + unsigned int index = 0; + unsigned int num_exts_i = 0; + char **exts_i = NULL; + if (context->GetStringi == NULL || context->GetIntegerv == NULL) { + return 0; + } + context->GetIntegerv(GL_NUM_EXTENSIONS, (int*) &num_exts_i); + if (num_exts_i > 0) { + exts_i = (char **) malloc(num_exts_i * (sizeof *exts_i)); + } + if (exts_i == NULL) { + return 0; + } + for(index = 0; index < num_exts_i; index++) { + const char *gl_str_tmp = (const char*) context->GetStringi(GL_EXTENSIONS, index); + size_t len = strlen(gl_str_tmp) + 1; + + char *local_str = (char*) malloc(len * sizeof(char)); + if(local_str != NULL) { + memcpy(local_str, gl_str_tmp, len * sizeof(char)); + } + + exts_i[index] = local_str; + } + + *out_num_exts_i = num_exts_i; + *out_exts_i = exts_i; + } +#endif + return 1; +} +static void glad_gl_free_extensions(char **exts_i, unsigned int num_exts_i) { + if (exts_i != NULL) { + unsigned int index; + for(index = 0; index < num_exts_i; index++) { + free((void *) (exts_i[index])); + } + free((void *)exts_i); + exts_i = NULL; + } +} +static int glad_gl_has_extension(int version, const char *exts, unsigned int num_exts_i, char **exts_i, const char *ext) { + if(GLAD_VERSION_MAJOR(version) < 3 || !GLAD_GL_IS_SOME_NEW_VERSION) { + const char *extensions; + const char *loc; + const char *terminator; + extensions = exts; + if(extensions == NULL || ext == NULL) { + return 0; + } + while(1) { + loc = strstr(extensions, ext); + if(loc == NULL) { + return 0; + } + terminator = loc + strlen(ext); + if((loc == extensions || *(loc - 1) == ' ') && + (*terminator == ' ' || *terminator == '\0')) { + return 1; + } + extensions = terminator; + } + } else { + unsigned int index; + for(index = 0; index < num_exts_i; index++) { + const char *e = exts_i[index]; + if(strcmp(e, ext) == 0) { + return 1; + } + } + } + return 0; +} + +static GLADapiproc glad_gl_get_proc_from_userptr(void *userptr, const char* name) { + return (GLAD_GNUC_EXTENSION (GLADapiproc (*)(const char *name)) userptr)(name); +} + +static int glad_gl_find_extensions_gles2(GladGLES2Context *context, int version) { + const char *exts = NULL; + unsigned int num_exts_i = 0; + char **exts_i = NULL; + if (!glad_gl_get_extensions(context, version, &exts, &num_exts_i, &exts_i)) return 0; + + context->OES_rgb8_rgba8 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_rgb8_rgba8"); + + glad_gl_free_extensions(exts_i, num_exts_i); + + return 1; +} + +static int glad_gl_find_core_gles2(GladGLES2Context *context) { + int i; + const char* version; + const char* prefixes[] = { + "OpenGL ES-CM ", + "OpenGL ES-CL ", + "OpenGL ES ", + "OpenGL SC ", + NULL + }; + int major = 0; + int minor = 0; + version = (const char*) context->GetString(GL_VERSION); + if (!version) return 0; + for (i = 0; prefixes[i]; i++) { + const size_t length = strlen(prefixes[i]); + if (strncmp(version, prefixes[i], length) == 0) { + version += length; + break; + } + } + + GLAD_IMPL_UTIL_SSCANF(version, "%d.%d", &major, &minor); + + context->ES_VERSION_2_0 = (major == 2 && minor >= 0) || major > 2; + + return GLAD_MAKE_VERSION(major, minor); +} + +int gladLoadGLES2ContextUserPtr(GladGLES2Context *context, GLADuserptrloadfunc load, void *userptr) { + int version; + + context->GetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString"); + if(context->GetString == NULL) return 0; + if(context->GetString(GL_VERSION) == NULL) return 0; + version = glad_gl_find_core_gles2(context); + + glad_gl_load_GL_ES_VERSION_2_0(context, load, userptr); + + if (!glad_gl_find_extensions_gles2(context, version)) return 0; + + + glad_gl_resolve_aliases(context); + + return version; +} + + +int gladLoadGLES2Context(GladGLES2Context *context, GLADloadfunc load) { + return gladLoadGLES2ContextUserPtr(context, glad_gl_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load); +} + + + + + + +#ifdef __cplusplus +} +#endif diff --git a/thirdparty/imgui_config/srb2_imconfig.h b/thirdparty/imgui_config/srb2_imconfig.h new file mode 100644 index 000000000..5c09001b2 --- /dev/null +++ b/thirdparty/imgui_config/srb2_imconfig.h @@ -0,0 +1,38 @@ +#ifndef __SRB2_IMCONFIG_H__ +#define __SRB2_IMCONFIG_H__ + +#include + +#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS +#define IMGUI_DISABLE_OBSOLETE_KEYIO + +// We provide needed functionalities provided by default win32 impls through the interface layer +#define IMGUI_DISABLE_WIN32_FUNCTIONS + +// RHI Handles are essentially 64-bit integers +#define ImTextureID uint64_t + +// RHI does not support integer vectors +#define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT \ +struct ImVec3 \ +{ \ + float x, y, z; \ + constexpr ImVec3() : x(0.0f), y(0.0f), z(0.0f) { } \ + constexpr ImVec3(float _x, float _y) : x(_x), y(_y), z(0.0f) { } \ + constexpr ImVec3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) { } \ + constexpr ImVec3(const ImVec2& rhs) : x(rhs.x), y(rhs.y), z(0.f) { } \ + ImVec3& operator=(const ImVec2& rhs) { x = rhs.x; y = rhs.y; return *this; } \ + operator ImVec2() const { return ImVec2(x, y); } \ + float operator[](size_t index) const { switch (index) {case 0: return x; case 1: return y; case 2: return z; default: return 0.f;} } \ + float operator[](size_t index) { switch (index) {case 0: return x; case 1: return y; case 2: return z; default: return 0.f;} } \ + \ +}; \ +struct ImDrawVert \ +{ \ + ImVec3 pos; \ + ImVec2 uv; \ + ImU32 col; \ + float colf[4]; \ +}; + +#endif // __SRB2_IMCONFIG_H__ From 286c96173a6e97f5184f695b70fbd48b552f7370 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sat, 14 Jan 2023 19:29:19 -0600 Subject: [PATCH 18/32] hwr2 gl3core: Implement render pass FBOs --- src/rhi/gl3_core/gl3_core_rhi.cpp | 135 +++++++++++++++++++----------- 1 file changed, 86 insertions(+), 49 deletions(-) diff --git a/src/rhi/gl3_core/gl3_core_rhi.cpp b/src/rhi/gl3_core/gl3_core_rhi.cpp index f80667470..55e77fe00 100644 --- a/src/rhi/gl3_core/gl3_core_rhi.cpp +++ b/src/rhi/gl3_core/gl3_core_rhi.cpp @@ -948,14 +948,14 @@ void GlCoreRhi::begin_default_render_pass(Handle ctx, bool clea const Rect fb_rect = platform_->get_default_framebuffer_dimensions(); gl_->BindFramebuffer(GL_FRAMEBUFFER, 0); GL_ASSERT - gl_->Disable(GL_SCISSOR_TEST); + gl_->Disable(GL_SCISSOR_TEST); GL_ASSERT gl_->Viewport(0, 0, fb_rect.w, fb_rect.h); GL_ASSERT if (clear) { - gl_->ClearColor(0.0f, 0.0f, 0.0f, 1.0f); GL_ASSERT - gl_->ClearDepth(1.0f); GL_ASSERT - gl_->ClearStencil(0); GL_ASSERT + gl_->ClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl_->ClearDepth(1.0f); + gl_->ClearStencil(0); gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GL_ASSERT } @@ -974,22 +974,53 @@ void GlCoreRhi::begin_render_pass(Handle ctx, const RenderPassB if (fb_itr == framebuffers_.end()) { // Create a new framebuffer for this color-depth pair GLuint fb_name; - gl_->GenFramebuffers(1, &fb_name); - gl_->BindFramebuffer(GL_FRAMEBUFFER, fb_name); + gl_->GenFramebuffers(1, &fb_name); GL_ASSERT + gl_->BindFramebuffer(GL_FRAMEBUFFER, fb_name); GL_ASSERT fb_itr = framebuffers_.insert( {GlCoreFramebufferKey {info.color_attachment, info.depth_attachment}, static_cast(fb_name)}).first; - // TODO bind buffers correctly + GLuint attachment = GL_COLOR_ATTACHMENT0; + auto visitor = srb2::Overload { + [&, this](const Handle& handle) + { + SRB2_ASSERT(texture_slab_.is_valid(handle)); + auto& texture = *static_cast(&texture_slab_[handle]); + gl_->FramebufferTexture2D( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + texture.texture, + 0 + ); GL_ASSERT + }, + [&, this](const Handle& handle) + { + SRB2_ASSERT(renderbuffer_slab_.is_valid(handle)); + auto& renderbuffer = *static_cast(&renderbuffer_slab_[handle]); + gl_->FramebufferRenderbuffer( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, + renderbuffer.renderbuffer + ); GL_ASSERT + } + }; + std::visit(visitor, info.color_attachment); + if (info.depth_attachment) + { + attachment = GL_DEPTH_ATTACHMENT; + std::visit(visitor, *info.depth_attachment); + } } auto& fb = *fb_itr; - gl_->BindFramebuffer(GL_FRAMEBUFFER, fb.second); - gl_->Disable(GL_SCISSOR_TEST); + gl_->BindFramebuffer(GL_FRAMEBUFFER, fb.second); GL_ASSERT + gl_->Disable(GL_SCISSOR_TEST); GL_ASSERT if (rp.desc.load_op == rhi::AttachmentLoadOp::kClear) { gl_->ClearColor(info.clear_color.r, info.clear_color.g, info.clear_color.b, info.clear_color.a); gl_->ClearDepth(1.f); gl_->ClearStencil(0); - gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); GL_ASSERT } current_render_pass_ = info; @@ -1091,46 +1122,45 @@ void GlCoreRhi::bind_uniform_set(Handle ctx, uint32_t slot, Han SRB2_ASSERT(pl.uniform_locations.find(uniform_name) != pl.uniform_locations.end()); GLuint pipeline_uniform = pl.uniform_locations[uniform_name]; - struct UniformVariantVisitor { - GladGLContext* gl_; - rhi::UniformName name; - GLuint uniform; - - void operator()(const float& value) const noexcept { - gl_->Uniform1f(uniform, value); GL_ASSERT - } - void operator()(const std::array& value) const noexcept { - gl_->Uniform2f(uniform, value[0], value[1]); GL_ASSERT - } - void operator()(const std::array& value) const noexcept { - gl_->Uniform3f(uniform, value[0], value[1], value[2]); GL_ASSERT - } - void operator()(const std::array& value) const noexcept { - gl_->Uniform4f(uniform, value[0], value[1], value[2], value[3]); GL_ASSERT - } - void operator()(const int32_t& value) const noexcept { - gl_->Uniform1i(uniform, value); GL_ASSERT - } - void operator()(const std::array& value) const noexcept { - gl_->Uniform2i(uniform, value[0], value[1]); GL_ASSERT - } - void operator()(const std::array& value) const noexcept { - gl_->Uniform3i(uniform, value[0], value[1], value[2]); GL_ASSERT - } - void operator()(const std::array& value) const noexcept { - gl_->Uniform4i(uniform, value[0], value[1], value[2], value[3]); GL_ASSERT - } - void operator()(const std::array, 2>& value) const noexcept { - gl_->UniformMatrix2fv(uniform, 1, false, reinterpret_cast(&value)); GL_ASSERT - } - void operator()(const std::array, 3>& value) const noexcept { - gl_->UniformMatrix3fv(uniform, 1, false, reinterpret_cast(&value)); GL_ASSERT - } - void operator()(const std::array, 4>& value) const noexcept { - gl_->UniformMatrix4fv(uniform, 1, false, reinterpret_cast(&value)); GL_ASSERT - } + auto visitor = srb2::Overload + { + [&](const float& value){ gl_->Uniform1f(pipeline_uniform, value); GL_ASSERT }, + [&](const std::array& value) { gl_->Uniform2f(pipeline_uniform, value[0], value[1]); GL_ASSERT }, + [&](const std::array& value) + { + gl_->Uniform3f(pipeline_uniform, value[0], value[1], value[2]); GL_ASSERT + }, + [&](const std::array& value) + { + gl_->Uniform4f(pipeline_uniform, value[0], value[1], value[2], value[3]); GL_ASSERT + }, + [&](const int32_t& value) { gl_->Uniform1i(pipeline_uniform, value); GL_ASSERT }, + [&](const std::array& value) + { + gl_->Uniform2i(pipeline_uniform, value[0], value[1]); GL_ASSERT + }, + [&](const std::array& value) + { + gl_->Uniform3i(pipeline_uniform, value[0], value[1], value[2]); GL_ASSERT + }, + [&](const std::array& value) + { + gl_->Uniform4i(pipeline_uniform, value[0], value[1], value[2], value[3]); GL_ASSERT + }, + [&](const std::array, 2>& value) + { + gl_->UniformMatrix2fv(pipeline_uniform, 1, false, reinterpret_cast(&value)); GL_ASSERT + }, + [&](const std::array, 3>& value) + { + gl_->UniformMatrix3fv(pipeline_uniform, 1, false, reinterpret_cast(&value)); GL_ASSERT + }, + [&](const std::array, 4>& value) + { + gl_->UniformMatrix4fv(pipeline_uniform, 1, false, reinterpret_cast(&value)); GL_ASSERT + }, }; - std::visit(UniformVariantVisitor {gl_.get(), uniform_name, pipeline_uniform}, update_data); + std::visit(visitor, update_data); } } @@ -1251,6 +1281,13 @@ void GlCoreRhi::finish() { binding_set_slab_.clear(); uniform_set_slab_.clear(); + // I sure hope creating FBOs isn't costly on the driver! + for (auto& fbset : framebuffers_) + { + gl_->DeleteFramebuffers(1, &fbset.second); + } + framebuffers_.clear(); + for (auto it = disposal_.begin(); it != disposal_.end(); it++) { (*it)(); From b932607359fd9993a9c69cb02fcc5fae4bca1a3b Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sat, 14 Jan 2023 19:52:10 -0600 Subject: [PATCH 19/32] hwr2: Remove sw testing state from sdl video --- src/sdl/i_video.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/sdl/i_video.cpp b/src/sdl/i_video.cpp index dd5003fba..4a30c7bf9 100644 --- a/src/sdl/i_video.cpp +++ b/src/sdl/i_video.cpp @@ -152,17 +152,8 @@ SDL_Window *window; static SDL_bool havefocus = SDL_TRUE; static const char *fallback_resolution_name = "Fallback"; -struct RhiSwState { - rhi::Handle g_sw_palette_pipeline; - rhi::Handle g_sw_screen_texture; - rhi::Handle g_palette_texture; - rhi::Handle g_quad_vb; - rhi::Handle g_quad_ib; -}; - static std::unique_ptr g_rhi; static uint32_t g_rhi_generation = 0; -static RhiSwState g_rhi_sw_state; // windowed video modes from which to choose from. static INT32 windowedModes[MAXWINMODES][2] = From fcb4dfe3d77773c9cf147450f1b5f31555150e03 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sat, 14 Jan 2023 19:52:33 -0600 Subject: [PATCH 20/32] hwr2: Restore legacy OpenGL temporarily --- src/i_video_common.cpp | 11 ++ src/sdl/i_video.cpp | 237 ++++++++++++++++++++++++++++++++++++----- src/sdl/ogl_sdl.h | 2 + 3 files changed, 223 insertions(+), 27 deletions(-) diff --git a/src/i_video_common.cpp b/src/i_video_common.cpp index cd99ed618..3e9dabaa0 100644 --- a/src/i_video_common.cpp +++ b/src/i_video_common.cpp @@ -11,6 +11,9 @@ #include "hwr2/pass_imgui.hpp" #include "hwr2/pass_software.hpp" +// KILL THIS WHEN WE KILL OLD OGL SUPPORT PLEASE +#include "sdl/ogl_sdl.h" + using namespace srb2; using namespace srb2::hwr2; using namespace srb2::rhi; @@ -32,6 +35,14 @@ void I_FinishUpdate(void) return; } +#ifdef HWRENDER + if (rendermode == render_opengl) + { + OglSdlFinishUpdate(cv_vidwait.value); + return; + } +#endif + // TODO move this to srb2loop ImGuiIO& io = ImGui::GetIO(); io.DisplaySize.x = vid.realwidth; diff --git a/src/sdl/i_video.cpp b/src/sdl/i_video.cpp index 4a30c7bf9..f0feedaf5 100644 --- a/src/sdl/i_video.cpp +++ b/src/sdl/i_video.cpp @@ -226,6 +226,13 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_bool } } +#ifdef HWRENDER + if (rendermode == render_opengl) + { + OglSdlSurface(vid.width, vid.height); + } +#endif + SDL_GetWindowSize(window, &width, &height); vid.realwidth = static_cast(width); vid.realheight = static_cast(height); @@ -1256,6 +1263,12 @@ void I_UpdateNoBlit(void) return; if (exposevideo) { +#ifdef HWRENDER + if (rendermode == render_opengl) + { + OglSdlFinishUpdate(cv_vidwait.value); + } +#endif } exposevideo = SDL_FALSE; } @@ -1452,28 +1465,8 @@ void VID_PrepareModeList(void) #endif } -static SDL_bool Impl_CreateContext(void) +static void init_imgui() { - // RHI always uses OpenGL 3.2 Core (for now) - if (!sdlglcontext) - { - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); - sdlglcontext = SDL_GL_CreateContext(window); - } - if (sdlglcontext == NULL) - { - SDL_DestroyWindow(window); - I_Error("Failed to create a GL context: %s\n", SDL_GetError()); - } - SDL_GL_MakeCurrent(window, sdlglcontext); - - std::unique_ptr platform = std::make_unique(); - platform->window = window; - g_rhi = std::make_unique(std::move(platform), reinterpret_cast(SDL_GL_GetProcAddress)); - g_rhi_generation += 1; - ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; io.IniFilename = NULL; @@ -1487,6 +1480,46 @@ static SDL_bool Impl_CreateContext(void) io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); } ImGui::StyleColorsDark(); +} + +static SDL_bool Impl_CreateContext(void) +{ +#ifdef HWRENDER + if (rendermode == render_opengl) + { + if (!sdlglcontext) + sdlglcontext = SDL_GL_CreateContext(window); + if (sdlglcontext == NULL) + { + SDL_DestroyWindow(window); + I_Error("Failed to create a GL context: %s\n", SDL_GetError()); + } + init_imgui(); + SDL_GL_MakeCurrent(window, sdlglcontext); + return SDL_TRUE; + } +#endif + + // RHI always uses OpenGL 3.2 Core (for now) + if (!sdlglcontext) + { + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); + sdlglcontext = SDL_GL_CreateContext(window); + } + if (sdlglcontext == NULL) + { + SDL_DestroyWindow(window); + I_Error("Failed to create a GL context: %s\n", SDL_GetError()); + } + init_imgui(); + SDL_GL_MakeCurrent(window, sdlglcontext); + + std::unique_ptr platform = std::make_unique(); + platform->window = window; + g_rhi = std::make_unique(std::move(platform), reinterpret_cast(SDL_GL_GetProcAddress)); + g_rhi_generation += 1; return SDL_TRUE; } @@ -1514,6 +1547,9 @@ boolean VID_CheckRenderer(void) { boolean rendererchanged = false; boolean contextcreated = false; +#ifdef HWRENDER + rendermode_t oldrenderer = rendermode; +#endif if (dedicated) return false; @@ -1523,6 +1559,39 @@ boolean VID_CheckRenderer(void) rendermode = static_cast(setrenderneeded); rendererchanged = true; +#ifdef HWRENDER + if (rendermode == render_opengl) + { + VID_CheckGLLoaded(oldrenderer); + + // Initialise OpenGL before calling SDLSetMode!!! + // This is because SDLSetMode calls OglSdlSurface. + if (vid.glstate == VID_GL_LIBRARY_NOTLOADED) + { + VID_StartupOpenGL(); + + // Loaded successfully! + if (vid.glstate == VID_GL_LIBRARY_LOADED) + { + // Destroy the current window, if it exists. + if (window) + { + SDL_DestroyWindow(window); + window = NULL; + } + + // Create a new window. + Impl_CreateWindow(static_cast(USE_FULLSCREEN)); + + // From there, the OpenGL context was already created. + contextcreated = true; + } + } + else if (vid.glstate == VID_GL_LIBRARY_ERROR) + rendererchanged = false; + } +#endif + if (!contextcreated) Impl_CreateContext(); @@ -1536,6 +1605,13 @@ boolean VID_CheckRenderer(void) { SCR_SetDrawFuncs(); } +#ifdef HWRENDER + else if (rendermode == render_opengl && rendererchanged) + { + HWR_Switch(); + V_SetPalette(0); + } +#endif return rendererchanged; } @@ -1664,14 +1740,63 @@ void I_StartupGraphics(void) keyboard_started = true; - // TEMPORARY OVERRIDES FOR RHI - SOFTWARE ONLY - chosenrendermode = render_soft; - rendermode = render_soft; +#if !defined(HAVE_TTF) + // Previously audio was init here for questionable reasons? + if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) + { + CONS_Printf(M_GetText("Couldn't initialize SDL's Video System: %s\n"), SDL_GetError()); + return; + } +#endif + + // Renderer choices + // Takes priority over the config. + if (M_CheckParm("-renderer")) + { + INT32 i = 0; + CV_PossibleValue_t *renderer_list = cv_renderer_t; + const char *modeparm = M_GetNextParm(); + while (renderer_list[i].strvalue) + { + if (!stricmp(modeparm, renderer_list[i].strvalue)) + { + chosenrendermode = static_cast(renderer_list[i].value); + break; + } + i++; + } + } + + // Choose Software renderer + else if (M_CheckParm("-software")) + chosenrendermode = render_soft; + +#ifdef HWRENDER + // Choose OpenGL renderer + else if (M_CheckParm("-opengl")) + chosenrendermode = render_opengl; + + // Don't startup OpenGL + if (M_CheckParm("-nogl")) + { + vid.glstate = VID_GL_LIBRARY_ERROR; + if (chosenrendermode == render_opengl) + chosenrendermode = render_none; + } +#endif + + if (chosenrendermode != render_none) + rendermode = chosenrendermode; borderlesswindow = M_CheckParm("-borderless") ? SDL_TRUE : SDL_FALSE; VID_Command_ModeList_f(); +#ifdef HWRENDER + if (rendermode == render_opengl) + VID_StartupOpenGL(); +#endif + VID_SetMode(VID_GetModeForSize(BASEVIDWIDTH, BASEVIDHEIGHT)); vid.width = BASEVIDWIDTH; // Default size for startup @@ -1701,9 +1826,59 @@ void I_StartupGraphics(void) void VID_StartupOpenGL(void) { - CONS_Alert(CONS_WARNING, "VID_StartupOpenGL called (no longer going to use)"); - rendermode = render_soft; - setrenderneeded = 0; +#ifdef HWRENDER + static boolean glstartup = false; + if (!glstartup) + { + CONS_Printf("VID_StartupOpenGL()...\n"); + *(void**)&HWD.pfnInit = hwSym("Init",NULL); + *(void**)&HWD.pfnFinishUpdate = NULL; + *(void**)&HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL); + *(void**)&HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL); + *(void**)&HWD.pfnDrawIndexedTriangles = hwSym("DrawIndexedTriangles",NULL); + *(void**)&HWD.pfnRenderSkyDome = hwSym("RenderSkyDome",NULL); + *(void**)&HWD.pfnSetBlend = hwSym("SetBlend",NULL); + *(void**)&HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); + *(void**)&HWD.pfnSetTexture = hwSym("SetTexture",NULL); + *(void**)&HWD.pfnUpdateTexture = hwSym("UpdateTexture",NULL); + *(void**)&HWD.pfnDeleteTexture = hwSym("DeleteTexture",NULL); + *(void**)&HWD.pfnReadRect = hwSym("ReadRect",NULL); + *(void**)&HWD.pfnGClipRect = hwSym("GClipRect",NULL); + *(void**)&HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); + *(void**)&HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL); + *(void**)&HWD.pfnSetPalette = hwSym("SetPalette",NULL); + *(void**)&HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL); + *(void**)&HWD.pfnDrawModel = hwSym("DrawModel",NULL); + *(void**)&HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL); + *(void**)&HWD.pfnSetTransform = hwSym("SetTransform",NULL); + *(void**)&HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); + *(void**)&HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL); + *(void**)&HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL); + *(void**)&HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL); + *(void**)&HWD.pfnDoScreenWipe = hwSym("DoScreenWipe",NULL); + *(void**)&HWD.pfnDrawIntermissionBG=hwSym("DrawIntermissionBG",NULL); + *(void**)&HWD.pfnMakeScreenTexture= hwSym("MakeScreenTexture",NULL); + *(void**)&HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL); + *(void**)&HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL); + + *(void**)&HWD.pfnCompileShaders = hwSym("CompileShaders",NULL); + *(void**)&HWD.pfnCleanShaders = hwSym("CleanShaders",NULL); + *(void**)&HWD.pfnSetShader = hwSym("SetShader",NULL); + *(void**)&HWD.pfnUnSetShader = hwSym("UnSetShader",NULL); + + *(void**)&HWD.pfnSetShaderInfo = hwSym("SetShaderInfo",NULL); + *(void**)&HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL); + + vid.glstate = HWD.pfnInit() ? VID_GL_LIBRARY_LOADED : VID_GL_LIBRARY_ERROR; // let load the OpenGL library + + if (vid.glstate == VID_GL_LIBRARY_ERROR) + { + rendermode = render_soft; + setrenderneeded = 0; + } + glstartup = true; + } +#endif } void I_ShutdownGraphics(void) @@ -1721,6 +1896,14 @@ void I_ShutdownGraphics(void) } graphics_started = false; +#ifdef HWRENDER + if (GLUhandle) + hwClose(GLUhandle); + if (sdlglcontext) + { + SDL_GL_DeleteContext(sdlglcontext); + } +#endif SDL_QuitSubSystem(SDL_INIT_VIDEO); framebuffer = SDL_FALSE; } diff --git a/src/sdl/ogl_sdl.h b/src/sdl/ogl_sdl.h index 8b60b6242..26cedf0ae 100644 --- a/src/sdl/ogl_sdl.h +++ b/src/sdl/ogl_sdl.h @@ -20,6 +20,8 @@ #ifndef __SDL_OGL_SDL_H__ #define __SDL_OGL_SDL_H__ +#include + #include "../v_video.h" #ifdef __cplusplus From ccc10eadd0f1421a2d6dd24a75007ff6213a5511 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sat, 14 Jan 2023 19:59:41 -0600 Subject: [PATCH 21/32] hwr2: Reformat C++ code --- src/core/static_vec.hpp | 112 ++--- src/i_video_common.cpp | 2 +- src/rhi/gl3_core/gl3_core_rhi.cpp | 658 ++++++++++++++++++++---------- src/rhi/gl3_core/gl3_core_rhi.hpp | 71 ++-- src/rhi/gles2/gles2_rhi.cpp | 468 ++++++++++++++------- src/rhi/gles2/gles2_rhi.hpp | 66 +-- src/rhi/handle.hpp | 137 ++++--- src/rhi/rhi.cpp | 48 +-- src/rhi/rhi.hpp | 224 +++++++--- src/sdl/rhi_gl3_core_platform.cpp | 12 +- src/sdl/rhi_gl3_core_platform.hpp | 8 +- src/sdl/rhi_gles2_platform.cpp | 12 +- src/sdl/rhi_gles2_platform.hpp | 8 +- 13 files changed, 1157 insertions(+), 669 deletions(-) diff --git a/src/core/static_vec.hpp b/src/core/static_vec.hpp index f7bd26d69..823469649 100644 --- a/src/core/static_vec.hpp +++ b/src/core/static_vec.hpp @@ -5,14 +5,15 @@ #include #include #include -#include #include +#include #include #include #include "../cxxutil.hpp" -namespace srb2 { +namespace srb2 +{ template class StaticVec @@ -98,15 +99,9 @@ public: return *this; } - void push_back(const T& value) - { - arr_[size_++] = value; - } + void push_back(const T& value) { arr_[size_++] = value; } - void pop_back() - { - arr_[size_--] = T(); - } + void pop_back() { arr_[size_--] = T(); } void resize(size_t size, T value = T()) { @@ -135,80 +130,35 @@ public: } } - constexpr T* begin() noexcept - { - return &arr_[0]; - } + constexpr T* begin() noexcept { return &arr_[0]; } - constexpr const T* begin() const noexcept - { - return cbegin(); - } + constexpr const T* begin() const noexcept { return cbegin(); } - constexpr const T* cbegin() const noexcept - { - return &arr_[0]; - } + constexpr const T* cbegin() const noexcept { return &arr_[0]; } - constexpr T* end() noexcept - { - return &arr_[size_]; - } + constexpr T* end() noexcept { return &arr_[size_]; } - constexpr const T* end() const noexcept - { - return cend(); - } + constexpr const T* end() const noexcept { return cend(); } - constexpr const T* cend() const noexcept - { - return &arr_[size_]; - } + constexpr const T* cend() const noexcept { return &arr_[size_]; } - constexpr std::reverse_iterator rbegin() noexcept - { - return &arr_[size_]; - } + constexpr std::reverse_iterator rbegin() noexcept { return &arr_[size_]; } - constexpr std::reverse_iterator crbegin() const noexcept - { - return &arr_[size_]; - } + constexpr std::reverse_iterator crbegin() const noexcept { return &arr_[size_]; } - constexpr std::reverse_iterator rend() noexcept - { - return &arr_[0]; - } + constexpr std::reverse_iterator rend() noexcept { return &arr_[0]; } - constexpr std::reverse_iterator crend() const noexcept - { - return &arr_[0]; - } + constexpr std::reverse_iterator crend() const noexcept { return &arr_[0]; } - constexpr bool empty() const noexcept - { - return size_ == 0; - } + constexpr bool empty() const noexcept { return size_ == 0; } - constexpr size_t size() const noexcept - { - return size_; - } + constexpr size_t size() const noexcept { return size_; } - constexpr size_t capacity() const noexcept - { - return Limit; - } + constexpr size_t capacity() const noexcept { return Limit; } - constexpr size_t max_size() const noexcept - { - return Limit; - } + constexpr size_t max_size() const noexcept { return Limit; } - constexpr T& operator[](size_t index) noexcept - { - return arr_[index]; - } + constexpr T& operator[](size_t index) noexcept { return arr_[index]; } T& at(size_t index) { @@ -219,10 +169,7 @@ public: return this[index]; } - constexpr const T& operator[](size_t index) const noexcept - { - return arr_[index]; - } + constexpr const T& operator[](size_t index) const noexcept { return arr_[index]; } const T& at(size_t index) const { @@ -233,15 +180,9 @@ public: return this[index]; } - T& front() - { - return *arr_[0]; - } + T& front() { return *arr_[0]; } - T& back() - { - return *arr_[size_ - 1]; - } + T& back() { return *arr_[size_ - 1]; } }; } // namespace srb2 @@ -254,7 +195,8 @@ bool operator==(const srb2::StaticVec& lhs, const srb2::StaticVec& { return false; } - for (size_t i = 0; i < lhs; i++) { + for (size_t i = 0; i < lhs; i++) + { if (rhs[i] != lhs[i]) { return false; @@ -274,8 +216,8 @@ struct std::hash> { uint64_t operator()(const srb2::StaticVec& input) const { - constexpr const uint64_t prime { 0x00000100000001B3 }; - std::size_t ret { 0xcbf29ce484222325 }; + constexpr const uint64_t prime {0x00000100000001B3}; + std::size_t ret {0xcbf29ce484222325}; for (auto itr = input.begin(); itr != input.end(); itr++) { diff --git a/src/i_video_common.cpp b/src/i_video_common.cpp index 3e9dabaa0..d80818e9f 100644 --- a/src/i_video_common.cpp +++ b/src/i_video_common.cpp @@ -7,9 +7,9 @@ #include #include "cxxutil.hpp" -#include "v_video.h" #include "hwr2/pass_imgui.hpp" #include "hwr2/pass_software.hpp" +#include "v_video.h" // KILL THIS WHEN WE KILL OLD OGL SUPPORT PLEASE #include "sdl/ogl_sdl.h" diff --git a/src/rhi/gl3_core/gl3_core_rhi.cpp b/src/rhi/gl3_core/gl3_core_rhi.cpp index 55e77fe00..55d9b3948 100644 --- a/src/rhi/gl3_core/gl3_core_rhi.cpp +++ b/src/rhi/gl3_core/gl3_core_rhi.cpp @@ -16,21 +16,32 @@ using srb2::rhi::GlCorePlatform; using srb2::rhi::GlCoreRhi; #if 1 -#define GL_ASSERT {GLenum __err = gl_->GetError(); if (__err != GL_NO_ERROR) { I_Error("GL Error at %s %d: %d", __FILE__, __LINE__, __err); }} +#define GL_ASSERT \ + { \ + GLenum __err = gl_->GetError(); \ + if (__err != GL_NO_ERROR) \ + { \ + I_Error("GL Error at %s %d: %d", __FILE__, __LINE__, __err); \ + } \ + } #else #define GL_ASSERT ; #endif -namespace { +namespace +{ template -std::unique_ptr> static_unique_ptr_cast(std::unique_ptr> ptr) { +std::unique_ptr> static_unique_ptr_cast(std::unique_ptr> ptr) +{ D* derived = static_cast(ptr.release()); return std::unique_ptr>(derived, std::default_delete()); } -constexpr GLenum map_pixel_format(rhi::PixelFormat format) { - switch (format) { +constexpr GLenum map_pixel_format(rhi::PixelFormat format) +{ + switch (format) + { case rhi::PixelFormat::kRGBA8: return GL_RGBA8; case rhi::PixelFormat::kDepth16: @@ -42,11 +53,13 @@ constexpr GLenum map_pixel_format(rhi::PixelFormat format) { } } -constexpr std::tuple map_pixel_data_format(rhi::PixelFormat format) { +constexpr std::tuple map_pixel_data_format(rhi::PixelFormat format) +{ GLenum layout = GL_ZERO; GLenum type = GL_ZERO; GLuint size = 0; - switch (format) { + switch (format) + { case rhi::PixelFormat::kR8: layout = GL_RED; type = GL_UNSIGNED_BYTE; @@ -63,8 +76,10 @@ constexpr std::tuple map_pixel_data_format(rhi::PixelFor return std::tuple(layout, type, size); } -constexpr GLenum map_texture_format(rhi::TextureFormat format) { - switch (format) { +constexpr GLenum map_texture_format(rhi::TextureFormat format) +{ + switch (format) + { case rhi::TextureFormat::kRGBA: return GL_RGBA; case rhi::TextureFormat::kRGB: @@ -76,8 +91,10 @@ constexpr GLenum map_texture_format(rhi::TextureFormat format) { } } -constexpr GLenum map_buffer_type(rhi::BufferType type) { - switch (type) { +constexpr GLenum map_buffer_type(rhi::BufferType type) +{ + switch (type) + { case rhi::BufferType::kVertexBuffer: return GL_ARRAY_BUFFER; case rhi::BufferType::kIndexBuffer: @@ -87,8 +104,10 @@ constexpr GLenum map_buffer_type(rhi::BufferType type) { } } -constexpr GLenum map_buffer_usage(rhi::BufferUsage usage) { - switch (usage) { +constexpr GLenum map_buffer_usage(rhi::BufferUsage usage) +{ + switch (usage) + { case rhi::BufferUsage::kImmutable: return GL_STATIC_DRAW; case rhi::BufferUsage::kDynamic: @@ -98,8 +117,10 @@ constexpr GLenum map_buffer_usage(rhi::BufferUsage usage) { } } -constexpr GLenum map_compare_func(rhi::CompareFunc func) { - switch (func) { +constexpr GLenum map_compare_func(rhi::CompareFunc func) +{ + switch (func) + { case rhi::CompareFunc::kNever: return GL_NEVER; case rhi::CompareFunc::kLess: @@ -121,8 +142,10 @@ constexpr GLenum map_compare_func(rhi::CompareFunc func) { } } -constexpr GLenum map_blend_factor(rhi::BlendFactor factor) { - switch (factor) { +constexpr GLenum map_blend_factor(rhi::BlendFactor factor) +{ + switch (factor) + { case rhi::BlendFactor::kZero: return GL_ZERO; case rhi::BlendFactor::kOne: @@ -158,8 +181,10 @@ constexpr GLenum map_blend_factor(rhi::BlendFactor factor) { } } -constexpr GLenum map_blend_function(rhi::BlendFunction function) { - switch (function) { +constexpr GLenum map_blend_function(rhi::BlendFunction function) +{ + switch (function) + { case rhi::BlendFunction::kAdd: return GL_FUNC_ADD; case rhi::BlendFunction::kSubtract: @@ -171,8 +196,10 @@ constexpr GLenum map_blend_function(rhi::BlendFunction function) { } } -constexpr GLenum map_cull_mode(rhi::CullMode mode) { - switch (mode) { +constexpr GLenum map_cull_mode(rhi::CullMode mode) +{ + switch (mode) + { case rhi::CullMode::kNone: return GL_NONE; case rhi::CullMode::kFront: @@ -184,8 +211,10 @@ constexpr GLenum map_cull_mode(rhi::CullMode mode) { } } -constexpr GLenum map_winding(rhi::FaceWinding winding) { - switch (winding) { +constexpr GLenum map_winding(rhi::FaceWinding winding) +{ + switch (winding) + { case rhi::FaceWinding::kCounterClockwise: return GL_CCW; case rhi::FaceWinding::kClockwise: @@ -195,8 +224,10 @@ constexpr GLenum map_winding(rhi::FaceWinding winding) { } } -constexpr GLenum map_primitive_mode(rhi::PrimitiveType type) { - switch (type) { +constexpr GLenum map_primitive_mode(rhi::PrimitiveType type) +{ + switch (type) + { case rhi::PrimitiveType::kPoints: return GL_POINTS; case rhi::PrimitiveType::kLines: @@ -214,8 +245,10 @@ constexpr GLenum map_primitive_mode(rhi::PrimitiveType type) { } } -constexpr const char* map_vertex_attribute_symbol_name(rhi::VertexAttributeName name) { - switch (name) { +constexpr const char* map_vertex_attribute_symbol_name(rhi::VertexAttributeName name) +{ + switch (name) + { case rhi::VertexAttributeName::kPosition: return "a_position"; case rhi::VertexAttributeName::kNormal: @@ -231,8 +264,10 @@ constexpr const char* map_vertex_attribute_symbol_name(rhi::VertexAttributeName } } -constexpr const char* map_vertex_attribute_enable_define(rhi::VertexAttributeName name) { - switch (name) { +constexpr const char* map_vertex_attribute_enable_define(rhi::VertexAttributeName name) +{ + switch (name) + { case rhi::VertexAttributeName::kPosition: return "ENABLE_VA_POSITION"; case rhi::VertexAttributeName::kNormal: @@ -248,8 +283,10 @@ constexpr const char* map_vertex_attribute_enable_define(rhi::VertexAttributeNam } } -constexpr const char* map_uniform_attribute_symbol_name(rhi::UniformName name) { - switch (name) { +constexpr const char* map_uniform_attribute_symbol_name(rhi::UniformName name) +{ + switch (name) + { case rhi::UniformName::kTime: return "u_time"; case rhi::UniformName::kModelView: @@ -263,8 +300,10 @@ constexpr const char* map_uniform_attribute_symbol_name(rhi::UniformName name) { } } -constexpr const char* map_sampler_symbol_name(rhi::SamplerName name) { - switch (name) { +constexpr const char* map_sampler_symbol_name(rhi::SamplerName name) +{ + switch (name) + { case rhi::SamplerName::kSampler0: return "s_sampler0"; case rhi::SamplerName::kSampler1: @@ -278,8 +317,10 @@ constexpr const char* map_sampler_symbol_name(rhi::SamplerName name) { } } -constexpr GLenum map_vertex_attribute_format(rhi::VertexAttributeFormat format) { - switch (format) { +constexpr GLenum map_vertex_attribute_format(rhi::VertexAttributeFormat format) +{ + switch (format) + { case rhi::VertexAttributeFormat::kFloat: return GL_FLOAT; case rhi::VertexAttributeFormat::kFloat2: @@ -293,8 +334,10 @@ constexpr GLenum map_vertex_attribute_format(rhi::VertexAttributeFormat format) } } -constexpr GLenum map_vertex_attribute_type(rhi::VertexAttributeFormat format) { - switch (format) { +constexpr GLenum map_vertex_attribute_type(rhi::VertexAttributeFormat format) +{ + switch (format) + { case rhi::VertexAttributeFormat::kFloat: return GL_FLOAT; case rhi::VertexAttributeFormat::kFloat2: @@ -308,8 +351,10 @@ constexpr GLenum map_vertex_attribute_type(rhi::VertexAttributeFormat format) { } } -constexpr GLint map_vertex_attribute_format_size(rhi::VertexAttributeFormat format) { - switch (format) { +constexpr GLint map_vertex_attribute_format_size(rhi::VertexAttributeFormat format) +{ + switch (format) + { case rhi::VertexAttributeFormat::kFloat: return 1; case rhi::VertexAttributeFormat::kFloat2: @@ -323,8 +368,10 @@ constexpr GLint map_vertex_attribute_format_size(rhi::VertexAttributeFormat form } } -constexpr GLenum map_uniform_format(rhi::UniformFormat format) { - switch (format) { +constexpr GLenum map_uniform_format(rhi::UniformFormat format) +{ + switch (format) + { case rhi::UniformFormat::kFloat: return GL_FLOAT; case rhi::UniformFormat::kFloat2: @@ -352,24 +399,28 @@ constexpr GLenum map_uniform_format(rhi::UniformFormat format) { } } -struct GlCoreTexture : public rhi::Texture { +struct GlCoreTexture : public rhi::Texture +{ GLuint texture; rhi::TextureDesc desc; GlCoreTexture(GLuint texture, const rhi::TextureDesc& desc) noexcept : texture(texture), desc(desc) {} }; -struct GlCoreBuffer : public rhi::Buffer { +struct GlCoreBuffer : public rhi::Buffer +{ GLuint buffer; rhi::BufferDesc desc; GlCoreBuffer(GLuint buffer, const rhi::BufferDesc& desc) noexcept : buffer(buffer), desc(desc) {} }; -struct GlCoreRenderPass : public rhi::RenderPass { +struct GlCoreRenderPass : public rhi::RenderPass +{ rhi::RenderPassDesc desc; explicit GlCoreRenderPass(const rhi::RenderPassDesc& desc) noexcept : desc(desc) {} }; -struct GlCoreRenderbuffer : public rhi::Renderbuffer { +struct GlCoreRenderbuffer : public rhi::Renderbuffer +{ GLuint renderbuffer; explicit GlCoreRenderbuffer(GLuint renderbuffer) noexcept : renderbuffer(renderbuffer) {} @@ -386,7 +437,8 @@ struct GlCoreBindingSet : public rhi::BindingSet std::unordered_map textures {4}; }; -struct GlCorePipeline : public rhi::Pipeline { +struct GlCorePipeline : public rhi::Pipeline +{ GLuint vertex_shader = 0; GLuint fragment_shader = 0; GLuint program = 0; @@ -396,11 +448,16 @@ struct GlCorePipeline : public rhi::Pipeline { rhi::PipelineDesc desc; }; -struct GlCoreGraphicsContext : public rhi::GraphicsContext {}; +struct GlCoreGraphicsContext : public rhi::GraphicsContext +{ +}; -struct GlCoreTransferContext : public rhi::TransferContext {}; +struct GlCoreTransferContext : public rhi::TransferContext +{ +}; -struct GlCoreActiveUniform { +struct GlCoreActiveUniform +{ GLenum type; GLuint location; }; @@ -409,29 +466,32 @@ struct GlCoreActiveUniform { GlCorePlatform::~GlCorePlatform() = default; -GlCoreRhi::GlCoreRhi(std::unique_ptr&& platform, GlLoadFunc load_func) - : platform_(std::move(platform)) { +GlCoreRhi::GlCoreRhi(std::unique_ptr&& platform, GlLoadFunc load_func) : platform_(std::move(platform)) +{ gl_ = std::make_unique(); gladLoadGLContext(gl_.get(), load_func); } GlCoreRhi::~GlCoreRhi() = default; -rhi::Handle GlCoreRhi::create_render_pass(const rhi::RenderPassDesc& desc) { +rhi::Handle GlCoreRhi::create_render_pass(const rhi::RenderPassDesc& desc) +{ SRB2_ASSERT(graphics_context_active_ == false); // GL has no formal render pass object return render_pass_slab_.insert(std::make_unique(desc)); } -void GlCoreRhi::destroy_render_pass(rhi::Handle handle) { +void GlCoreRhi::destroy_render_pass(rhi::Handle handle) +{ SRB2_ASSERT(graphics_context_active_ == false); std::unique_ptr buffer = render_pass_slab_.remove(handle); std::unique_ptr casted(static_cast(buffer.release())); } -rhi::Handle GlCoreRhi::create_texture(const rhi::TextureDesc& desc) { +rhi::Handle GlCoreRhi::create_texture(const rhi::TextureDesc& desc) +{ SRB2_ASSERT(graphics_context_active_ == false); GLenum internal_format = map_texture_format(desc.format); @@ -442,16 +502,22 @@ rhi::Handle GlCoreRhi::create_texture(const rhi::TextureDesc& desc gl_->BindTexture(GL_TEXTURE_2D, name); - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); GL_ASSERT - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); GL_ASSERT - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); GL_ASSERT - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); GL_ASSERT - gl_->TexImage2D(GL_TEXTURE_2D, 0, internal_format, desc.width, desc.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); GL_ASSERT + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + GL_ASSERT + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + GL_ASSERT + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + GL_ASSERT + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + GL_ASSERT + gl_->TexImage2D(GL_TEXTURE_2D, 0, internal_format, desc.width, desc.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + GL_ASSERT return texture_slab_.insert(std::make_unique(name, desc)); } -void GlCoreRhi::destroy_texture(rhi::Handle handle) { +void GlCoreRhi::destroy_texture(rhi::Handle handle) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(texture_slab_.is_valid(handle) == true); @@ -460,7 +526,14 @@ void GlCoreRhi::destroy_texture(rhi::Handle handle) { disposal_.push_back([this, name] { gl_->DeleteTextures(1, &name); }); } -void GlCoreRhi::update_texture(Handle ctx, Handle texture, Rect region, srb2::rhi::PixelFormat data_format, tcb::span data) { +void GlCoreRhi::update_texture( + Handle ctx, + Handle texture, + Rect region, + srb2::rhi::PixelFormat data_format, + tcb::span data +) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(transfer_context_active_ == true); SRB2_ASSERT(ctx.generation() == transfer_context_generation_); @@ -482,12 +555,26 @@ void GlCoreRhi::update_texture(Handle ctx, Handle text SRB2_ASSERT(region.w * region.h * size == data.size_bytes()); SRB2_ASSERT(region.x + region.w <= t.desc.width && region.y + region.h <= t.desc.height); - gl_->ActiveTexture(GL_TEXTURE0); GL_ASSERT - gl_->BindTexture(GL_TEXTURE_2D, t.texture); GL_ASSERT - gl_->TexSubImage2D(GL_TEXTURE_2D, 0, region.x, region.y, region.w, region.h, format, type, reinterpret_cast(data.data())); GL_ASSERT + gl_->ActiveTexture(GL_TEXTURE0); + GL_ASSERT + gl_->BindTexture(GL_TEXTURE_2D, t.texture); + GL_ASSERT + gl_->TexSubImage2D( + GL_TEXTURE_2D, + 0, + region.x, + region.y, + region.w, + region.h, + format, + type, + reinterpret_cast(data.data()) + ); + GL_ASSERT } -rhi::Handle GlCoreRhi::create_buffer(const rhi::BufferDesc& desc) { +rhi::Handle GlCoreRhi::create_buffer(const rhi::BufferDesc& desc) +{ SRB2_ASSERT(graphics_context_active_ == false); GLenum target = map_buffer_type(desc.type); @@ -497,16 +584,20 @@ rhi::Handle GlCoreRhi::create_buffer(const rhi::BufferDesc& desc) { SRB2_ASSERT(usage != GL_ZERO); GLuint name = 0; - gl_->GenBuffers(1, &name); GL_ASSERT + gl_->GenBuffers(1, &name); + GL_ASSERT - gl_->BindBuffer(target, name); GL_ASSERT + gl_->BindBuffer(target, name); + GL_ASSERT - gl_->BufferData(target, desc.size, nullptr, usage); GL_ASSERT + gl_->BufferData(target, desc.size, nullptr, usage); + GL_ASSERT return buffer_slab_.insert(std::make_unique(name, desc)); } -void GlCoreRhi::destroy_buffer(rhi::Handle handle) { +void GlCoreRhi::destroy_buffer(rhi::Handle handle) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(buffer_slab_.is_valid(handle) == true); @@ -517,7 +608,13 @@ void GlCoreRhi::destroy_buffer(rhi::Handle handle) { disposal_.push_back([this, name] { gl_->DeleteBuffers(1, &name); }); } -void GlCoreRhi::update_buffer_contents(rhi::Handle ctx, rhi::Handle handle, uint32_t offset, tcb::span data) { +void GlCoreRhi::update_buffer_contents( + rhi::Handle ctx, + rhi::Handle handle, + uint32_t offset, + tcb::span data +) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(transfer_context_active_ == true); SRB2_ASSERT(ctx.generation() == transfer_context_generation_); @@ -533,7 +630,8 @@ void GlCoreRhi::update_buffer_contents(rhi::Handle ctx, rhi::Ha SRB2_ASSERT(offset < b.desc.size && offset + data.size() <= b.desc.size); GLenum target = GL_ZERO; - switch (b.desc.type) { + switch (b.desc.type) + { case rhi::BufferType::kVertexBuffer: target = GL_ARRAY_BUFFER; break; @@ -542,11 +640,14 @@ void GlCoreRhi::update_buffer_contents(rhi::Handle ctx, rhi::Ha break; } - gl_->BindBuffer(target, b.buffer); GL_ASSERT - gl_->BufferSubData(target, offset, data.size(), data.data()); GL_ASSERT + gl_->BindBuffer(target, b.buffer); + GL_ASSERT + gl_->BufferSubData(target, offset, data.size(), data.data()); + GL_ASSERT } -rhi::Handle GlCoreRhi::create_uniform_set(rhi::Handle ctx, const rhi::CreateUniformSetInfo& info) +rhi::Handle +GlCoreRhi::create_uniform_set(rhi::Handle ctx, const rhi::CreateUniformSetInfo& info) { SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(transfer_context_active_ == true); @@ -562,7 +663,11 @@ rhi::Handle GlCoreRhi::create_uniform_set(rhi::Handle(std::move(uniform_set))); } -rhi::Handle GlCoreRhi::create_binding_set(rhi::Handle ctx, Handle pipeline, const rhi::CreateBindingSetInfo& info) +rhi::Handle GlCoreRhi::create_binding_set( + rhi::Handle ctx, + Handle pipeline, + const rhi::CreateBindingSetInfo& info +) { SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(transfer_context_active_ == true); @@ -576,18 +681,22 @@ rhi::Handle GlCoreRhi::create_binding_set(rhi::HandleGenVertexArrays(1, &vao); GL_ASSERT - gl_->BindVertexArray(vao); GL_ASSERT + gl_->GenVertexArrays(1, &vao); + GL_ASSERT + gl_->BindVertexArray(vao); + GL_ASSERT for (auto& attr_layout : pl.desc.vertex_input.attr_layouts) { SRB2_ASSERT(buffer_slab_.is_valid(info.vertex_buffers[attr_layout.buffer_index].vertex_buffer)); - auto& buf = *static_cast(&buffer_slab_[info.vertex_buffers[attr_layout.buffer_index].vertex_buffer]); + auto& buf = + *static_cast(&buffer_slab_[info.vertex_buffers[attr_layout.buffer_index].vertex_buffer]); SRB2_ASSERT(buf.desc.type == rhi::BufferType::kVertexBuffer); auto& buffer_layout = pl.desc.vertex_input.buffer_layouts[attr_layout.buffer_index]; - gl_->BindBuffer(GL_ARRAY_BUFFER, buf.buffer); GL_ASSERT + gl_->BindBuffer(GL_ARRAY_BUFFER, buf.buffer); + GL_ASSERT GLuint attrib_location = pl.attrib_locations[attr_layout.name]; VertexAttributeFormat vert_attr_format = rhi::vertex_attribute_format(attr_layout.name); @@ -596,8 +705,17 @@ rhi::Handle GlCoreRhi::create_binding_set(rhi::HandleEnableVertexAttribArray(pl.attrib_locations[attr_layout.name]); GL_ASSERT - gl_->VertexAttribPointer(attrib_location, vertex_attr_size, vertex_attr_type, GL_FALSE, buffer_layout.stride, reinterpret_cast(vertex_buffer_offset + attr_layout.offset)); GL_ASSERT + gl_->EnableVertexAttribArray(pl.attrib_locations[attr_layout.name]); + GL_ASSERT + gl_->VertexAttribPointer( + attrib_location, + vertex_attr_size, + vertex_attr_type, + GL_FALSE, + buffer_layout.stride, + reinterpret_cast(vertex_buffer_offset + attr_layout.offset) + ); + GL_ASSERT } binding_set.vao = vao; @@ -617,20 +735,24 @@ rhi::Handle GlCoreRhi::create_binding_set(rhi::Handle(std::move(binding_set))); } -rhi::Handle GlCoreRhi::create_renderbuffer(const rhi::RenderbufferDesc& desc) { +rhi::Handle GlCoreRhi::create_renderbuffer(const rhi::RenderbufferDesc& desc) +{ SRB2_ASSERT(graphics_context_active_ == false); GLuint name = 0; gl_->GenRenderbuffers(1, &name); // Obtain storage up-front. - gl_->BindRenderbuffer(GL_RENDERBUFFER, name); GL_ASSERT - gl_->RenderbufferStorage(GL_RENDERBUFFER, map_pixel_format(desc.format), desc.width, desc.height); GL_ASSERT + gl_->BindRenderbuffer(GL_RENDERBUFFER, name); + GL_ASSERT + gl_->RenderbufferStorage(GL_RENDERBUFFER, map_pixel_format(desc.format), desc.width, desc.height); + GL_ASSERT return renderbuffer_slab_.insert(std::make_unique(GlCoreRenderbuffer {name})); } -void GlCoreRhi::destroy_renderbuffer(rhi::Handle handle) { +void GlCoreRhi::destroy_renderbuffer(rhi::Handle handle) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(renderbuffer_slab_.is_valid(handle) == true); @@ -640,7 +762,8 @@ void GlCoreRhi::destroy_renderbuffer(rhi::Handle handle) { disposal_.push_back([this, name] { gl_->DeleteRenderbuffers(1, &name); }); } -rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) { +rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(platform_ != nullptr); // TODO assert compatibility of pipeline description with program using ProgramRequirements @@ -696,20 +819,23 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) gl_->CompileShader(vertex); GLint is_compiled = 0; gl_->GetShaderiv(vertex, GL_COMPILE_STATUS, &is_compiled); - if (is_compiled == GL_FALSE) { + if (is_compiled == GL_FALSE) + { GLint max_length = 0; gl_->GetShaderiv(vertex, GL_INFO_LOG_LENGTH, &max_length); std::vector compile_error(max_length); gl_->GetShaderInfoLog(vertex, max_length, &max_length, compile_error.data()); gl_->DeleteShader(vertex); - throw std::runtime_error(fmt::format("Vertex shader compilation failed: {}", std::string(compile_error.data()))); + throw std::runtime_error(fmt::format("Vertex shader compilation failed: {}", std::string(compile_error.data())) + ); } fragment = gl_->CreateShader(GL_FRAGMENT_SHADER); gl_->ShaderSource(fragment, 1, frag_src_arr, frag_src_arr_lens); gl_->CompileShader(fragment); gl_->GetShaderiv(vertex, GL_COMPILE_STATUS, &is_compiled); - if (is_compiled == GL_FALSE) { + if (is_compiled == GL_FALSE) + { GLint max_length = 0; gl_->GetShaderiv(fragment, GL_INFO_LOG_LENGTH, &max_length); std::vector compile_error(max_length); @@ -717,7 +843,9 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); - throw std::runtime_error(fmt::format("Fragment shader compilation failed: {}", std::string(compile_error.data()))); + throw std::runtime_error( + fmt::format("Fragment shader compilation failed: {}", std::string(compile_error.data())) + ); } // Program link @@ -727,7 +855,8 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) gl_->AttachShader(program, fragment); gl_->LinkProgram(program); gl_->GetProgramiv(program, GL_LINK_STATUS, &is_compiled); - if (is_compiled == GL_FALSE) { + if (is_compiled == GL_FALSE) + { GLint max_length = 0; gl_->GetProgramiv(program, GL_INFO_LOG_LENGTH, &max_length); std::vector link_error(max_length); @@ -742,74 +871,85 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) std::unordered_map active_attributes; GLint active_attribute_total = -1; gl_->GetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attribute_total); - if (active_attribute_total < 0) { + if (active_attribute_total < 0) + { gl_->DeleteProgram(program); gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); throw std::runtime_error("Unable to retrieve program active attributes"); } - if (desc.vertex_input.attr_layouts.size() != static_cast(active_attribute_total)) { + if (desc.vertex_input.attr_layouts.size() != static_cast(active_attribute_total)) + { gl_->DeleteProgram(program); gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); - throw std::runtime_error( - fmt::format( - "Pipeline's enabled attribute count does not match the linked program's total: {} vs {}", - desc.vertex_input.attr_layouts.size(), - static_cast(active_attribute_total) - ) - ); + throw std::runtime_error(fmt::format( + "Pipeline's enabled attribute count does not match the linked program's total: {} vs {}", + desc.vertex_input.attr_layouts.size(), + static_cast(active_attribute_total) + )); } - for (GLint i = 0; i < active_attribute_total; i++) { + for (GLint i = 0; i < active_attribute_total; i++) + { GLsizei name_len = 0; GLint size = 0; GLenum type = GL_ZERO; char name[256]; - gl_->GetActiveAttrib(program, i, 255, &name_len, &size, &type, name); GL_ASSERT - GLint location = gl_->GetAttribLocation(program, name); GL_ASSERT + gl_->GetActiveAttrib(program, i, 255, &name_len, &size, &type, name); + GL_ASSERT + GLint location = gl_->GetAttribLocation(program, name); + GL_ASSERT active_attributes.insert({std::string(name), GlCoreActiveUniform {type, static_cast(location)}}); } std::unordered_map active_uniforms; size_t total_enabled_uniforms = 0; - for (auto g = desc.uniform_input.enabled_uniforms.cbegin() ; g != desc.uniform_input.enabled_uniforms.cend(); g = std::next(g)) + for (auto g = desc.uniform_input.enabled_uniforms.cbegin(); g != desc.uniform_input.enabled_uniforms.cend(); + g = std::next(g)) { total_enabled_uniforms += g->size(); } GLint active_uniform_total = -1; gl_->GetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniform_total); - if (active_uniform_total < 0) { + if (active_uniform_total < 0) + { gl_->DeleteProgram(program); gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); throw std::runtime_error("Unable to retrieve program active uniforms"); } - if (total_enabled_uniforms + desc.sampler_input.enabled_samplers.size() != static_cast(active_uniform_total)) { + if (total_enabled_uniforms + desc.sampler_input.enabled_samplers.size() != + static_cast(active_uniform_total)) + { gl_->DeleteProgram(program); gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); - throw std::runtime_error( - fmt::format( - "Pipeline's enabled uniform count (uniforms + samplers) does not match the linked program's total: {} vs {}", - total_enabled_uniforms + desc.sampler_input.enabled_samplers.size(), - static_cast(active_uniform_total) - ) - ); + throw std::runtime_error(fmt::format( + "Pipeline's enabled uniform count (uniforms + samplers) does not match the linked program's total: {} vs " + "{}", + total_enabled_uniforms + desc.sampler_input.enabled_samplers.size(), + static_cast(active_uniform_total) + )); } - for (GLint i = 0; i < active_uniform_total; i++) { + for (GLint i = 0; i < active_uniform_total; i++) + { GLsizei name_len = 0; GLint size = 0; GLenum type = GL_ZERO; char name[256]; - gl_->GetActiveUniform(program, i, 255, &name_len, &size, &type, name); GL_ASSERT - GLint location = gl_->GetUniformLocation(program, name); GL_ASSERT + gl_->GetActiveUniform(program, i, 255, &name_len, &size, &type, name); + GL_ASSERT + GLint location = gl_->GetUniformLocation(program, name); + GL_ASSERT active_uniforms.insert({std::string(name), GlCoreActiveUniform {type, static_cast(location)}}); } - for (auto& attr : desc.vertex_input.attr_layouts) { + for (auto& attr : desc.vertex_input.attr_layouts) + { const char* symbol_name = map_vertex_attribute_symbol_name(attr.name); SRB2_ASSERT(symbol_name != nullptr); - if (active_attributes.find(symbol_name) == active_attributes.end()) { + if (active_attributes.find(symbol_name) == active_attributes.end()) + { gl_->DeleteProgram(program); gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); @@ -819,7 +959,8 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) auto expected_format = rhi::vertex_attribute_format(attr.name); auto expected_gl_type = map_vertex_attribute_format(expected_format); SRB2_ASSERT(expected_gl_type != GL_ZERO); - if (expected_gl_type != active_attr.type) { + if (expected_gl_type != active_attr.type) + { gl_->DeleteProgram(program); gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); @@ -829,7 +970,9 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) pipeline.attrib_locations.insert({attr.name, active_attr.location}); } - for (auto group_itr = desc.uniform_input.enabled_uniforms.cbegin(); group_itr != desc.uniform_input.enabled_uniforms.cend(); group_itr = std::next(group_itr)) + for (auto group_itr = desc.uniform_input.enabled_uniforms.cbegin(); + group_itr != desc.uniform_input.enabled_uniforms.cend(); + group_itr = std::next(group_itr)) { auto& group = *group_itr; for (auto itr = group.cbegin(); itr != group.cend(); itr = std::next(itr)) @@ -837,7 +980,8 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) auto& uniform = *itr; const char* symbol_name = map_uniform_attribute_symbol_name(uniform); SRB2_ASSERT(symbol_name != nullptr); - if (active_uniforms.find(symbol_name) == active_uniforms.end()) { + if (active_uniforms.find(symbol_name) == active_uniforms.end()) + { gl_->DeleteProgram(program); gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); @@ -847,7 +991,8 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) auto expected_format = rhi::uniform_format(uniform); auto expected_gl_type = map_uniform_format(expected_format); SRB2_ASSERT(expected_gl_type != GL_ZERO); - if (expected_gl_type != active_uniform.type) { + if (expected_gl_type != active_uniform.type) + { gl_->DeleteProgram(program); gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); @@ -858,17 +1003,20 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) } } - for (auto& sampler : desc.sampler_input.enabled_samplers) { + for (auto& sampler : desc.sampler_input.enabled_samplers) + { const char* symbol_name = map_sampler_symbol_name(sampler); SRB2_ASSERT(symbol_name != nullptr); - if (active_uniforms.find(symbol_name) == active_uniforms.end()) { + if (active_uniforms.find(symbol_name) == active_uniforms.end()) + { gl_->DeleteProgram(program); gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); throw std::runtime_error("Enabled sampler not found in linked program"); } auto& active_sampler = active_uniforms[symbol_name]; - if (active_sampler.type != GL_SAMPLER_2D) { + if (active_sampler.type != GL_SAMPLER_2D) + { gl_->DeleteProgram(program); gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); @@ -886,7 +1034,8 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) return pipeline_slab_.insert(std::make_unique(std::move(pipeline))); } -void GlCoreRhi::destroy_pipeline(rhi::Handle handle) { +void GlCoreRhi::destroy_pipeline(rhi::Handle handle) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(pipeline_slab_.is_valid(handle) == true); @@ -900,18 +1049,21 @@ void GlCoreRhi::destroy_pipeline(rhi::Handle handle) { disposal_.push_back([this, program] { gl_->DeleteProgram(program); }); } -rhi::Handle GlCoreRhi::begin_graphics() { +rhi::Handle GlCoreRhi::begin_graphics() +{ SRB2_ASSERT(graphics_context_active_ == false); graphics_context_active_ = true; return rhi::Handle(0, graphics_context_generation_); } -void GlCoreRhi::end_graphics(rhi::Handle handle) { +void GlCoreRhi::end_graphics(rhi::Handle handle) +{ SRB2_ASSERT(graphics_context_active_ == true); SRB2_ASSERT(current_pipeline_.has_value() == false && current_render_pass_.has_value() == false); graphics_context_generation_ += 1; graphics_context_active_ = false; - gl_->Flush(); GL_ASSERT + gl_->Flush(); + GL_ASSERT } rhi::Handle GlCoreRhi::begin_transfer() @@ -933,36 +1085,43 @@ void GlCoreRhi::end_transfer(rhi::Handle ctx) transfer_context_active_ = false; } -void GlCoreRhi::present() { +void GlCoreRhi::present() +{ SRB2_ASSERT(platform_ != nullptr); SRB2_ASSERT(graphics_context_active_ == false); platform_->present(); } -void GlCoreRhi::begin_default_render_pass(Handle ctx, bool clear) { +void GlCoreRhi::begin_default_render_pass(Handle ctx, bool clear) +{ SRB2_ASSERT(platform_ != nullptr); SRB2_ASSERT(graphics_context_active_ == true); SRB2_ASSERT(current_render_pass_.has_value() == false); const Rect fb_rect = platform_->get_default_framebuffer_dimensions(); - gl_->BindFramebuffer(GL_FRAMEBUFFER, 0); GL_ASSERT - gl_->Disable(GL_SCISSOR_TEST); GL_ASSERT - gl_->Viewport(0, 0, fb_rect.w, fb_rect.h); GL_ASSERT + gl_->BindFramebuffer(GL_FRAMEBUFFER, 0); + GL_ASSERT + gl_->Disable(GL_SCISSOR_TEST); + GL_ASSERT + gl_->Viewport(0, 0, fb_rect.w, fb_rect.h); + GL_ASSERT if (clear) { gl_->ClearColor(0.0f, 0.0f, 0.0f, 1.0f); gl_->ClearDepth(1.0f); gl_->ClearStencil(0); - gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GL_ASSERT + gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + GL_ASSERT } current_render_pass_ = GlCoreRhi::DefaultRenderPassState {}; } -void GlCoreRhi::begin_render_pass(Handle ctx, const RenderPassBeginInfo& info) { +void GlCoreRhi::begin_render_pass(Handle ctx, const RenderPassBeginInfo& info) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == false); @@ -971,13 +1130,20 @@ void GlCoreRhi::begin_render_pass(Handle ctx, const RenderPassB SRB2_ASSERT(rp.desc.depth_format.has_value() == info.depth_attachment.has_value()); auto fb_itr = framebuffers_.find(GlCoreFramebufferKey {info.color_attachment, info.depth_attachment}); - if (fb_itr == framebuffers_.end()) { + if (fb_itr == framebuffers_.end()) + { // Create a new framebuffer for this color-depth pair GLuint fb_name; - gl_->GenFramebuffers(1, &fb_name); GL_ASSERT - gl_->BindFramebuffer(GL_FRAMEBUFFER, fb_name); GL_ASSERT - fb_itr = framebuffers_.insert( - {GlCoreFramebufferKey {info.color_attachment, info.depth_attachment}, static_cast(fb_name)}).first; + gl_->GenFramebuffers(1, &fb_name); + GL_ASSERT + gl_->BindFramebuffer(GL_FRAMEBUFFER, fb_name); + GL_ASSERT + fb_itr = framebuffers_ + .insert( + {GlCoreFramebufferKey {info.color_attachment, info.depth_attachment}, + static_cast(fb_name)} + ) + .first; GLuint attachment = GL_COLOR_ATTACHMENT0; auto visitor = srb2::Overload { @@ -985,13 +1151,8 @@ void GlCoreRhi::begin_render_pass(Handle ctx, const RenderPassB { SRB2_ASSERT(texture_slab_.is_valid(handle)); auto& texture = *static_cast(&texture_slab_[handle]); - gl_->FramebufferTexture2D( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - texture.texture, - 0 - ); GL_ASSERT + gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.texture, 0); + GL_ASSERT }, [&, this](const Handle& handle) { @@ -1002,9 +1163,9 @@ void GlCoreRhi::begin_render_pass(Handle ctx, const RenderPassB GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer.renderbuffer - ); GL_ASSERT - } - }; + ); + GL_ASSERT + }}; std::visit(visitor, info.color_attachment); if (info.depth_attachment) { @@ -1013,20 +1174,25 @@ void GlCoreRhi::begin_render_pass(Handle ctx, const RenderPassB } } auto& fb = *fb_itr; - gl_->BindFramebuffer(GL_FRAMEBUFFER, fb.second); GL_ASSERT - gl_->Disable(GL_SCISSOR_TEST); GL_ASSERT + gl_->BindFramebuffer(GL_FRAMEBUFFER, fb.second); + GL_ASSERT + gl_->Disable(GL_SCISSOR_TEST); + GL_ASSERT - if (rp.desc.load_op == rhi::AttachmentLoadOp::kClear) { + if (rp.desc.load_op == rhi::AttachmentLoadOp::kClear) + { gl_->ClearColor(info.clear_color.r, info.clear_color.g, info.clear_color.b, info.clear_color.a); gl_->ClearDepth(1.f); gl_->ClearStencil(0); - gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); GL_ASSERT + gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + GL_ASSERT } current_render_pass_ = info; } -void GlCoreRhi::end_render_pass(Handle ctx) { +void GlCoreRhi::end_render_pass(Handle ctx) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true); @@ -1034,7 +1200,8 @@ void GlCoreRhi::end_render_pass(Handle ctx) { current_render_pass_ = std::nullopt; } -void GlCoreRhi::bind_pipeline(Handle ctx, Handle pipeline) { +void GlCoreRhi::bind_pipeline(Handle ctx, Handle pipeline) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true); @@ -1042,46 +1209,74 @@ void GlCoreRhi::bind_pipeline(Handle ctx, Handle pipe auto& pl = *static_cast(&pipeline_slab_[pipeline]); auto& desc = pl.desc; - gl_->UseProgram(pl.program); GL_ASSERT + gl_->UseProgram(pl.program); + GL_ASSERT - gl_->Disable(GL_SCISSOR_TEST); GL_ASSERT + gl_->Disable(GL_SCISSOR_TEST); + GL_ASSERT - if (desc.depth_attachment) { - gl_->Enable(GL_DEPTH_TEST); GL_ASSERT + if (desc.depth_attachment) + { + gl_->Enable(GL_DEPTH_TEST); + GL_ASSERT GLenum depth_func = map_compare_func(desc.depth_attachment->func); SRB2_ASSERT(depth_func != GL_ZERO); - gl_->DepthFunc(depth_func); GL_ASSERT - gl_->DepthMask(desc.depth_attachment->write ? GL_TRUE : GL_FALSE); GL_ASSERT - } else { - gl_->Disable(GL_DEPTH_TEST); GL_ASSERT + gl_->DepthFunc(depth_func); + GL_ASSERT + gl_->DepthMask(desc.depth_attachment->write ? GL_TRUE : GL_FALSE); + GL_ASSERT + } + else + { + gl_->Disable(GL_DEPTH_TEST); + GL_ASSERT } - if (desc.color_attachment.blend) { + if (desc.color_attachment.blend) + { rhi::BlendDesc& bl = *desc.color_attachment.blend; - gl_->Enable(GL_BLEND); GL_ASSERT - gl_->BlendFuncSeparate(map_blend_factor(bl.source_factor_color), - map_blend_factor(bl.dest_factor_color), - map_blend_factor(bl.source_factor_alpha), - map_blend_factor(bl.dest_factor_alpha)); GL_ASSERT - gl_->BlendEquationSeparate(map_blend_function(bl.color_function), map_blend_function(bl.alpha_function)); GL_ASSERT - gl_->BlendColor(desc.blend_color.r, desc.blend_color.g, desc.blend_color.b, desc.blend_color.a); GL_ASSERT - } else { + gl_->Enable(GL_BLEND); + GL_ASSERT + gl_->BlendFuncSeparate( + map_blend_factor(bl.source_factor_color), + map_blend_factor(bl.dest_factor_color), + map_blend_factor(bl.source_factor_alpha), + map_blend_factor(bl.dest_factor_alpha) + ); + GL_ASSERT + gl_->BlendEquationSeparate(map_blend_function(bl.color_function), map_blend_function(bl.alpha_function)); + GL_ASSERT + gl_->BlendColor(desc.blend_color.r, desc.blend_color.g, desc.blend_color.b, desc.blend_color.a); + GL_ASSERT + } + else + { gl_->Disable(GL_BLEND); } - gl_->ColorMask(desc.color_attachment.color_mask.r ? GL_TRUE : GL_FALSE, - desc.color_attachment.color_mask.g ? GL_TRUE : GL_FALSE, - desc.color_attachment.color_mask.b ? GL_TRUE : GL_FALSE, - desc.color_attachment.color_mask.a ? GL_TRUE : GL_FALSE); GL_ASSERT + gl_->ColorMask( + desc.color_attachment.color_mask.r ? GL_TRUE : GL_FALSE, + desc.color_attachment.color_mask.g ? GL_TRUE : GL_FALSE, + desc.color_attachment.color_mask.b ? GL_TRUE : GL_FALSE, + desc.color_attachment.color_mask.a ? GL_TRUE : GL_FALSE + ); + GL_ASSERT GLenum cull_face = map_cull_mode(desc.cull); - if (cull_face == GL_NONE) { - gl_->Disable(GL_CULL_FACE); GL_ASSERT - } else { - gl_->Enable(GL_CULL_FACE); GL_ASSERT - gl_->CullFace(cull_face); GL_ASSERT + if (cull_face == GL_NONE) + { + gl_->Disable(GL_CULL_FACE); + GL_ASSERT } - gl_->FrontFace(map_winding(desc.winding)); GL_ASSERT + else + { + gl_->Enable(GL_CULL_FACE); + GL_ASSERT + gl_->CullFace(cull_face); + GL_ASSERT + } + gl_->FrontFace(map_winding(desc.winding)); + GL_ASSERT current_pipeline_ = pipeline; current_primitive_type_ = desc.primitive; @@ -1122,42 +1317,61 @@ void GlCoreRhi::bind_uniform_set(Handle ctx, uint32_t slot, Han SRB2_ASSERT(pl.uniform_locations.find(uniform_name) != pl.uniform_locations.end()); GLuint pipeline_uniform = pl.uniform_locations[uniform_name]; - auto visitor = srb2::Overload - { - [&](const float& value){ gl_->Uniform1f(pipeline_uniform, value); GL_ASSERT }, - [&](const std::array& value) { gl_->Uniform2f(pipeline_uniform, value[0], value[1]); GL_ASSERT }, + auto visitor = srb2::Overload { + [&](const float& value) + { + gl_->Uniform1f(pipeline_uniform, value); + GL_ASSERT + }, + [&](const std::array& value) + { + gl_->Uniform2f(pipeline_uniform, value[0], value[1]); + GL_ASSERT + }, [&](const std::array& value) { - gl_->Uniform3f(pipeline_uniform, value[0], value[1], value[2]); GL_ASSERT + gl_->Uniform3f(pipeline_uniform, value[0], value[1], value[2]); + GL_ASSERT }, [&](const std::array& value) { - gl_->Uniform4f(pipeline_uniform, value[0], value[1], value[2], value[3]); GL_ASSERT + gl_->Uniform4f(pipeline_uniform, value[0], value[1], value[2], value[3]); + GL_ASSERT + }, + [&](const int32_t& value) + { + gl_->Uniform1i(pipeline_uniform, value); + GL_ASSERT }, - [&](const int32_t& value) { gl_->Uniform1i(pipeline_uniform, value); GL_ASSERT }, [&](const std::array& value) { - gl_->Uniform2i(pipeline_uniform, value[0], value[1]); GL_ASSERT + gl_->Uniform2i(pipeline_uniform, value[0], value[1]); + GL_ASSERT }, [&](const std::array& value) { - gl_->Uniform3i(pipeline_uniform, value[0], value[1], value[2]); GL_ASSERT + gl_->Uniform3i(pipeline_uniform, value[0], value[1], value[2]); + GL_ASSERT }, [&](const std::array& value) { - gl_->Uniform4i(pipeline_uniform, value[0], value[1], value[2], value[3]); GL_ASSERT + gl_->Uniform4i(pipeline_uniform, value[0], value[1], value[2], value[3]); + GL_ASSERT }, [&](const std::array, 2>& value) { - gl_->UniformMatrix2fv(pipeline_uniform, 1, false, reinterpret_cast(&value)); GL_ASSERT + gl_->UniformMatrix2fv(pipeline_uniform, 1, false, reinterpret_cast(&value)); + GL_ASSERT }, [&](const std::array, 3>& value) { - gl_->UniformMatrix3fv(pipeline_uniform, 1, false, reinterpret_cast(&value)); GL_ASSERT + gl_->UniformMatrix3fv(pipeline_uniform, 1, false, reinterpret_cast(&value)); + GL_ASSERT }, [&](const std::array, 4>& value) { - gl_->UniformMatrix4fv(pipeline_uniform, 1, false, reinterpret_cast(&value)); GL_ASSERT + gl_->UniformMatrix4fv(pipeline_uniform, 1, false, reinterpret_cast(&value)); + GL_ASSERT }, }; std::visit(visitor, update_data); @@ -1192,7 +1406,8 @@ void GlCoreRhi::bind_binding_set(Handle ctx, Handle GLuint sampler_uniform_loc = pl.sampler_locations[sampler_name]; GLenum active_texture = GL_TEXTURE0; GLuint uniform_value = 0; - switch (sampler_name) { + switch (sampler_name) + { case rhi::SamplerName::kSampler0: active_texture = GL_TEXTURE0; uniform_value = 0; @@ -1210,9 +1425,12 @@ void GlCoreRhi::bind_binding_set(Handle ctx, Handle uniform_value = 3; break; } - gl_->ActiveTexture(active_texture); GL_ASSERT - gl_->BindTexture(GL_TEXTURE_2D, texture_gl_name); GL_ASSERT - gl_->Uniform1i(sampler_uniform_loc, uniform_value); GL_ASSERT + gl_->ActiveTexture(active_texture); + GL_ASSERT + gl_->BindTexture(GL_TEXTURE_2D, texture_gl_name); + GL_ASSERT + gl_->Uniform1i(sampler_uniform_loc, uniform_value); + GL_ASSERT } } @@ -1230,7 +1448,8 @@ void GlCoreRhi::bind_index_buffer(Handle ctx, Handle bu gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib.buffer); } -void GlCoreRhi::set_scissor(Handle ctx, const Rect& rect) { +void GlCoreRhi::set_scissor(Handle ctx, const Rect& rect) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); @@ -1238,28 +1457,35 @@ void GlCoreRhi::set_scissor(Handle ctx, const Rect& rect) { gl_->Scissor(rect.x, rect.y, rect.w, rect.h); } -void GlCoreRhi::set_viewport(Handle ctx, const Rect& rect) { +void GlCoreRhi::set_viewport(Handle ctx, const Rect& rect) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); gl_->Viewport(rect.x, rect.y, rect.w, rect.h); } -void GlCoreRhi::draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) { +void GlCoreRhi::draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); - gl_->DrawArrays(map_primitive_mode(current_primitive_type_), first_vertex, vertex_count); GL_ASSERT + gl_->DrawArrays(map_primitive_mode(current_primitive_type_), first_vertex, vertex_count); + GL_ASSERT } -void GlCoreRhi::draw_indexed(Handle ctx, - uint32_t index_count, - uint32_t first_index) { +void GlCoreRhi::draw_indexed(Handle ctx, uint32_t index_count, uint32_t first_index) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); - gl_->DrawElements(map_primitive_mode(current_primitive_type_), index_count, GL_UNSIGNED_SHORT, reinterpret_cast(first_index * 2 + index_buffer_offset_)); GL_ASSERT + gl_->DrawElements( + map_primitive_mode(current_primitive_type_), + index_count, + GL_UNSIGNED_SHORT, + reinterpret_cast(first_index * 2 + index_buffer_offset_) + ); + GL_ASSERT } - void GlCoreRhi::read_pixels(Handle ctx, const Rect& rect, tcb::span out) { SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); @@ -1269,14 +1495,17 @@ void GlCoreRhi::read_pixels(Handle ctx, const Rect& rect, tcb:: gl_->ReadPixels(rect.x, rect.y, rect.w, rect.h, GL_RGBA, GL_UNSIGNED_BYTE, out.data()); } -void GlCoreRhi::finish() { +void GlCoreRhi::finish() +{ SRB2_ASSERT(graphics_context_active_ == false); for (auto it = binding_set_slab_.cbegin(); it != binding_set_slab_.cend(); it++) { - gl_->BindVertexArray(0); GL_ASSERT + gl_->BindVertexArray(0); + GL_ASSERT GLuint vao = reinterpret_cast(*it).vao; - gl_->DeleteVertexArrays(1, &vao); GL_ASSERT + gl_->DeleteVertexArrays(1, &vao); + GL_ASSERT } binding_set_slab_.clear(); uniform_set_slab_.clear(); @@ -1293,5 +1522,6 @@ void GlCoreRhi::finish() { (*it)(); } - disposal_.clear(); GL_ASSERT + disposal_.clear(); + GL_ASSERT } diff --git a/src/rhi/gl3_core/gl3_core_rhi.hpp b/src/rhi/gl3_core/gl3_core_rhi.hpp index a11d58d52..d20747cc6 100644 --- a/src/rhi/gl3_core/gl3_core_rhi.hpp +++ b/src/rhi/gl3_core/gl3_core_rhi.hpp @@ -11,19 +11,17 @@ #include "../rhi.hpp" -namespace srb2::rhi { +namespace srb2::rhi +{ -struct GlCoreFramebufferKey { +struct GlCoreFramebufferKey +{ TextureOrRenderbuffer color; std::optional depth; - bool operator==(const GlCoreFramebufferKey& rhs) const noexcept { - return color == rhs.color && depth == rhs.depth; - } + bool operator==(const GlCoreFramebufferKey& rhs) const noexcept { return color == rhs.color && depth == rhs.depth; } - bool operator!=(const GlCoreFramebufferKey& rhs) const noexcept { - return !(*this == rhs); - } + bool operator!=(const GlCoreFramebufferKey& rhs) const noexcept { return !(*this == rhs); } }; } // namespace srb2::rhi @@ -32,19 +30,25 @@ struct GlCoreFramebufferKey { // we need to split the namespace declarations _before_ the instantiation of std::unordered_map. template <> -struct std::hash { - std::size_t operator()(const srb2::rhi::GlCoreFramebufferKey& key) const { - struct GetHandleHashVisitor { - uint32_t operator()(const srb2::rhi::Handle& handle) const noexcept { +struct std::hash +{ + std::size_t operator()(const srb2::rhi::GlCoreFramebufferKey& key) const + { + struct GetHandleHashVisitor + { + uint32_t operator()(const srb2::rhi::Handle& handle) const noexcept + { return std::hash>()(handle); } - uint32_t operator()(const srb2::rhi::Handle& handle) const noexcept { + uint32_t operator()(const srb2::rhi::Handle& handle) const noexcept + { return std::hash>()(handle); } }; std::size_t color_hash = std::visit(GetHandleHashVisitor {}, key.color); std::size_t depth_hash = 0; - if (key.depth) { + if (key.depth) + { depth_hash = std::visit(GetHandleHashVisitor {}, *key.depth); } return color_hash ^ (depth_hash << 1); @@ -53,13 +57,15 @@ struct std::hash { struct GladGLContext; -namespace srb2::rhi { +namespace srb2::rhi +{ typedef void (*GlProc)(void); typedef GlProc (*GlLoadFunc)(const char* name); /// @brief Platform-specific implementation details for the GLES2 backend. -struct GlCorePlatform { +struct GlCorePlatform +{ virtual ~GlCorePlatform(); virtual void present() = 0; @@ -67,7 +73,8 @@ struct GlCorePlatform { virtual Rect get_default_framebuffer_dimensions() = 0; }; -class GlCoreRhi final : public Rhi { +class GlCoreRhi final : public Rhi +{ std::unique_ptr platform_; std::unique_ptr gl_; @@ -82,7 +89,9 @@ class GlCoreRhi final : public Rhi { std::unordered_map framebuffers_ {16}; - struct DefaultRenderPassState {}; + struct DefaultRenderPassState + { + }; using RenderPassState = std::variant; std::optional current_render_pass_; std::optional> current_pipeline_; @@ -114,10 +123,24 @@ public: virtual Handle begin_transfer() override; virtual void end_transfer(Handle handle) override; - virtual void update_buffer_contents(Handle ctx, Handle buffer, uint32_t offset, tcb::span data) override; - virtual void update_texture(Handle ctx, Handle texture, Rect region, srb2::rhi::PixelFormat data_format, tcb::span data) override; - virtual Handle create_uniform_set(Handle ctx, const CreateUniformSetInfo& info) override; - virtual Handle create_binding_set(Handle ctx, Handle pipeline, const CreateBindingSetInfo& info) override; + virtual void update_buffer_contents( + Handle ctx, + Handle buffer, + uint32_t offset, + tcb::span data + ) override; + virtual void update_texture( + Handle ctx, + Handle texture, + Rect region, + srb2::rhi::PixelFormat data_format, + tcb::span data + ) override; + virtual Handle + create_uniform_set(Handle ctx, const CreateUniformSetInfo& info) override; + virtual Handle + create_binding_set(Handle ctx, Handle pipeline, const CreateBindingSetInfo& info) + override; virtual Handle begin_graphics() override; virtual void end_graphics(Handle ctx) override; @@ -133,9 +156,7 @@ public: virtual void set_scissor(Handle ctx, const Rect& rect) override; virtual void set_viewport(Handle ctx, const Rect& rect) override; virtual void draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) override; - virtual void draw_indexed(Handle ctx, - uint32_t index_count, - uint32_t first_index) override; + virtual void draw_indexed(Handle ctx, uint32_t index_count, uint32_t first_index) override; virtual void read_pixels(Handle ctx, const Rect& rect, tcb::span out) override; virtual void present() override; diff --git a/src/rhi/gles2/gles2_rhi.cpp b/src/rhi/gles2/gles2_rhi.cpp index 8e9d61f7d..5c8134eb6 100644 --- a/src/rhi/gles2/gles2_rhi.cpp +++ b/src/rhi/gles2/gles2_rhi.cpp @@ -13,16 +13,20 @@ using namespace srb2; using srb2::rhi::Gles2Platform; using srb2::rhi::Gles2Rhi; -namespace { +namespace +{ template -std::unique_ptr> static_unique_ptr_cast(std::unique_ptr> ptr) { +std::unique_ptr> static_unique_ptr_cast(std::unique_ptr> ptr) +{ D* derived = static_cast(ptr.release()); return std::unique_ptr>(derived, std::default_delete()); } -constexpr GLenum map_pixel_format(rhi::PixelFormat format) { - switch (format) { +constexpr GLenum map_pixel_format(rhi::PixelFormat format) +{ + switch (format) + { case rhi::PixelFormat::kRGBA8: // requires extension GL_OES_rgb8_rgba8, which is always requested return GL_RGBA8_OES; @@ -35,11 +39,13 @@ constexpr GLenum map_pixel_format(rhi::PixelFormat format) { } } -constexpr std::tuple map_pixel_data_format(rhi::PixelFormat format) { +constexpr std::tuple map_pixel_data_format(rhi::PixelFormat format) +{ GLenum layout = GL_ZERO; GLenum type = GL_ZERO; GLuint size = 0; - switch (format) { + switch (format) + { case rhi::PixelFormat::kR8: layout = GL_LUMINANCE; type = GL_UNSIGNED_BYTE; @@ -56,8 +62,10 @@ constexpr std::tuple map_pixel_data_format(rhi::PixelFor return std::tuple(layout, type, size); } -constexpr GLenum map_texture_format(rhi::TextureFormat format) { - switch (format) { +constexpr GLenum map_texture_format(rhi::TextureFormat format) +{ + switch (format) + { case rhi::TextureFormat::kRGBA: return GL_RGBA; case rhi::TextureFormat::kRGB: @@ -69,8 +77,10 @@ constexpr GLenum map_texture_format(rhi::TextureFormat format) { } } -constexpr GLenum map_buffer_type(rhi::BufferType type) { - switch (type) { +constexpr GLenum map_buffer_type(rhi::BufferType type) +{ + switch (type) + { case rhi::BufferType::kVertexBuffer: return GL_ARRAY_BUFFER; case rhi::BufferType::kIndexBuffer: @@ -80,8 +90,10 @@ constexpr GLenum map_buffer_type(rhi::BufferType type) { } } -constexpr GLenum map_buffer_usage(rhi::BufferUsage usage) { - switch (usage) { +constexpr GLenum map_buffer_usage(rhi::BufferUsage usage) +{ + switch (usage) + { case rhi::BufferUsage::kImmutable: return GL_STATIC_DRAW; case rhi::BufferUsage::kDynamic: @@ -91,8 +103,10 @@ constexpr GLenum map_buffer_usage(rhi::BufferUsage usage) { } } -constexpr GLenum map_compare_func(rhi::CompareFunc func) { - switch (func) { +constexpr GLenum map_compare_func(rhi::CompareFunc func) +{ + switch (func) + { case rhi::CompareFunc::kNever: return GL_NEVER; case rhi::CompareFunc::kLess: @@ -114,8 +128,10 @@ constexpr GLenum map_compare_func(rhi::CompareFunc func) { } } -constexpr GLenum map_blend_factor(rhi::BlendFactor factor) { - switch (factor) { +constexpr GLenum map_blend_factor(rhi::BlendFactor factor) +{ + switch (factor) + { case rhi::BlendFactor::kZero: return GL_ZERO; case rhi::BlendFactor::kOne: @@ -151,8 +167,10 @@ constexpr GLenum map_blend_factor(rhi::BlendFactor factor) { } } -constexpr GLenum map_blend_function(rhi::BlendFunction function) { - switch (function) { +constexpr GLenum map_blend_function(rhi::BlendFunction function) +{ + switch (function) + { case rhi::BlendFunction::kAdd: return GL_FUNC_ADD; case rhi::BlendFunction::kSubtract: @@ -164,8 +182,10 @@ constexpr GLenum map_blend_function(rhi::BlendFunction function) { } } -constexpr GLenum map_cull_mode(rhi::CullMode mode) { - switch (mode) { +constexpr GLenum map_cull_mode(rhi::CullMode mode) +{ + switch (mode) + { case rhi::CullMode::kNone: return GL_NONE; case rhi::CullMode::kFront: @@ -177,8 +197,10 @@ constexpr GLenum map_cull_mode(rhi::CullMode mode) { } } -constexpr GLenum map_winding(rhi::FaceWinding winding) { - switch (winding) { +constexpr GLenum map_winding(rhi::FaceWinding winding) +{ + switch (winding) + { case rhi::FaceWinding::kCounterClockwise: return GL_CCW; case rhi::FaceWinding::kClockwise: @@ -188,8 +210,10 @@ constexpr GLenum map_winding(rhi::FaceWinding winding) { } } -constexpr GLenum map_primitive_mode(rhi::PrimitiveType type) { - switch (type) { +constexpr GLenum map_primitive_mode(rhi::PrimitiveType type) +{ + switch (type) + { case rhi::PrimitiveType::kPoints: return GL_POINTS; case rhi::PrimitiveType::kLines: @@ -207,8 +231,10 @@ constexpr GLenum map_primitive_mode(rhi::PrimitiveType type) { } } -constexpr const char* map_vertex_attribute_symbol_name(rhi::VertexAttributeName name) { - switch (name) { +constexpr const char* map_vertex_attribute_symbol_name(rhi::VertexAttributeName name) +{ + switch (name) + { case rhi::VertexAttributeName::kPosition: return "a_position"; case rhi::VertexAttributeName::kNormal: @@ -243,8 +269,10 @@ constexpr const char* map_vertex_attribute_enable_define(rhi::VertexAttributeNam } */ -constexpr const char* map_uniform_attribute_symbol_name(rhi::UniformName name) { - switch (name) { +constexpr const char* map_uniform_attribute_symbol_name(rhi::UniformName name) +{ + switch (name) + { case rhi::UniformName::kTime: return "u_time"; case rhi::UniformName::kModelView: @@ -271,8 +299,10 @@ constexpr const char* map_uniform_attribute_enable_define(rhi::UniformName name) } */ -constexpr const char* map_sampler_symbol_name(rhi::SamplerName name) { - switch (name) { +constexpr const char* map_sampler_symbol_name(rhi::SamplerName name) +{ + switch (name) + { case rhi::SamplerName::kSampler0: return "s_sampler0"; case rhi::SamplerName::kSampler1: @@ -286,8 +316,10 @@ constexpr const char* map_sampler_symbol_name(rhi::SamplerName name) { } } -constexpr GLenum map_vertex_attribute_format(rhi::VertexAttributeFormat format) { - switch (format) { +constexpr GLenum map_vertex_attribute_format(rhi::VertexAttributeFormat format) +{ + switch (format) + { case rhi::VertexAttributeFormat::kFloat: return GL_FLOAT; case rhi::VertexAttributeFormat::kFloat2: @@ -301,8 +333,10 @@ constexpr GLenum map_vertex_attribute_format(rhi::VertexAttributeFormat format) } } -constexpr GLenum map_vertex_attribute_type(rhi::VertexAttributeFormat format) { - switch (format) { +constexpr GLenum map_vertex_attribute_type(rhi::VertexAttributeFormat format) +{ + switch (format) + { case rhi::VertexAttributeFormat::kFloat: return GL_FLOAT; case rhi::VertexAttributeFormat::kFloat2: @@ -316,8 +350,10 @@ constexpr GLenum map_vertex_attribute_type(rhi::VertexAttributeFormat format) { } } -constexpr GLint map_vertex_attribute_format_size(rhi::VertexAttributeFormat format) { - switch (format) { +constexpr GLint map_vertex_attribute_format_size(rhi::VertexAttributeFormat format) +{ + switch (format) + { case rhi::VertexAttributeFormat::kFloat: return 1; case rhi::VertexAttributeFormat::kFloat2: @@ -331,8 +367,10 @@ constexpr GLint map_vertex_attribute_format_size(rhi::VertexAttributeFormat form } } -constexpr GLenum map_uniform_format(rhi::UniformFormat format) { - switch (format) { +constexpr GLenum map_uniform_format(rhi::UniformFormat format) +{ + switch (format) + { case rhi::UniformFormat::kFloat: return GL_FLOAT; case rhi::UniformFormat::kFloat2: @@ -360,30 +398,35 @@ constexpr GLenum map_uniform_format(rhi::UniformFormat format) { } } -struct Gles2Texture : public rhi::Texture { +struct Gles2Texture : public rhi::Texture +{ GLuint texture; rhi::TextureDesc desc; Gles2Texture(GLuint texture, const rhi::TextureDesc& desc) noexcept : texture(texture), desc(desc) {} }; -struct Gles2Buffer : public rhi::Buffer { +struct Gles2Buffer : public rhi::Buffer +{ GLuint buffer; rhi::BufferDesc desc; Gles2Buffer(GLuint buffer, const rhi::BufferDesc& desc) noexcept : buffer(buffer), desc(desc) {} }; -struct Gles2RenderPass : public rhi::RenderPass { +struct Gles2RenderPass : public rhi::RenderPass +{ rhi::RenderPassDesc desc; explicit Gles2RenderPass(const rhi::RenderPassDesc& desc) noexcept : desc(desc) {} }; -struct Gles2Renderbuffer : public rhi::Renderbuffer { +struct Gles2Renderbuffer : public rhi::Renderbuffer +{ GLuint renderbuffer; explicit Gles2Renderbuffer(GLuint renderbuffer) noexcept : renderbuffer(renderbuffer) {} }; -struct Gles2Pipeline : public rhi::Pipeline { +struct Gles2Pipeline : public rhi::Pipeline +{ GLuint vertex_shader = 0; GLuint fragment_shader = 0; GLuint program = 0; @@ -393,16 +436,23 @@ struct Gles2Pipeline : public rhi::Pipeline { rhi::PipelineDesc desc; Gles2Pipeline() = default; - explicit Gles2Pipeline(GLuint vertex_shader, - GLuint fragment_shader, - GLuint program, - const rhi::PipelineDesc& desc) noexcept - : vertex_shader(vertex_shader), fragment_shader(fragment_shader), program(program), desc(desc) {} + explicit Gles2Pipeline( + GLuint vertex_shader, + GLuint fragment_shader, + GLuint program, + const rhi::PipelineDesc& desc + ) noexcept + : vertex_shader(vertex_shader), fragment_shader(fragment_shader), program(program), desc(desc) + { + } }; -struct Gles2GraphicsContext : public rhi::GraphicsContext {}; +struct Gles2GraphicsContext : public rhi::GraphicsContext +{ +}; -struct Gles2ActiveUniform { +struct Gles2ActiveUniform +{ GLenum type; GLuint location; }; @@ -411,27 +461,34 @@ struct Gles2ActiveUniform { Gles2Platform::~Gles2Platform() = default; -Gles2Rhi::Gles2Rhi(std::unique_ptr&& platform) - : platform_(std::move(platform)) { +Gles2Rhi::Gles2Rhi(std::unique_ptr&& platform) : platform_(std::move(platform)) +{ } Gles2Rhi::~Gles2Rhi() = default; -rhi::Handle Gles2Rhi::create_render_pass(const rhi::RenderPassDesc& desc) { +rhi::Handle Gles2Rhi::create_render_pass(const rhi::RenderPassDesc& desc) +{ SRB2_ASSERT(graphics_context_active_ == false); // GL has no formal render pass object return render_pass_slab_.insert(std::make_unique(desc)); } -void Gles2Rhi::destroy_render_pass(rhi::Handle&& handle) { +void Gles2Rhi::destroy_render_pass(rhi::Handle&& handle) +{ SRB2_ASSERT(graphics_context_active_ == false); std::unique_ptr buffer = render_pass_slab_.remove(handle); std::unique_ptr casted(static_cast(buffer.release())); } -rhi::Handle Gles2Rhi::create_texture(const rhi::TextureDesc& desc, srb2::rhi::PixelFormat data_format, tcb::span data) { +rhi::Handle Gles2Rhi::create_texture( + const rhi::TextureDesc& desc, + srb2::rhi::PixelFormat data_format, + tcb::span data +) +{ SRB2_ASSERT(graphics_context_active_ == false); GLint internal_format = map_texture_format(desc.format); @@ -451,7 +508,8 @@ rhi::Handle Gles2Rhi::create_texture(const rhi::TextureDesc& desc, std::tie(format, type, size) = map_pixel_data_format(data_format); SRB2_ASSERT(format != GL_ZERO && type != GL_ZERO); SRB2_ASSERT(internal_format == format); - if (!data.empty()) { + if (!data.empty()) + { SRB2_ASSERT(size * desc.width * desc.height == data.size_bytes()); raw_data = static_cast(data.data()); } @@ -464,7 +522,8 @@ rhi::Handle Gles2Rhi::create_texture(const rhi::TextureDesc& desc, return texture_slab_.insert(std::make_unique(name, desc)); } -void Gles2Rhi::destroy_texture(rhi::Handle&& handle) { +void Gles2Rhi::destroy_texture(rhi::Handle&& handle) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(texture_slab_.is_valid(handle) == true); @@ -473,7 +532,13 @@ void Gles2Rhi::destroy_texture(rhi::Handle&& handle) { disposal_.push_back([name] { glDeleteTextures(1, &name); }); } -void Gles2Rhi::update_texture(Handle texture, Rect region, srb2::rhi::PixelFormat data_format, tcb::span data) { +void Gles2Rhi::update_texture( + Handle texture, + Rect region, + srb2::rhi::PixelFormat data_format, + tcb::span data +) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(texture_slab_.is_valid(texture) == true); @@ -490,10 +555,21 @@ void Gles2Rhi::update_texture(Handle texture, Rect region, srb2::rhi::P glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, t.texture); - glTexSubImage2D(GL_TEXTURE_2D, 0, region.x, region.y, region.w, region.h, format, type, reinterpret_cast(data.data())); + glTexSubImage2D( + GL_TEXTURE_2D, + 0, + region.x, + region.y, + region.w, + region.h, + format, + type, + reinterpret_cast(data.data()) + ); } -rhi::Handle Gles2Rhi::create_buffer(const rhi::BufferDesc& desc, tcb::span data) { +rhi::Handle Gles2Rhi::create_buffer(const rhi::BufferDesc& desc, tcb::span data) +{ SRB2_ASSERT(graphics_context_active_ == false); // If data is provided, it must match the buffer description size exactly @@ -512,7 +588,8 @@ rhi::Handle Gles2Rhi::create_buffer(const rhi::BufferDesc& desc, tc // if no data is provided, the initial buffer data is undefined const void* raw_data = nullptr; - if (!data.empty()) { + if (!data.empty()) + { raw_data = static_cast(data.data()); } glBufferData(target, desc.size, raw_data, usage); @@ -520,7 +597,8 @@ rhi::Handle Gles2Rhi::create_buffer(const rhi::BufferDesc& desc, tc return buffer_slab_.insert(std::make_unique(name, desc)); } -void Gles2Rhi::destroy_buffer(rhi::Handle&& handle) { +void Gles2Rhi::destroy_buffer(rhi::Handle&& handle) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(buffer_slab_.is_valid(handle) == true); @@ -531,7 +609,8 @@ void Gles2Rhi::destroy_buffer(rhi::Handle&& handle) { disposal_.push_back([name] { glDeleteBuffers(1, &name); }); } -void Gles2Rhi::update_buffer_contents(rhi::Handle handle, uint32_t offset, tcb::span data) { +void Gles2Rhi::update_buffer_contents(rhi::Handle handle, uint32_t offset, tcb::span data) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(buffer_slab_.is_valid(handle) == true); @@ -542,7 +621,8 @@ void Gles2Rhi::update_buffer_contents(rhi::Handle handle, uint32_t SRB2_ASSERT(offset < b.desc.size && offset + data.size() < b.desc.size); - switch (b.desc.type) { + switch (b.desc.type) + { case rhi::BufferType::kVertexBuffer: glBindBuffer(GL_ARRAY_BUFFER, b.buffer); glBufferSubData(GL_ARRAY_BUFFER, offset, data.size(), data.data()); @@ -554,7 +634,8 @@ void Gles2Rhi::update_buffer_contents(rhi::Handle handle, uint32_t } } -rhi::Handle Gles2Rhi::create_renderbuffer(const rhi::RenderbufferDesc& desc) { +rhi::Handle Gles2Rhi::create_renderbuffer(const rhi::RenderbufferDesc& desc) +{ SRB2_ASSERT(graphics_context_active_ == false); GLuint name = 0; @@ -567,7 +648,8 @@ rhi::Handle Gles2Rhi::create_renderbuffer(const rhi::Renderbu return renderbuffer_slab_.insert(std::make_unique(Gles2Renderbuffer {name})); } -void Gles2Rhi::destroy_renderbuffer(rhi::Handle&& handle) { +void Gles2Rhi::destroy_renderbuffer(rhi::Handle&& handle) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(renderbuffer_slab_.is_valid(handle) == true); @@ -577,7 +659,8 @@ void Gles2Rhi::destroy_renderbuffer(rhi::Handle&& handle) { disposal_.push_back([name] { glDeleteRenderbuffers(1, &name); }); } -rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { +rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) +{ SRB2_ASSERT(platform_ != nullptr); // TODO assert compatibility of pipeline description with program using ProgramRequirements @@ -600,7 +683,8 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { glCompileShader(vertex); GLint is_compiled = 0; glGetShaderiv(vertex, GL_COMPILE_STATUS, &is_compiled); - if (is_compiled == GL_FALSE) { + if (is_compiled == GL_FALSE) + { GLint max_length = 0; glGetShaderiv(vertex, GL_INFO_LOG_LENGTH, &max_length); std::vector compile_error(max_length); @@ -613,7 +697,8 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { glShaderSource(fragment, 1, frag_src_arr, frag_src_arr_lens); glCompileShader(fragment); glGetShaderiv(vertex, GL_COMPILE_STATUS, &is_compiled); - if (is_compiled == GL_FALSE) { + if (is_compiled == GL_FALSE) + { GLint max_length = 0; glGetShaderiv(fragment, GL_INFO_LOG_LENGTH, &max_length); std::vector compile_error(max_length); @@ -621,14 +706,17 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { glDeleteShader(fragment); glDeleteShader(vertex); - throw std::runtime_error(std::string("Fragment shader compilation failed: ") + std::string(compile_error.data())); + throw std::runtime_error( + std::string("Fragment shader compilation failed: ") + std::string(compile_error.data()) + ); } program = glCreateProgram(); glAttachShader(program, vertex); glAttachShader(program, fragment); glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &is_compiled); - if (is_compiled == GL_FALSE) { + if (is_compiled == GL_FALSE) + { GLint max_length = 0; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &max_length); std::vector link_error(max_length); @@ -643,13 +731,15 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { std::unordered_map active_attributes; GLint active_attribute_total = -1; glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attribute_total); - if (active_attribute_total < 0) { + if (active_attribute_total < 0) + { glDeleteProgram(program); glDeleteShader(fragment); glDeleteShader(vertex); throw std::runtime_error("Unable to retrieve program active attributes"); } - if (desc.vertex_input.attr_layouts.size() != static_cast(active_attribute_total)) { + if (desc.vertex_input.attr_layouts.size() != static_cast(active_attribute_total)) + { glDeleteProgram(program); glDeleteShader(fragment); glDeleteShader(vertex); @@ -659,7 +749,8 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { ex_msg.append(std::to_string(static_cast(active_attribute_total))); throw std::runtime_error(std::move(ex_msg)); } - for (GLint i = 0; i < active_attribute_total; i++) { + for (GLint i = 0; i < active_attribute_total; i++) + { GLsizei name_len = 0; GLint size = 0; GLenum type = GL_ZERO; @@ -671,23 +762,29 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { std::unordered_map active_uniforms; GLint active_uniform_total = -1; glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniform_total); - if (active_uniform_total < 0) { + if (active_uniform_total < 0) + { glDeleteProgram(program); glDeleteShader(fragment); glDeleteShader(vertex); throw std::runtime_error("Unable to retrieve program active uniforms"); } - if (desc.uniform_input.enabled_uniforms.size() + desc.sampler_input.enabled_samplers.size() != static_cast(active_uniform_total)) { + if (desc.uniform_input.enabled_uniforms.size() + desc.sampler_input.enabled_samplers.size() != + static_cast(active_uniform_total)) + { glDeleteProgram(program); glDeleteShader(fragment); glDeleteShader(vertex); - std::string ex_msg("Pipeline's enabled uniform count (uniforms + samplers) does not match the linked program's total: "); + std::string ex_msg( + "Pipeline's enabled uniform count (uniforms + samplers) does not match the linked program's total: " + ); ex_msg.append(std::to_string(desc.uniform_input.enabled_uniforms.size())); ex_msg.append(" vs "); ex_msg.append(std::to_string(static_cast(active_uniform_total))); throw std::runtime_error(std::move(ex_msg)); } - for (GLint i = 0; i < active_uniform_total; i++) { + for (GLint i = 0; i < active_uniform_total; i++) + { GLsizei name_len = 0; GLint size = 0; GLenum type = GL_ZERO; @@ -696,10 +793,12 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { active_uniforms.insert({std::string(name), Gles2ActiveUniform {type, static_cast(i)}}); } - for (auto& attr : desc.vertex_input.attr_layouts) { + for (auto& attr : desc.vertex_input.attr_layouts) + { const char* symbol_name = map_vertex_attribute_symbol_name(attr.name); SRB2_ASSERT(symbol_name != nullptr); - if (active_attributes.find(symbol_name) == active_attributes.end()) { + if (active_attributes.find(symbol_name) == active_attributes.end()) + { glDeleteProgram(program); glDeleteShader(fragment); glDeleteShader(vertex); @@ -709,7 +808,8 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { auto expected_format = rhi::vertex_attribute_format(attr.name); auto expected_gl_type = map_vertex_attribute_format(expected_format); SRB2_ASSERT(expected_gl_type != GL_ZERO); - if (expected_gl_type != active_attr.type) { + if (expected_gl_type != active_attr.type) + { glDeleteProgram(program); glDeleteShader(fragment); glDeleteShader(vertex); @@ -718,10 +818,12 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { pipeline.attrib_locations.insert({attr.name, active_attr.location}); } - for (auto& uniform : desc.uniform_input.enabled_uniforms) { + for (auto& uniform : desc.uniform_input.enabled_uniforms) + { const char* symbol_name = map_uniform_attribute_symbol_name(uniform); SRB2_ASSERT(symbol_name != nullptr); - if (active_uniforms.find(symbol_name) == active_uniforms.end()) { + if (active_uniforms.find(symbol_name) == active_uniforms.end()) + { glDeleteProgram(program); glDeleteShader(fragment); glDeleteShader(vertex); @@ -731,7 +833,8 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { auto expected_format = rhi::uniform_format(uniform); auto expected_gl_type = map_uniform_format(expected_format); SRB2_ASSERT(expected_gl_type != GL_ZERO); - if (expected_gl_type != active_uniform.type) { + if (expected_gl_type != active_uniform.type) + { glDeleteProgram(program); glDeleteShader(fragment); glDeleteShader(vertex); @@ -740,17 +843,20 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { pipeline.uniform_locations.insert({uniform, active_uniform.location}); } - for (auto& sampler : desc.sampler_input.enabled_samplers) { + for (auto& sampler : desc.sampler_input.enabled_samplers) + { const char* symbol_name = map_sampler_symbol_name(sampler); SRB2_ASSERT(symbol_name != nullptr); - if (active_uniforms.find(symbol_name) == active_uniforms.end()) { + if (active_uniforms.find(symbol_name) == active_uniforms.end()) + { glDeleteProgram(program); glDeleteShader(fragment); glDeleteShader(vertex); throw std::runtime_error("Enabled sampler not found in linked program"); } auto& active_sampler = active_uniforms[symbol_name]; - if (active_sampler.type != GL_SAMPLER_2D) { + if (active_sampler.type != GL_SAMPLER_2D) + { glDeleteProgram(program); glDeleteShader(fragment); glDeleteShader(vertex); @@ -768,7 +874,8 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { return pipeline_slab_.insert(std::make_unique(std::move(pipeline))); } -void Gles2Rhi::destroy_pipeline(rhi::Handle&& handle) { +void Gles2Rhi::destroy_pipeline(rhi::Handle&& handle) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(pipeline_slab_.is_valid(handle) == true); @@ -782,13 +889,15 @@ void Gles2Rhi::destroy_pipeline(rhi::Handle&& handle) { disposal_.push_back([=] { glDeleteProgram(program); }); } -rhi::Handle Gles2Rhi::begin_graphics() { +rhi::Handle Gles2Rhi::begin_graphics() +{ SRB2_ASSERT(graphics_context_active_ == false); graphics_context_active_ = true; return rhi::Handle(0, graphics_context_generation_); } -void Gles2Rhi::end_graphics(rhi::Handle&& handle) { +void Gles2Rhi::end_graphics(rhi::Handle&& handle) +{ SRB2_ASSERT(graphics_context_active_ == true); SRB2_ASSERT(current_pipeline_.has_value() == false && current_render_pass_.has_value() == false); graphics_context_generation_ += 1; @@ -796,14 +905,16 @@ void Gles2Rhi::end_graphics(rhi::Handle&& handle) { glFlush(); } -void Gles2Rhi::present() { +void Gles2Rhi::present() +{ SRB2_ASSERT(platform_ != nullptr); SRB2_ASSERT(graphics_context_active_ == false); platform_->present(); } -void Gles2Rhi::begin_default_render_pass(Handle ctx) { +void Gles2Rhi::begin_default_render_pass(Handle ctx) +{ SRB2_ASSERT(platform_ != nullptr); SRB2_ASSERT(graphics_context_active_ == true); SRB2_ASSERT(current_render_pass_.has_value() == false); @@ -821,7 +932,8 @@ void Gles2Rhi::begin_default_render_pass(Handle ctx) { current_render_pass_ = Gles2Rhi::DefaultRenderPassState {}; } -void Gles2Rhi::begin_render_pass(Handle ctx, const RenderPassBeginInfo& info) { +void Gles2Rhi::begin_render_pass(Handle ctx, const RenderPassBeginInfo& info) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == false); @@ -830,20 +942,26 @@ void Gles2Rhi::begin_render_pass(Handle ctx, const RenderPassBe SRB2_ASSERT(rp.desc.depth_format.has_value() == info.depth_attachment.has_value()); auto fb_itr = framebuffers_.find(Gles2FramebufferKey {info.color_attachment, info.depth_attachment}); - if (fb_itr == framebuffers_.end()) { + if (fb_itr == framebuffers_.end()) + { // Create a new framebuffer for this color-depth pair GLuint fb_name; glGenFramebuffers(1, &fb_name); glBindFramebuffer(GL_FRAMEBUFFER, fb_name); - fb_itr = framebuffers_.insert( - {Gles2FramebufferKey {info.color_attachment, info.depth_attachment}, static_cast(fb_name)}).first; + fb_itr = + framebuffers_ + .insert( + {Gles2FramebufferKey {info.color_attachment, info.depth_attachment}, static_cast(fb_name)} + ) + .first; // TODO bind buffers correctly } auto& fb = *fb_itr; glBindFramebuffer(GL_FRAMEBUFFER, fb.second); - if (rp.desc.load_op == rhi::AttachmentLoadOp::kClear) { + if (rp.desc.load_op == rhi::AttachmentLoadOp::kClear) + { glClearColor(info.clear_color.r, info.clear_color.g, info.clear_color.b, info.clear_color.a); glClearDepthf(1.f); glClearStencil(0); @@ -853,7 +971,8 @@ void Gles2Rhi::begin_render_pass(Handle ctx, const RenderPassBe current_render_pass_ = info; } -void Gles2Rhi::end_render_pass(Handle ctx) { +void Gles2Rhi::end_render_pass(Handle ctx) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true); @@ -861,7 +980,8 @@ void Gles2Rhi::end_render_pass(Handle ctx) { current_render_pass_ = std::nullopt; } -void Gles2Rhi::bind_pipeline(Handle ctx, Handle pipeline) { +void Gles2Rhi::bind_pipeline(Handle ctx, Handle pipeline) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true); @@ -873,38 +993,51 @@ void Gles2Rhi::bind_pipeline(Handle ctx, Handle pipel glDisable(GL_SCISSOR_TEST); - if (desc.depth_attachment) { + if (desc.depth_attachment) + { glEnable(GL_DEPTH_TEST); GLenum depth_func = map_compare_func(desc.depth_attachment->func); SRB2_ASSERT(depth_func != GL_ZERO); glDepthFunc(depth_func); glDepthMask(desc.depth_attachment->write ? GL_TRUE : GL_FALSE); - } else { + } + else + { glDisable(GL_DEPTH_TEST); } - if (desc.color_attachment.blend) { + if (desc.color_attachment.blend) + { rhi::BlendDesc& bl = *desc.color_attachment.blend; glEnable(GL_BLEND); - glBlendFuncSeparate(map_blend_factor(bl.source_factor_color), - map_blend_factor(bl.dest_factor_color), - map_blend_factor(bl.source_factor_alpha), - map_blend_factor(bl.dest_factor_alpha)); + glBlendFuncSeparate( + map_blend_factor(bl.source_factor_color), + map_blend_factor(bl.dest_factor_color), + map_blend_factor(bl.source_factor_alpha), + map_blend_factor(bl.dest_factor_alpha) + ); glBlendEquationSeparate(map_blend_function(bl.color_function), map_blend_function(bl.alpha_function)); glBlendColor(desc.blend_color.r, desc.blend_color.g, desc.blend_color.b, desc.blend_color.a); - } else { + } + else + { glDisable(GL_BLEND); } - glColorMask(desc.color_attachment.color_mask.r ? GL_TRUE : GL_FALSE, - desc.color_attachment.color_mask.g ? GL_TRUE : GL_FALSE, - desc.color_attachment.color_mask.b ? GL_TRUE : GL_FALSE, - desc.color_attachment.color_mask.a ? GL_TRUE : GL_FALSE); + glColorMask( + desc.color_attachment.color_mask.r ? GL_TRUE : GL_FALSE, + desc.color_attachment.color_mask.g ? GL_TRUE : GL_FALSE, + desc.color_attachment.color_mask.b ? GL_TRUE : GL_FALSE, + desc.color_attachment.color_mask.a ? GL_TRUE : GL_FALSE + ); GLenum cull_face = map_cull_mode(desc.cull); - if (cull_face == GL_NONE) { + if (cull_face == GL_NONE) + { glDisable(GL_CULL_FACE); - } else { + } + else + { glEnable(GL_CULL_FACE); glCullFace(cull_face); } @@ -914,7 +1047,8 @@ void Gles2Rhi::bind_pipeline(Handle ctx, Handle pipel current_primitive_type_ = desc.primitive; } -void Gles2Rhi::update_bindings(Handle ctx, const UpdateBindingsInfo& info) { +void Gles2Rhi::update_bindings(Handle ctx, const UpdateBindingsInfo& info) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); @@ -926,7 +1060,8 @@ void Gles2Rhi::update_bindings(Handle ctx, const UpdateBindings SRB2_ASSERT(info.sampler_textures.size() == pl.desc.sampler_input.enabled_samplers.size()); // TODO only disable the vertex attributes of the previously bound pipeline (performance) - for (GLuint i = 0; i < kMaxVertexAttributes; i++) { + for (GLuint i = 0; i < kMaxVertexAttributes; i++) + { glDisableVertexAttribArray(i); } @@ -935,7 +1070,8 @@ void Gles2Rhi::update_bindings(Handle ctx, const UpdateBindings // OpenGL ES does not require binding buffers to the pipeline the same way Vulkan does. // Instead, we need to find the pipeline vertex attributes which would be affected by // the changing set of vertex buffers, and reassign their Vertex Attribute Pointers. - for (size_t i = 0; i < pl.desc.vertex_input.attr_layouts.size(); i++) { + for (size_t i = 0; i < pl.desc.vertex_input.attr_layouts.size(); i++) + { auto& attr_layout = pl.desc.vertex_input.attr_layouts[i]; uint32_t attr_buffer_index = attr_layout.buffer_index; VertexAttributeName attr_name = attr_layout.name; @@ -960,21 +1096,32 @@ void Gles2Rhi::update_bindings(Handle ctx, const UpdateBindings glBindBuffer(GL_ARRAY_BUFFER, buffer.buffer); glEnableVertexAttribArray(gl_attr_location); - glVertexAttribPointer(gl_attr_location, vertex_attr_size, vertex_attr_type, GL_FALSE, buffer_layout.stride, reinterpret_cast(vertex_buffer_offset + attr_layout.offset)); + glVertexAttribPointer( + gl_attr_location, + vertex_attr_size, + vertex_attr_type, + GL_FALSE, + buffer_layout.stride, + reinterpret_cast(vertex_buffer_offset + attr_layout.offset) + ); } rhi::Handle index_buffer_handle; std::tie(index_buffer_handle, index_buffer_offset_) = info.index_buffer; - if (index_buffer_handle == rhi::kNullHandle) { + if (index_buffer_handle == rhi::kNullHandle) + { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } else { + } + else + { SRB2_ASSERT(buffer_slab_.is_valid(index_buffer_handle)); auto& ib = *static_cast(&buffer_slab_[index_buffer_handle]); SRB2_ASSERT(ib.desc.type == rhi::BufferType::kIndexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib.buffer); } - for (size_t i = 0; i < info.sampler_textures.size(); i++) { + for (size_t i = 0; i < info.sampler_textures.size(); i++) + { auto& sampler_name = pl.desc.sampler_input.enabled_samplers[i]; rhi::Handle texture_handle = info.sampler_textures[i]; SRB2_ASSERT(texture_slab_.is_valid(texture_handle)); @@ -985,7 +1132,8 @@ void Gles2Rhi::update_bindings(Handle ctx, const UpdateBindings GLenum active_texture = GL_TEXTURE0; GLuint uniform_value = 0; - switch (sampler_name) { + switch (sampler_name) + { case rhi::SamplerName::kSampler0: active_texture = GL_TEXTURE0; uniform_value = 0; @@ -1009,7 +1157,8 @@ void Gles2Rhi::update_bindings(Handle ctx, const UpdateBindings } } -void Gles2Rhi::update_uniforms(Handle ctx, tcb::span uniforms) { +void Gles2Rhi::update_uniforms(Handle ctx, tcb::span uniforms) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); @@ -1021,58 +1170,71 @@ void Gles2Rhi::update_uniforms(Handle ctx, tcb::span& value) const noexcept { + void operator()(const std::array& value) const noexcept + { SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kFloat2); glUniform2f(uniform, value[0], value[1]); } - void operator()(const std::array& value) const noexcept { + void operator()(const std::array& value) const noexcept + { SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kFloat3); glUniform3f(uniform, value[0], value[1], value[2]); } - void operator()(const std::array& value) const noexcept { + void operator()(const std::array& value) const noexcept + { SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kFloat4); glUniform4f(uniform, value[0], value[1], value[2], value[3]); } - void operator()(const int32_t& value) const noexcept { + void operator()(const int32_t& value) const noexcept + { SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kInt); glUniform1i(uniform, value); } - void operator()(const std::array& value) const noexcept { + void operator()(const std::array& value) const noexcept + { SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kInt2); glUniform2i(uniform, value[0], value[1]); } - void operator()(const std::array& value) const noexcept { + void operator()(const std::array& value) const noexcept + { SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kInt3); glUniform3i(uniform, value[0], value[1], value[2]); } - void operator()(const std::array& value) const noexcept { + void operator()(const std::array& value) const noexcept + { SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kInt4); glUniform4i(uniform, value[0], value[1], value[2], value[3]); } - void operator()(const std::array, 2>& value) const noexcept { + void operator()(const std::array, 2>& value) const noexcept + { SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kMat2); glUniformMatrix2fv(uniform, 1, false, reinterpret_cast(&value)); } - void operator()(const std::array, 3>& value) const noexcept { + void operator()(const std::array, 3>& value) const noexcept + { SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kMat3); glUniformMatrix3fv(uniform, 1, false, reinterpret_cast(&value)); } - void operator()(const std::array, 4>& value) const noexcept { + void operator()(const std::array, 4>& value) const noexcept + { SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kMat4); glUniformMatrix4fv(uniform, 1, false, reinterpret_cast(&value)); } @@ -1081,42 +1243,56 @@ void Gles2Rhi::update_uniforms(Handle ctx, tcb::span ctx, const Rect& rect) { +void Gles2Rhi::set_scissor(Handle ctx, const Rect& rect) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); // TODO handle scissor pipeline state } -void Gles2Rhi::set_viewport(Handle ctx, const Rect& rect) { +void Gles2Rhi::set_viewport(Handle ctx, const Rect& rect) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); // TODO handle viewport pipeline state } -void Gles2Rhi::draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) { +void Gles2Rhi::draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); glDrawArrays(map_primitive_mode(current_primitive_type_), first_vertex, vertex_count); } -void Gles2Rhi::draw_indexed(Handle ctx, - uint32_t index_count, - uint32_t first_index, - uint32_t vertex_offset) { +void Gles2Rhi::draw_indexed( + Handle ctx, + uint32_t index_count, + uint32_t first_index, + uint32_t vertex_offset +) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); - glDrawElements(map_primitive_mode(current_primitive_type_), first_index, GL_UNSIGNED_SHORT, reinterpret_cast(index_buffer_offset_)); + glDrawElements( + map_primitive_mode(current_primitive_type_), + first_index, + GL_UNSIGNED_SHORT, + reinterpret_cast(index_buffer_offset_) + ); } -void Gles2Rhi::finish() { +void Gles2Rhi::finish() +{ SRB2_ASSERT(graphics_context_active_ == false); - for (auto it = disposal_.begin(); it != disposal_.end(); it++) { + for (auto it = disposal_.begin(); it != disposal_.end(); it++) + { (*it)(); } disposal_.clear(); } -void rhi::load_gles2(Gles2LoadFunc func) { +void rhi::load_gles2(Gles2LoadFunc func) +{ gladLoadGLES2(static_cast(func)); } diff --git a/src/rhi/gles2/gles2_rhi.hpp b/src/rhi/gles2/gles2_rhi.hpp index 4f19aa7c5..9858e770b 100644 --- a/src/rhi/gles2/gles2_rhi.hpp +++ b/src/rhi/gles2/gles2_rhi.hpp @@ -11,19 +11,17 @@ #include "../rhi.hpp" -namespace srb2::rhi { +namespace srb2::rhi +{ -struct Gles2FramebufferKey { +struct Gles2FramebufferKey +{ TextureOrRenderbuffer color; std::optional depth; - bool operator==(const Gles2FramebufferKey& rhs) const noexcept { - return color == rhs.color && depth == rhs.depth; - } + bool operator==(const Gles2FramebufferKey& rhs) const noexcept { return color == rhs.color && depth == rhs.depth; } - bool operator!=(const Gles2FramebufferKey& rhs) const noexcept { - return !(*this == rhs); - } + bool operator!=(const Gles2FramebufferKey& rhs) const noexcept { return !(*this == rhs); } }; } // namespace srb2::rhi @@ -32,29 +30,37 @@ struct Gles2FramebufferKey { // we need to split the namespace declarations _before_ the instantiation of std::unordered_map. template <> -struct std::hash { - std::size_t operator()(const srb2::rhi::Gles2FramebufferKey& key) const { - struct GetHandleHashVisitor { - uint32_t operator()(const srb2::rhi::Handle& handle) const noexcept { +struct std::hash +{ + std::size_t operator()(const srb2::rhi::Gles2FramebufferKey& key) const + { + struct GetHandleHashVisitor + { + uint32_t operator()(const srb2::rhi::Handle& handle) const noexcept + { return std::hash>()(handle); } - uint32_t operator()(const srb2::rhi::Handle& handle) const noexcept { + uint32_t operator()(const srb2::rhi::Handle& handle) const noexcept + { return std::hash>()(handle); } }; std::size_t color_hash = std::visit(GetHandleHashVisitor {}, key.color); std::size_t depth_hash = 0; - if (key.depth) { + if (key.depth) + { depth_hash = std::visit(GetHandleHashVisitor {}, *key.depth); } return color_hash ^ (depth_hash << 1); } }; -namespace srb2::rhi { +namespace srb2::rhi +{ /// @brief Platform-specific implementation details for the GLES2 backend. -struct Gles2Platform { +struct Gles2Platform +{ virtual ~Gles2Platform(); virtual void present() = 0; @@ -62,7 +68,8 @@ struct Gles2Platform { virtual Rect get_default_framebuffer_dimensions() = 0; }; -class Gles2Rhi final : public Rhi { +class Gles2Rhi final : public Rhi +{ std::unique_ptr platform_; Slab render_pass_slab_; @@ -73,7 +80,9 @@ class Gles2Rhi final : public Rhi { std::unordered_map framebuffers_ {16}; - struct DefaultRenderPassState {}; + struct DefaultRenderPassState + { + }; using RenderPassState = std::variant; std::optional current_render_pass_; std::optional> current_pipeline_; @@ -90,7 +99,9 @@ public: virtual Handle create_render_pass(const RenderPassDesc& desc) override; virtual void destroy_render_pass(Handle&& handle) override; - virtual Handle create_texture(const TextureDesc& desc, srb2::rhi::PixelFormat data_format, tcb::span data) override; + virtual Handle + create_texture(const TextureDesc& desc, srb2::rhi::PixelFormat data_format, tcb::span data) + override; virtual void destroy_texture(Handle&& handle) override; virtual Handle create_buffer(const BufferDesc& desc, tcb::span data) override; virtual void destroy_buffer(Handle&& handle) override; @@ -99,8 +110,14 @@ public: virtual Handle create_pipeline(const PipelineDesc& desc) override; virtual void destroy_pipeline(Handle&& handle) override; - virtual void update_buffer_contents(Handle buffer, uint32_t offset, tcb::span data) override; - virtual void update_texture(Handle texture, Rect region, srb2::rhi::PixelFormat data_format, tcb::span data) override; + virtual void + update_buffer_contents(Handle buffer, uint32_t offset, tcb::span data) override; + virtual void update_texture( + Handle texture, + Rect region, + srb2::rhi::PixelFormat data_format, + tcb::span data + ) override; virtual Handle begin_graphics() override; virtual void end_graphics(Handle&& ctx) override; @@ -115,10 +132,9 @@ public: virtual void set_scissor(Handle ctx, const Rect& rect) override; virtual void set_viewport(Handle ctx, const Rect& rect) override; virtual void draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) override; - virtual void draw_indexed(Handle ctx, - uint32_t index_count, - uint32_t first_index, - uint32_t vertex_offset) override; + virtual void + draw_indexed(Handle ctx, uint32_t index_count, uint32_t first_index, uint32_t vertex_offset) + override; virtual void present() override; diff --git a/src/rhi/handle.hpp b/src/rhi/handle.hpp index 7a780d8ca..110783538 100644 --- a/src/rhi/handle.hpp +++ b/src/rhi/handle.hpp @@ -10,35 +10,40 @@ #include "../cxxutil.hpp" -namespace srb2::rhi { +namespace srb2::rhi +{ -struct NullHandleType {}; +struct NullHandleType +{ +}; constexpr const NullHandleType kNullHandle = NullHandleType {}; template -class Handle { +class Handle +{ uint32_t id_; uint32_t generation_; public: Handle(uint32_t id, uint32_t generation) noexcept : id_(id), generation_(generation) {} - Handle(uint64_t combined) noexcept - : id_(combined & 0xFFFFFFFF) - , generation_((combined & 0xFFFFFFFF00000000) >> 32) - {} + Handle(uint64_t combined) noexcept : id_(combined & 0xFFFFFFFF), generation_((combined & 0xFFFFFFFF00000000) >> 32) + { + } Handle() noexcept : Handle(0, 0) {} Handle(NullHandleType) noexcept : Handle() {} Handle(const Handle&) = default; - Handle(Handle&& rhs) noexcept { + Handle(Handle&& rhs) noexcept + { id_ = std::exchange(rhs.id_, 0); generation_ = std::exchange(rhs.generation_, 0); }; Handle& operator=(const Handle&) = default; - Handle& operator=(Handle&& rhs) noexcept { + Handle& operator=(Handle&& rhs) noexcept + { id_ = std::exchange(rhs.id_, 0); generation_ = std::exchange(rhs.generation_, 0); return *this; @@ -47,22 +52,27 @@ public: // Conversions from Handles of derived type U to base type T template , bool> = true> - Handle(const Handle& rhs) noexcept : id_(rhs.id_), generation_(rhs.generation_) {} + Handle(const Handle& rhs) noexcept : id_(rhs.id_), generation_(rhs.generation_) + { + } template , bool> = true> - Handle(Handle&& rhs) noexcept { + Handle(Handle&& rhs) noexcept + { id_ = std::exchange(rhs.id_, 0); generation_ = std::exchange(rhs.generation_, 0); } template , bool> = true> - Handle& operator=(const Handle& rhs) noexcept { + Handle& operator=(const Handle& rhs) noexcept + { id_ = rhs.id_; generation_ = rhs.generation_; } template , bool> = true> - Handle& operator=(Handle&& rhs) noexcept { + Handle& operator=(Handle&& rhs) noexcept + { id_ = std::exchange(rhs.id_, 0); generation_ = std::exchange(rhs.generation_, 0); return *this; @@ -74,7 +84,8 @@ public: /// @return true if this Handle is valid (belonging to a generation > 0); false otherwise bool valid() const noexcept { return generation_ != 0; } - bool operator==(const Handle& handle) const noexcept { + bool operator==(const Handle& handle) const noexcept + { return handle.generation_ == generation_ && handle.id_ == id_; } bool operator!=(const Handle& handle) const noexcept { return !(handle == *this); } @@ -100,17 +111,20 @@ inline bool operator==(const Handle& lhs, const std::nullptr_t&) noexcept // Non-member equality of base Handle to derived Handle template , bool> = true> -inline bool operator==(const Handle& lhs, const Handle& rhs) noexcept { +inline bool operator==(const Handle& lhs, const Handle& rhs) noexcept +{ return lhs.generation() == rhs.generation() && lhs.id() == rhs.id(); } template , bool> = true> -inline bool operator!=(const Handle& lhs, const Handle& rhs) noexcept { +inline bool operator!=(const Handle& lhs, const Handle& rhs) noexcept +{ return !(lhs == rhs); } template -class HandlePool { +class HandlePool +{ std::atomic_uint32_t current_id_ {0}; std::atomic_uint32_t current_gen_ {1}; @@ -124,7 +138,8 @@ public: /// @brief Create a new unique Handle in the current generation. /// @return the new Handle. - Handle create() noexcept { + Handle create() noexcept + { const uint32_t id = current_id_.fetch_add(1); SRB2_ASSERT(id != UINT32_MAX); const uint32_t gen = current_gen_.load(); @@ -132,7 +147,8 @@ public: } /// @brief Increment the generation. All handles created after this will belong to a new generation. - void generation() noexcept { + void generation() noexcept + { const uint32_t old_gen = current_gen_.fetch_add(1); SRB2_ASSERT(old_gen != UINT32_MAX); } @@ -150,6 +166,7 @@ class SlabIterator SlabIterator(size_t index, const Slab>* slab) : index_(index), slab_(slab) {} friend Slab>; + public: SlabIterator() = default; SlabIterator(const SlabIterator&) = default; @@ -158,10 +175,7 @@ public: SlabIterator& operator=(const SlabIterator&) = default; SlabIterator& operator=(SlabIterator&&) = default; - T& operator*() const noexcept - { - return *slab_->vec_[index_].item.get(); - } + T& operator*() const noexcept { return *slab_->vec_[index_].item.get(); } SlabIterator& operator++() noexcept { @@ -187,20 +201,16 @@ public: return SlabIterator {index_ + 1, slab_}; } - bool operator==(const SlabIterator& rhs) const noexcept - { - return slab_ == rhs.slab_ && index_ == rhs.index_; - } + bool operator==(const SlabIterator& rhs) const noexcept { return slab_ == rhs.slab_ && index_ == rhs.index_; } - bool operator!=(const SlabIterator& rhs) const noexcept - { - return !(*this == rhs); - } + bool operator!=(const SlabIterator& rhs) const noexcept { return !(*this == rhs); } }; template -class Slab { - struct SlabStorage { +class Slab +{ + struct SlabStorage + { std::unique_ptr item; uint32_t gen; }; @@ -210,34 +220,42 @@ class Slab { friend SlabIterator; friend SlabIterator; + public: Slab() = default; Slab(const Slab&) = delete; Slab& operator=(const Slab&) = delete; - Handle insert(std::unique_ptr&& value) { + Handle insert(std::unique_ptr&& value) + { uint32_t ret_id = 0; - if (!free_list_.empty()) { + if (!free_list_.empty()) + { ret_id = free_list_.back(); free_list_.pop_back(); SlabStorage& storage = vec_[ret_id]; storage.item = std::move(value); storage.gen = gen_; - } else { + } + else + { ret_id = vec_.size(); vec_.push_back(SlabStorage {std::move(value), gen_}); } return Handle(ret_id, gen_); } - std::unique_ptr remove(Handle handle) { + std::unique_ptr remove(Handle handle) + { uint32_t handle_id = handle.id(); uint32_t handle_gen = handle.generation(); - if (handle_id >= vec_.size()) { + if (handle_id >= vec_.size()) + { return nullptr; } SlabStorage& storage = vec_[handle_id]; - if (storage.gen > handle_gen) { + if (storage.gen > handle_gen) + { return nullptr; } std::unique_ptr ret = std::move(storage.item); @@ -251,14 +269,17 @@ public: return ret; } - bool is_valid(Handle handle) { + bool is_valid(Handle handle) + { uint32_t handle_id = handle.id(); uint32_t handle_gen = handle.generation(); - if (handle_id >= vec_.size()) { + if (handle_id >= vec_.size()) + { return false; } SlabStorage& storage = vec_[handle_id]; - if (storage.gen > handle_gen) { + if (storage.gen > handle_gen) + { return false; } return true; @@ -275,39 +296,31 @@ public: } } - T& operator[](Handle handle) { + T& operator[](Handle handle) + { SRB2_ASSERT(is_valid(handle)); return *vec_[handle.id()].item; } - SlabIterator begin() - { - return SlabIterator {0, this}; - } + SlabIterator begin() { return SlabIterator {0, this}; } - SlabIterator end() - { - return SlabIterator {vec_.size(), this}; - } + SlabIterator end() { return SlabIterator {vec_.size(), this}; } - SlabIterator cbegin() const - { - return SlabIterator {0, this}; - } + SlabIterator cbegin() const { return SlabIterator {0, this}; } - SlabIterator cend() const - { - return SlabIterator {vec_.size(), this}; - } + SlabIterator cend() const { return SlabIterator {vec_.size(), this}; } }; } // namespace srb2::rhi -namespace std { +namespace std +{ template -struct hash> { - std::size_t operator()(const srb2::rhi::Handle& e) const { +struct hash> +{ + std::size_t operator()(const srb2::rhi::Handle& e) const + { return std::hash()(e.generation()) ^ (std::hash()(e.id()) << 1); } }; diff --git a/src/rhi/rhi.cpp b/src/rhi/rhi.cpp index c5fd0b973..c63282b95 100644 --- a/src/rhi/rhi.cpp +++ b/src/rhi/rhi.cpp @@ -9,38 +9,28 @@ using namespace srb2::rhi; Rhi::~Rhi() = default; const ProgramRequirements srb2::rhi::kProgramRequirementsUnshaded = { - ProgramVertexInputRequirements {{ - ProgramVertexInput {VertexAttributeName::kPosition, VertexAttributeFormat::kFloat3, true}, - ProgramVertexInput {VertexAttributeName::kTexCoord0, VertexAttributeFormat::kFloat2, false}, - ProgramVertexInput {VertexAttributeName::kColor, VertexAttributeFormat::kFloat4, false} - }}, - ProgramUniformRequirements {{ - {{UniformName::kProjection}}, - {{UniformName::kModelView, UniformName::kTexCoord0Transform}} - }}, - ProgramSamplerRequirements {{ - ProgramSamplerInput {SamplerName::kSampler0, true} - }} -}; + ProgramVertexInputRequirements { + {ProgramVertexInput {VertexAttributeName::kPosition, VertexAttributeFormat::kFloat3, true}, + ProgramVertexInput {VertexAttributeName::kTexCoord0, VertexAttributeFormat::kFloat2, false}, + ProgramVertexInput {VertexAttributeName::kColor, VertexAttributeFormat::kFloat4, false}}}, + ProgramUniformRequirements { + {{{UniformName::kProjection}}, {{UniformName::kModelView, UniformName::kTexCoord0Transform}}}}, + ProgramSamplerRequirements {{ProgramSamplerInput {SamplerName::kSampler0, true}}}}; const ProgramRequirements srb2::rhi::kProgramRequirementsUnshadedPaletted = { - ProgramVertexInputRequirements {{ - ProgramVertexInput {VertexAttributeName::kPosition, VertexAttributeFormat::kFloat3, true}, - ProgramVertexInput {VertexAttributeName::kTexCoord0, VertexAttributeFormat::kFloat2, false}, - ProgramVertexInput {VertexAttributeName::kColor, VertexAttributeFormat::kFloat4, false} - }}, - ProgramUniformRequirements {{ - {{UniformName::kProjection}}, - {{UniformName::kModelView, UniformName::kTexCoord0Transform}} - }}, - ProgramSamplerRequirements {{ - ProgramSamplerInput {SamplerName::kSampler0, true}, - ProgramSamplerInput {SamplerName::kSampler1, true} - }} -}; + ProgramVertexInputRequirements { + {ProgramVertexInput {VertexAttributeName::kPosition, VertexAttributeFormat::kFloat3, true}, + ProgramVertexInput {VertexAttributeName::kTexCoord0, VertexAttributeFormat::kFloat2, false}, + ProgramVertexInput {VertexAttributeName::kColor, VertexAttributeFormat::kFloat4, false}}}, + ProgramUniformRequirements { + {{{UniformName::kProjection}}, {{UniformName::kModelView, UniformName::kTexCoord0Transform}}}}, + ProgramSamplerRequirements { + {ProgramSamplerInput {SamplerName::kSampler0, true}, ProgramSamplerInput {SamplerName::kSampler1, true}}}}; -const ProgramRequirements& rhi::program_requirements_for_program(PipelineProgram program) noexcept { - switch (program) { +const ProgramRequirements& rhi::program_requirements_for_program(PipelineProgram program) noexcept +{ + switch (program) + { case PipelineProgram::kUnshaded: return kProgramRequirementsUnshaded; case PipelineProgram::kUnshadedPaletted: diff --git a/src/rhi/rhi.hpp b/src/rhi/rhi.hpp index 1da54fbf0..a44423aee 100644 --- a/src/rhi/rhi.hpp +++ b/src/rhi/rhi.hpp @@ -12,28 +12,41 @@ #include "../core/static_vec.hpp" #include "handle.hpp" -namespace srb2::rhi { +namespace srb2::rhi +{ -struct Buffer {}; +struct Buffer +{ +}; -struct Texture {}; +struct Texture +{ +}; -struct Pipeline {}; +struct Pipeline +{ +}; -struct RenderPass {}; +struct RenderPass +{ +}; -struct Renderbuffer {}; +struct Renderbuffer +{ +}; using TextureOrRenderbuffer = std::variant, Handle>; -enum class VertexAttributeFormat { +enum class VertexAttributeFormat +{ kFloat, kFloat2, kFloat3, kFloat4 }; -enum class UniformFormat { +enum class UniformFormat +{ kFloat, kFloat2, kFloat3, @@ -47,20 +60,23 @@ enum class UniformFormat { kMat4 }; -enum class PixelFormat { +enum class PixelFormat +{ kR8, kRGBA8, kDepth16, kStencil8 }; -enum class TextureFormat { +enum class TextureFormat +{ kLuminance, kRGB, kRGBA }; -enum class CompareFunc { +enum class CompareFunc +{ kNever, kLess, kEqual, @@ -71,7 +87,8 @@ enum class CompareFunc { kAlways }; -enum class BlendFactor { +enum class BlendFactor +{ kZero, kOne, kSource, @@ -89,13 +106,15 @@ enum class BlendFactor { kSourceAlphaSaturated }; -enum class BlendFunction { +enum class BlendFunction +{ kAdd, kSubtract, kReverseSubtract }; -enum class PrimitiveType { +enum class PrimitiveType +{ kPoints, kLines, kLineStrip, @@ -104,44 +123,52 @@ enum class PrimitiveType { kTriangleFan }; -enum class CullMode { +enum class CullMode +{ kNone, kFront, kBack }; -enum class FaceWinding { +enum class FaceWinding +{ kCounterClockwise, kClockwise }; -enum class AttachmentLoadOp { +enum class AttachmentLoadOp +{ kLoad, kClear, kDontCare }; -enum class AttachmentStoreOp { +enum class AttachmentStoreOp +{ kStore, kDontCare }; -enum class PipelineProgram { +enum class PipelineProgram +{ kUnshaded, kUnshadedPaletted }; -enum class BufferType { +enum class BufferType +{ kVertexBuffer, kIndexBuffer }; -enum class BufferUsage { +enum class BufferUsage +{ kImmutable, kDynamic }; -enum class VertexAttributeName { +enum class VertexAttributeName +{ kPosition, kNormal, kTexCoord0, @@ -149,28 +176,32 @@ enum class VertexAttributeName { kColor }; -enum class UniformName { +enum class UniformName +{ kTime, kModelView, kProjection, kTexCoord0Transform }; -enum class SamplerName { +enum class SamplerName +{ kSampler0, kSampler1, kSampler2, kSampler3 }; -struct Color { +struct Color +{ float r; float g; float b; float a; }; -struct Rect { +struct Rect +{ int32_t x; int32_t y; uint32_t w; @@ -180,35 +211,42 @@ struct Rect { constexpr const size_t kMaxVertexAttributes = 8; constexpr const size_t kMaxSamplers = 4; -struct ProgramVertexInput { +struct ProgramVertexInput +{ VertexAttributeName name; VertexAttributeFormat type; bool required; }; -struct ProgramUniformInput { +struct ProgramUniformInput +{ UniformName name; bool required; }; -struct ProgramSamplerInput { +struct ProgramSamplerInput +{ SamplerName name; bool required; }; -struct ProgramVertexInputRequirements { +struct ProgramVertexInputRequirements +{ srb2::StaticVec attributes; }; -struct ProgramUniformRequirements { +struct ProgramUniformRequirements +{ srb2::StaticVec, 4> uniform_groups; }; -struct ProgramSamplerRequirements { +struct ProgramSamplerRequirements +{ std::array, kMaxSamplers> samplers; }; -struct ProgramRequirements { +struct ProgramRequirements +{ ProgramVertexInputRequirements vertex_input; ProgramUniformRequirements uniforms; ProgramSamplerRequirements samplers; @@ -221,7 +259,8 @@ const ProgramRequirements& program_requirements_for_program(PipelineProgram prog inline constexpr const VertexAttributeFormat vertex_attribute_format(VertexAttributeName name) noexcept { - switch (name) { + switch (name) + { case VertexAttributeName::kPosition: return VertexAttributeFormat::kFloat3; case VertexAttributeName::kNormal: @@ -239,7 +278,8 @@ inline constexpr const VertexAttributeFormat vertex_attribute_format(VertexAttri inline constexpr const UniformFormat uniform_format(UniformName name) noexcept { - switch (name) { + switch (name) + { case UniformName::kTime: return UniformFormat::kFloat; case UniformName::kModelView: @@ -253,11 +293,13 @@ inline constexpr const UniformFormat uniform_format(UniformName name) noexcept } } -struct VertexBufferLayoutDesc { +struct VertexBufferLayoutDesc +{ uint32_t stride; }; -struct VertexAttributeLayoutDesc { +struct VertexAttributeLayoutDesc +{ VertexAttributeName name; uint32_t buffer_index; uint32_t offset; @@ -265,27 +307,32 @@ struct VertexAttributeLayoutDesc { // constexpr const size_t kMaxVertexBufferBindings = 4; -struct VertexInputDesc { +struct VertexInputDesc +{ std::vector buffer_layouts; std::vector attr_layouts; }; -struct UniformInputDesc { +struct UniformInputDesc +{ srb2::StaticVec, 4> enabled_uniforms; }; -struct SamplerInputDesc { +struct SamplerInputDesc +{ std::vector enabled_samplers; }; -struct ColorMask { +struct ColorMask +{ bool r; bool g; bool b; bool a; }; -struct BlendDesc { +struct BlendDesc +{ BlendFactor source_factor_color; BlendFactor dest_factor_color; BlendFunction color_function; @@ -294,19 +341,22 @@ struct BlendDesc { BlendFunction alpha_function; }; -struct PipelineDepthAttachmentDesc { +struct PipelineDepthAttachmentDesc +{ PixelFormat format; CompareFunc func; bool write; }; -struct PipelineColorAttachmentDesc { +struct PipelineColorAttachmentDesc +{ PixelFormat format; std::optional blend; ColorMask color_mask; }; -struct PipelineDesc { +struct PipelineDesc +{ PipelineProgram program; VertexInputDesc vertex_input; UniformInputDesc uniform_input; @@ -320,32 +370,37 @@ struct PipelineDesc { Color blend_color; }; -struct RenderPassDesc { +struct RenderPassDesc +{ std::optional depth_format; PixelFormat color_format; AttachmentLoadOp load_op; AttachmentStoreOp store_op; }; -struct RenderbufferDesc { +struct RenderbufferDesc +{ PixelFormat format; uint32_t width; uint32_t height; }; -struct TextureDesc { +struct TextureDesc +{ TextureFormat format; uint32_t width; uint32_t height; }; -struct BufferDesc { +struct BufferDesc +{ uint32_t size; BufferType type; BufferUsage usage; }; -struct RenderPassBeginInfo { +struct RenderPassBeginInfo +{ Handle render_pass; TextureOrRenderbuffer color_attachment; std::optional depth_attachment; @@ -367,8 +422,7 @@ using UniformVariant = std::variant< std::array, 2>, std::array, 3>, - std::array, 4> ->; + std::array, 4>>; inline constexpr UniformFormat uniform_variant_format(const UniformVariant& variant) { @@ -382,40 +436,62 @@ inline constexpr UniformFormat uniform_variant_format(const UniformVariant& vari UniformFormat operator()(const std::array&) const noexcept { return UniformFormat::kInt2; } UniformFormat operator()(const std::array&) const noexcept { return UniformFormat::kInt3; } UniformFormat operator()(const std::array&) const noexcept { return UniformFormat::kInt4; } - UniformFormat operator()(const std::array, 2>&) const noexcept { return UniformFormat::kMat2; } - UniformFormat operator()(const std::array, 3>&) const noexcept { return UniformFormat::kMat3; } - UniformFormat operator()(const std::array, 4>&) const noexcept { return UniformFormat::kMat4; } + UniformFormat operator()(const std::array, 2>&) const noexcept + { + return UniformFormat::kMat2; + } + UniformFormat operator()(const std::array, 3>&) const noexcept + { + return UniformFormat::kMat3; + } + UniformFormat operator()(const std::array, 4>&) const noexcept + { + return UniformFormat::kMat4; + } }; - return std::visit(Visitor{}, variant); + return std::visit(Visitor {}, variant); } -struct VertexAttributeBufferBinding { +struct VertexAttributeBufferBinding +{ uint32_t attribute_index; Handle vertex_buffer; }; -struct TextureBinding { +struct TextureBinding +{ SamplerName name; Handle texture; }; -struct CreateUniformSetInfo { +struct CreateUniformSetInfo +{ tcb::span uniforms; }; -struct CreateBindingSetInfo { +struct CreateBindingSetInfo +{ tcb::span vertex_buffers; tcb::span sampler_textures; }; -struct UniformSet {}; -struct BindingSet {}; +struct UniformSet +{ +}; +struct BindingSet +{ +}; -struct TransferContext {}; -struct GraphicsContext {}; +struct TransferContext +{ +}; +struct GraphicsContext +{ +}; /// @brief An active handle to a rendering device. -struct Rhi { +struct Rhi +{ virtual ~Rhi(); virtual Handle create_render_pass(const RenderPassDesc& desc) = 0; @@ -434,10 +510,22 @@ struct Rhi { virtual void end_transfer(Handle handle) = 0; // Transfer Context functions - virtual void update_buffer_contents(Handle ctx, Handle buffer, uint32_t offset, tcb::span data) = 0; - virtual void update_texture(Handle ctx, Handle texture, Rect region, srb2::rhi::PixelFormat data_format, tcb::span data) = 0; + virtual void update_buffer_contents( + Handle ctx, + Handle buffer, + uint32_t offset, + tcb::span data + ) = 0; + virtual void update_texture( + Handle ctx, + Handle texture, + Rect region, + srb2::rhi::PixelFormat data_format, + tcb::span data + ) = 0; virtual Handle create_uniform_set(Handle ctx, const CreateUniformSetInfo& info) = 0; - virtual Handle create_binding_set(Handle ctx, Handle pipeline, const CreateBindingSetInfo& info) = 0; + virtual Handle + create_binding_set(Handle ctx, Handle pipeline, const CreateBindingSetInfo& info) = 0; virtual Handle begin_graphics() = 0; virtual void end_graphics(Handle ctx) = 0; diff --git a/src/sdl/rhi_gl3_core_platform.cpp b/src/sdl/rhi_gl3_core_platform.cpp index e6971873d..d8c0cde33 100644 --- a/src/sdl/rhi_gl3_core_platform.cpp +++ b/src/sdl/rhi_gl3_core_platform.cpp @@ -11,17 +11,20 @@ using namespace srb2::rhi; SdlGlCorePlatform::~SdlGlCorePlatform() = default; -void SdlGlCorePlatform::present() { +void SdlGlCorePlatform::present() +{ SRB2_ASSERT(window != nullptr); SRB2_ASSERT(SDL_GetWindowID(window) != 0); SDL_GL_SwapWindow(window); } -std::tuple SdlGlCorePlatform::find_shader_sources(rhi::PipelineProgram program) { +std::tuple SdlGlCorePlatform::find_shader_sources(rhi::PipelineProgram program) +{ const char* vertex_lump_name = nullptr; const char* fragment_lump_name = nullptr; - switch (program) { + switch (program) + { case rhi::PipelineProgram::kUnshaded: vertex_lump_name = "rhi_glcore_vertex_unshaded"; fragment_lump_name = "rhi_glcore_fragment_unshaded"; @@ -47,7 +50,8 @@ std::tuple SdlGlCorePlatform::find_shader_sources(rhi: return std::make_tuple(std::move(vertex_shader), std::move(fragment_shader)); } -rhi::Rect SdlGlCorePlatform::get_default_framebuffer_dimensions() { +rhi::Rect SdlGlCorePlatform::get_default_framebuffer_dimensions() +{ SRB2_ASSERT(window != nullptr); int w; int h; diff --git a/src/sdl/rhi_gl3_core_platform.hpp b/src/sdl/rhi_gl3_core_platform.hpp index 0683a428b..0c0f6f4f3 100644 --- a/src/sdl/rhi_gl3_core_platform.hpp +++ b/src/sdl/rhi_gl3_core_platform.hpp @@ -1,14 +1,16 @@ #ifndef __SRB2_SDL_RHI_GLES2_PLATFORM_HPP__ #define __SRB2_SDL_RHI_GLES2_PLATFORM_HPP__ -#include "../rhi/rhi.hpp" #include "../rhi/gl3_core/gl3_core_rhi.hpp" +#include "../rhi/rhi.hpp" #include -namespace srb2::rhi { +namespace srb2::rhi +{ -struct SdlGlCorePlatform final : public GlCorePlatform { +struct SdlGlCorePlatform final : public GlCorePlatform +{ SDL_Window* window = nullptr; virtual ~SdlGlCorePlatform(); diff --git a/src/sdl/rhi_gles2_platform.cpp b/src/sdl/rhi_gles2_platform.cpp index d9d8546e5..d91a3d2bf 100644 --- a/src/sdl/rhi_gles2_platform.cpp +++ b/src/sdl/rhi_gles2_platform.cpp @@ -11,17 +11,20 @@ using namespace srb2::rhi; SdlGles2Platform::~SdlGles2Platform() = default; -void SdlGles2Platform::present() { +void SdlGles2Platform::present() +{ SRB2_ASSERT(window != nullptr); SRB2_ASSERT(SDL_GetWindowID(window) != 0); SDL_GL_SwapWindow(window); } -std::tuple SdlGles2Platform::find_shader_sources(rhi::PipelineProgram program) { +std::tuple SdlGles2Platform::find_shader_sources(rhi::PipelineProgram program) +{ const char* vertex_lump_name = nullptr; const char* fragment_lump_name = nullptr; - switch (program) { + switch (program) + { case rhi::PipelineProgram::kUnshaded: vertex_lump_name = "rhi_glsles_vertex_unshaded"; fragment_lump_name = "rhi_glsles_fragment_unshaded"; @@ -47,7 +50,8 @@ std::tuple SdlGles2Platform::find_shader_sources(rhi:: return std::make_tuple(std::move(vertex_shader), std::move(fragment_shader)); } -rhi::Rect SdlGles2Platform::get_default_framebuffer_dimensions() { +rhi::Rect SdlGles2Platform::get_default_framebuffer_dimensions() +{ SRB2_ASSERT(window != nullptr); int w; int h; diff --git a/src/sdl/rhi_gles2_platform.hpp b/src/sdl/rhi_gles2_platform.hpp index 0476931d0..19970d8f1 100644 --- a/src/sdl/rhi_gles2_platform.hpp +++ b/src/sdl/rhi_gles2_platform.hpp @@ -1,14 +1,16 @@ #ifndef __SRB2_SDL_RHI_GLES2_PLATFORM_HPP__ #define __SRB2_SDL_RHI_GLES2_PLATFORM_HPP__ -#include "../rhi/rhi.hpp" #include "../rhi/gles2/gles2_rhi.hpp" +#include "../rhi/rhi.hpp" #include -namespace srb2::rhi { +namespace srb2::rhi +{ -struct SdlGles2Platform final : public Gles2Platform { +struct SdlGles2Platform final : public Gles2Platform +{ SDL_Window* window = nullptr; virtual ~SdlGles2Platform(); From 610e2c66be226aa07b0cf8d139e91b8b1994e3f5 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 14 Jan 2023 18:11:46 -0800 Subject: [PATCH 22/32] Adjust Garden Top physics - 110% -> 150% top speed - no friction decrease if grinding - 250% -> 300% gravity when grinding (for slope sliding) - 275% -> 325% max boost when releasing grind - 60% minimum boost speed when relasing grind --- src/k_kart.c | 6 ++++-- src/p_mobj.c | 2 +- src/p_user.c | 5 +++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 6debceecf..694425773 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3386,7 +3386,7 @@ fixed_t K_GetNewSpeed(player_t *player) if (player->curshield == KSHIELD_TOP) { - p_speed = 11 * p_speed / 10; + p_speed = 15 * p_speed / 10; } if (K_PlayerUsesBotMovement(player) == true && player->botvars.rubberband > 0) @@ -9873,7 +9873,9 @@ void K_AdjustPlayerFriction(player_t *player) player->mo->friction += ((FRACUNIT - prevfriction) / greasetics) * player->tiregrease; } - if (player->curshield == KSHIELD_TOP) + // Less friction on Top unless grinding + if (player->curshield == KSHIELD_TOP && + K_GetForwardMove(player) > 0) { player->mo->friction += 1024; } diff --git a/src/p_mobj.c b/src/p_mobj.c index b5bb16c45..778e65263 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1134,7 +1134,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) if (K_IsHoldingDownTop(mo->player)) { - gravityadd = (5*gravityadd)/2; + gravityadd *= 3; } else if (mo->player->fastfall != 0) { diff --git a/src/p_user.c b/src/p_user.c index c00991850..cf9beeb8e 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2017,14 +2017,15 @@ static void P_3dMovement(player_t *player) if (onground && player->curshield == KSHIELD_TOP && (K_GetKartButtons(player) & BT_DRIFT) != BT_DRIFT && (player->oldcmd.buttons & BT_DRIFT)) { const fixed_t gmin = FRACUNIT/4; - const fixed_t gmax = 5*FRACUNIT/2; + const fixed_t gmax = 3*FRACUNIT; const fixed_t grindfactor = (gmax - gmin) / GARDENTOP_MAXGRINDTIME; const fixed_t grindscale = gmin + (player->topdriftheld * grindfactor); const fixed_t speed = R_PointToDist2(0, 0, player->mo->momx, player->mo->momy); + const fixed_t minspeed = 3 * K_GetKartSpeed(player, false, false) / 5; // 60% top speed - P_InstaThrust(player->mo, player->mo->angle, FixedMul(speed, grindscale)); + P_InstaThrust(player->mo, player->mo->angle, FixedMul(max(speed, minspeed), grindscale)); player->topdriftheld = 0;/* reset after release */ } From 095aa635b0894463cc1b210cc645f26a3afd18a7 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sat, 14 Jan 2023 20:27:56 -0600 Subject: [PATCH 23/32] hwr: Store T in Slab directly --- src/rhi/gl3_core/gl3_core_rhi.cpp | 151 +++++++++--------------------- src/rhi/gl3_core/gl3_core_rhi.hpp | 72 ++++++++++++-- src/rhi/handle.hpp | 42 +++------ 3 files changed, 123 insertions(+), 142 deletions(-) diff --git a/src/rhi/gl3_core/gl3_core_rhi.cpp b/src/rhi/gl3_core/gl3_core_rhi.cpp index 55d9b3948..705dc4289 100644 --- a/src/rhi/gl3_core/gl3_core_rhi.cpp +++ b/src/rhi/gl3_core/gl3_core_rhi.cpp @@ -11,9 +11,7 @@ #include using namespace srb2; - -using srb2::rhi::GlCorePlatform; -using srb2::rhi::GlCoreRhi; +using namespace rhi; #if 1 #define GL_ASSERT \ @@ -31,13 +29,6 @@ using srb2::rhi::GlCoreRhi; namespace { -template -std::unique_ptr> static_unique_ptr_cast(std::unique_ptr> ptr) -{ - D* derived = static_cast(ptr.release()); - return std::unique_ptr>(derived, std::default_delete()); -} - constexpr GLenum map_pixel_format(rhi::PixelFormat format) { switch (format) @@ -399,69 +390,6 @@ constexpr GLenum map_uniform_format(rhi::UniformFormat format) } } -struct GlCoreTexture : public rhi::Texture -{ - GLuint texture; - rhi::TextureDesc desc; - GlCoreTexture(GLuint texture, const rhi::TextureDesc& desc) noexcept : texture(texture), desc(desc) {} -}; - -struct GlCoreBuffer : public rhi::Buffer -{ - GLuint buffer; - rhi::BufferDesc desc; - GlCoreBuffer(GLuint buffer, const rhi::BufferDesc& desc) noexcept : buffer(buffer), desc(desc) {} -}; - -struct GlCoreRenderPass : public rhi::RenderPass -{ - rhi::RenderPassDesc desc; - explicit GlCoreRenderPass(const rhi::RenderPassDesc& desc) noexcept : desc(desc) {} -}; - -struct GlCoreRenderbuffer : public rhi::Renderbuffer -{ - GLuint renderbuffer; - - explicit GlCoreRenderbuffer(GLuint renderbuffer) noexcept : renderbuffer(renderbuffer) {} -}; - -struct GlCoreUniformSet : public rhi::UniformSet -{ - std::vector uniforms; -}; - -struct GlCoreBindingSet : public rhi::BindingSet -{ - GLuint vao; - std::unordered_map textures {4}; -}; - -struct GlCorePipeline : public rhi::Pipeline -{ - GLuint vertex_shader = 0; - GLuint fragment_shader = 0; - GLuint program = 0; - std::unordered_map attrib_locations {2}; - std::unordered_map uniform_locations {2}; - std::unordered_map sampler_locations {2}; - rhi::PipelineDesc desc; -}; - -struct GlCoreGraphicsContext : public rhi::GraphicsContext -{ -}; - -struct GlCoreTransferContext : public rhi::TransferContext -{ -}; - -struct GlCoreActiveUniform -{ - GLenum type; - GLuint location; -}; - } // namespace GlCorePlatform::~GlCorePlatform() = default; @@ -479,15 +407,16 @@ rhi::Handle GlCoreRhi::create_render_pass(const rhi::RenderPass SRB2_ASSERT(graphics_context_active_ == false); // GL has no formal render pass object - return render_pass_slab_.insert(std::make_unique(desc)); + GlCoreRenderPass pass; + pass.desc = desc; + return render_pass_slab_.insert(std::move(pass)); } void GlCoreRhi::destroy_render_pass(rhi::Handle handle) { SRB2_ASSERT(graphics_context_active_ == false); - std::unique_ptr buffer = render_pass_slab_.remove(handle); - std::unique_ptr casted(static_cast(buffer.release())); + render_pass_slab_.remove(handle); } rhi::Handle GlCoreRhi::create_texture(const rhi::TextureDesc& desc) @@ -513,7 +442,10 @@ rhi::Handle GlCoreRhi::create_texture(const rhi::TextureDesc& desc gl_->TexImage2D(GL_TEXTURE_2D, 0, internal_format, desc.width, desc.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); GL_ASSERT - return texture_slab_.insert(std::make_unique(name, desc)); + GlCoreTexture texture; + texture.texture = name; + texture.desc = desc; + return texture_slab_.insert(std::move(texture)); } void GlCoreRhi::destroy_texture(rhi::Handle handle) @@ -521,8 +453,8 @@ void GlCoreRhi::destroy_texture(rhi::Handle handle) SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(texture_slab_.is_valid(handle) == true); - std::unique_ptr casted = static_unique_ptr_cast(texture_slab_.remove(handle)); - GLuint name = casted->texture; + GlCoreTexture casted = texture_slab_.remove(handle); + GLuint name = casted.texture; disposal_.push_back([this, name] { gl_->DeleteTextures(1, &name); }); } @@ -544,7 +476,7 @@ void GlCoreRhi::update_texture( } SRB2_ASSERT(texture_slab_.is_valid(texture) == true); - auto& t = *static_cast(&texture_slab_[texture]); + auto& t = texture_slab_[texture]; GLenum format = GL_RGBA; GLenum type = GL_UNSIGNED_BYTE; @@ -593,7 +525,10 @@ rhi::Handle GlCoreRhi::create_buffer(const rhi::BufferDesc& desc) gl_->BufferData(target, desc.size, nullptr, usage); GL_ASSERT - return buffer_slab_.insert(std::make_unique(name, desc)); + GlCoreBuffer buffer; + buffer.buffer = name; + buffer.desc = desc; + return buffer_slab_.insert(std::move(buffer)); } void GlCoreRhi::destroy_buffer(rhi::Handle handle) @@ -602,8 +537,8 @@ void GlCoreRhi::destroy_buffer(rhi::Handle handle) SRB2_ASSERT(buffer_slab_.is_valid(handle) == true); SRB2_ASSERT(graphics_context_active_ == false); - std::unique_ptr casted = static_unique_ptr_cast(buffer_slab_.remove(handle)); - GLuint name = casted->buffer; + GlCoreBuffer casted = buffer_slab_.remove(handle); + GLuint name = casted.buffer; disposal_.push_back([this, name] { gl_->DeleteBuffers(1, &name); }); } @@ -625,7 +560,7 @@ void GlCoreRhi::update_buffer_contents( } SRB2_ASSERT(buffer_slab_.is_valid(handle) == true); - auto& b = *static_cast(&buffer_slab_[handle]); + auto& b = buffer_slab_[handle]; SRB2_ASSERT(offset < b.desc.size && offset + data.size() <= b.desc.size); @@ -660,7 +595,7 @@ GlCoreRhi::create_uniform_set(rhi::Handle ctx, const rhi:: uniform_set.uniforms.push_back(uniform); } - return uniform_set_slab_.insert(std::make_unique(std::move(uniform_set))); + return uniform_set_slab_.insert(std::move(uniform_set)); } rhi::Handle GlCoreRhi::create_binding_set( @@ -674,7 +609,7 @@ rhi::Handle GlCoreRhi::create_binding_set( SRB2_ASSERT(ctx.generation() == transfer_context_generation_); SRB2_ASSERT(pipeline_slab_.is_valid(pipeline) == true); - auto& pl = *static_cast(&pipeline_slab_[pipeline]); + auto& pl = pipeline_slab_[pipeline]; SRB2_ASSERT(info.vertex_buffers.size() == pl.desc.vertex_input.buffer_layouts.size()); @@ -689,8 +624,7 @@ rhi::Handle GlCoreRhi::create_binding_set( for (auto& attr_layout : pl.desc.vertex_input.attr_layouts) { SRB2_ASSERT(buffer_slab_.is_valid(info.vertex_buffers[attr_layout.buffer_index].vertex_buffer)); - auto& buf = - *static_cast(&buffer_slab_[info.vertex_buffers[attr_layout.buffer_index].vertex_buffer]); + auto& buf = buffer_slab_[info.vertex_buffers[attr_layout.buffer_index].vertex_buffer]; SRB2_ASSERT(buf.desc.type == rhi::BufferType::kVertexBuffer); auto& buffer_layout = pl.desc.vertex_input.buffer_layouts[attr_layout.buffer_index]; @@ -728,11 +662,11 @@ rhi::Handle GlCoreRhi::create_binding_set( SRB2_ASSERT(binding.name == sampler_name); SRB2_ASSERT(texture_slab_.is_valid(binding.texture)); - auto& tx = *static_cast(&texture_slab_[binding.texture]); + auto& tx = texture_slab_[binding.texture]; binding_set.textures.insert({sampler_name, tx.texture}); } - return binding_set_slab_.insert(std::make_unique(std::move(binding_set))); + return binding_set_slab_.insert(std::move(binding_set)); } rhi::Handle GlCoreRhi::create_renderbuffer(const rhi::RenderbufferDesc& desc) @@ -748,7 +682,9 @@ rhi::Handle GlCoreRhi::create_renderbuffer(const rhi::Renderb gl_->RenderbufferStorage(GL_RENDERBUFFER, map_pixel_format(desc.format), desc.width, desc.height); GL_ASSERT - return renderbuffer_slab_.insert(std::make_unique(GlCoreRenderbuffer {name})); + GlCoreRenderbuffer rb; + rb.renderbuffer = name; + return renderbuffer_slab_.insert(std::move(rb)); } void GlCoreRhi::destroy_renderbuffer(rhi::Handle handle) @@ -756,9 +692,8 @@ void GlCoreRhi::destroy_renderbuffer(rhi::Handle handle) SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(renderbuffer_slab_.is_valid(handle) == true); - std::unique_ptr casted = - static_unique_ptr_cast(renderbuffer_slab_.remove(handle)); - GLuint name = casted->renderbuffer; + GlCoreRenderbuffer casted = renderbuffer_slab_.remove(handle); + GLuint name = casted.renderbuffer; disposal_.push_back([this, name] { gl_->DeleteRenderbuffers(1, &name); }); } @@ -1031,7 +966,7 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) pipeline.fragment_shader = fragment; pipeline.program = program; - return pipeline_slab_.insert(std::make_unique(std::move(pipeline))); + return pipeline_slab_.insert(std::move(pipeline)); } void GlCoreRhi::destroy_pipeline(rhi::Handle handle) @@ -1039,10 +974,10 @@ void GlCoreRhi::destroy_pipeline(rhi::Handle handle) SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(pipeline_slab_.is_valid(handle) == true); - std::unique_ptr casted = static_unique_ptr_cast(pipeline_slab_.remove(handle)); - GLuint vertex_shader = casted->vertex_shader; - GLuint fragment_shader = casted->fragment_shader; - GLuint program = casted->program; + GlCorePipeline casted = pipeline_slab_.remove(handle); + GLuint vertex_shader = casted.vertex_shader; + GLuint fragment_shader = casted.fragment_shader; + GLuint program = casted.program; disposal_.push_back([this, fragment_shader] { gl_->DeleteShader(fragment_shader); }); disposal_.push_back([this, vertex_shader] { gl_->DeleteShader(vertex_shader); }); @@ -1126,7 +1061,7 @@ void GlCoreRhi::begin_render_pass(Handle ctx, const RenderPassB SRB2_ASSERT(current_render_pass_.has_value() == false); SRB2_ASSERT(render_pass_slab_.is_valid(info.render_pass) == true); - auto& rp = *static_cast(&render_pass_slab_[info.render_pass]); + auto& rp = render_pass_slab_[info.render_pass]; SRB2_ASSERT(rp.desc.depth_format.has_value() == info.depth_attachment.has_value()); auto fb_itr = framebuffers_.find(GlCoreFramebufferKey {info.color_attachment, info.depth_attachment}); @@ -1150,14 +1085,14 @@ void GlCoreRhi::begin_render_pass(Handle ctx, const RenderPassB [&, this](const Handle& handle) { SRB2_ASSERT(texture_slab_.is_valid(handle)); - auto& texture = *static_cast(&texture_slab_[handle]); + auto& texture = texture_slab_[handle]; gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.texture, 0); GL_ASSERT }, [&, this](const Handle& handle) { SRB2_ASSERT(renderbuffer_slab_.is_valid(handle)); - auto& renderbuffer = *static_cast(&renderbuffer_slab_[handle]); + auto& renderbuffer = renderbuffer_slab_[handle]; gl_->FramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, @@ -1206,7 +1141,7 @@ void GlCoreRhi::bind_pipeline(Handle ctx, Handle pipe SRB2_ASSERT(current_render_pass_.has_value() == true); SRB2_ASSERT(pipeline_slab_.is_valid(pipeline) == true); - auto& pl = *static_cast(&pipeline_slab_[pipeline]); + auto& pl = pipeline_slab_[pipeline]; auto& desc = pl.desc; gl_->UseProgram(pl.program); @@ -1288,10 +1223,10 @@ void GlCoreRhi::bind_uniform_set(Handle ctx, uint32_t slot, Han SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); SRB2_ASSERT(pipeline_slab_.is_valid(*current_pipeline_)); - auto& pl = *static_cast(&pipeline_slab_[*current_pipeline_]); + auto& pl = pipeline_slab_[*current_pipeline_]; SRB2_ASSERT(uniform_set_slab_.is_valid(set)); - auto& us = *static_cast(&uniform_set_slab_[set]); + auto& us = uniform_set_slab_[set]; auto& uniform_input = pl.desc.uniform_input; SRB2_ASSERT(slot < uniform_input.enabled_uniforms.size()); @@ -1384,10 +1319,10 @@ void GlCoreRhi::bind_binding_set(Handle ctx, Handle SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); SRB2_ASSERT(pipeline_slab_.is_valid(*current_pipeline_)); - auto& pl = *static_cast(&pipeline_slab_[*current_pipeline_]); + auto& pl = pipeline_slab_[*current_pipeline_]; SRB2_ASSERT(binding_set_slab_.is_valid(set)); - auto& bs = *static_cast(&binding_set_slab_[set]); + auto& bs = binding_set_slab_[set]; SRB2_ASSERT(bs.textures.size() == pl.desc.sampler_input.enabled_samplers.size()); @@ -1441,7 +1376,7 @@ void GlCoreRhi::bind_index_buffer(Handle ctx, Handle bu SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); SRB2_ASSERT(buffer_slab_.is_valid(buffer)); - auto& ib = *static_cast(&buffer_slab_[buffer]); + auto& ib = buffer_slab_[buffer]; SRB2_ASSERT(ib.desc.type == rhi::BufferType::kIndexBuffer); diff --git a/src/rhi/gl3_core/gl3_core_rhi.hpp b/src/rhi/gl3_core/gl3_core_rhi.hpp index d20747cc6..fa7997b8b 100644 --- a/src/rhi/gl3_core/gl3_core_rhi.hpp +++ b/src/rhi/gl3_core/gl3_core_rhi.hpp @@ -73,19 +73,77 @@ struct GlCorePlatform virtual Rect get_default_framebuffer_dimensions() = 0; }; +struct GlCoreTexture : public rhi::Texture +{ + uint32_t texture; + rhi::TextureDesc desc; +}; + +struct GlCoreBuffer : public rhi::Buffer +{ + uint32_t buffer; + rhi::BufferDesc desc; +}; + +struct GlCoreRenderPass : public rhi::RenderPass +{ + rhi::RenderPassDesc desc; +}; + +struct GlCoreRenderbuffer : public rhi::Renderbuffer +{ + uint32_t renderbuffer; +}; + +struct GlCoreUniformSet : public rhi::UniformSet +{ + std::vector uniforms; +}; + +struct GlCoreBindingSet : public rhi::BindingSet +{ + uint32_t vao; + std::unordered_map textures {4}; +}; + +struct GlCorePipeline : public rhi::Pipeline +{ + uint32_t vertex_shader = 0; + uint32_t fragment_shader = 0; + uint32_t program = 0; + std::unordered_map attrib_locations {2}; + std::unordered_map uniform_locations {2}; + std::unordered_map sampler_locations {2}; + rhi::PipelineDesc desc; +}; + +struct GlCoreGraphicsContext : public rhi::GraphicsContext +{ +}; + +struct GlCoreTransferContext : public rhi::TransferContext +{ +}; + +struct GlCoreActiveUniform +{ + uint32_t type; + uint32_t location; +}; + class GlCoreRhi final : public Rhi { std::unique_ptr platform_; std::unique_ptr gl_; - Slab render_pass_slab_; - Slab texture_slab_; - Slab buffer_slab_; - Slab renderbuffer_slab_; - Slab pipeline_slab_; - Slab uniform_set_slab_; - Slab binding_set_slab_; + Slab render_pass_slab_; + Slab texture_slab_; + Slab buffer_slab_; + Slab renderbuffer_slab_; + Slab pipeline_slab_; + Slab uniform_set_slab_; + Slab binding_set_slab_; std::unordered_map framebuffers_ {16}; diff --git a/src/rhi/handle.hpp b/src/rhi/handle.hpp index 110783538..bda2928fa 100644 --- a/src/rhi/handle.hpp +++ b/src/rhi/handle.hpp @@ -52,17 +52,10 @@ public: // Conversions from Handles of derived type U to base type T template , bool> = true> - Handle(const Handle& rhs) noexcept : id_(rhs.id_), generation_(rhs.generation_) + Handle(const Handle& rhs) noexcept : id_(rhs.id()), generation_(rhs.generation()) { } - template , bool> = true> - Handle(Handle&& rhs) noexcept - { - id_ = std::exchange(rhs.id_, 0); - generation_ = std::exchange(rhs.generation_, 0); - } - template , bool> = true> Handle& operator=(const Handle& rhs) noexcept { @@ -70,14 +63,6 @@ public: generation_ = rhs.generation_; } - template , bool> = true> - Handle& operator=(Handle&& rhs) noexcept - { - id_ = std::exchange(rhs.id_, 0); - generation_ = std::exchange(rhs.generation_, 0); - return *this; - } - uint32_t id() const noexcept { return id_; } uint32_t generation() const noexcept { return generation_; } @@ -175,7 +160,7 @@ public: SlabIterator& operator=(const SlabIterator&) = default; SlabIterator& operator=(SlabIterator&&) = default; - T& operator*() const noexcept { return *slab_->vec_[index_].item.get(); } + T& operator*() const noexcept { return slab_->vec_[index_].item; } SlabIterator& operator++() noexcept { @@ -211,7 +196,7 @@ class Slab { struct SlabStorage { - std::unique_ptr item; + T item; uint32_t gen; }; std::vector vec_; @@ -226,7 +211,7 @@ public: Slab(const Slab&) = delete; Slab& operator=(const Slab&) = delete; - Handle insert(std::unique_ptr&& value) + Handle insert(T&& value) { uint32_t ret_id = 0; if (!free_list_.empty()) @@ -245,21 +230,22 @@ public: return Handle(ret_id, gen_); } - std::unique_ptr remove(Handle handle) + template , bool> = true> + T remove(Handle handle) { uint32_t handle_id = handle.id(); uint32_t handle_gen = handle.generation(); if (handle_id >= vec_.size()) { - return nullptr; + return T(); } SlabStorage& storage = vec_[handle_id]; if (storage.gen > handle_gen) { - return nullptr; + return T(); } - std::unique_ptr ret = std::move(storage.item); - storage.item = nullptr; + T ret = std::move(storage.item); + storage.item = T(); free_list_.push_back(handle_id); gen_ += 1; if (gen_ == 0) @@ -269,7 +255,8 @@ public: return ret; } - bool is_valid(Handle handle) + template , bool> = true> + bool is_valid(Handle handle) { uint32_t handle_id = handle.id(); uint32_t handle_gen = handle.generation(); @@ -296,10 +283,11 @@ public: } } - T& operator[](Handle handle) + template , bool> = true> + T& operator[](Handle handle) { SRB2_ASSERT(is_valid(handle)); - return *vec_[handle.id()].item; + return vec_[handle.id()].item; } SlabIterator begin() { return SlabIterator {0, this}; } From 7db8b7d20c5674183e97ef96a923fdda3778901b Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sat, 14 Jan 2023 20:30:52 -0600 Subject: [PATCH 24/32] hwr2 gl3core: Fix FBO depth attachment --- src/rhi/gl3_core/gl3_core_rhi.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rhi/gl3_core/gl3_core_rhi.cpp b/src/rhi/gl3_core/gl3_core_rhi.cpp index 705dc4289..7b9500594 100644 --- a/src/rhi/gl3_core/gl3_core_rhi.cpp +++ b/src/rhi/gl3_core/gl3_core_rhi.cpp @@ -1086,7 +1086,7 @@ void GlCoreRhi::begin_render_pass(Handle ctx, const RenderPassB { SRB2_ASSERT(texture_slab_.is_valid(handle)); auto& texture = texture_slab_[handle]; - gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.texture, 0); + gl_->FramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture.texture, 0); GL_ASSERT }, [&, this](const Handle& handle) @@ -1095,7 +1095,7 @@ void GlCoreRhi::begin_render_pass(Handle ctx, const RenderPassB auto& renderbuffer = renderbuffer_slab_[handle]; gl_->FramebufferRenderbuffer( GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, + attachment, GL_RENDERBUFFER, renderbuffer.renderbuffer ); From 8ff95af61dfe672a280b269b66ca39c74a0df0d7 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 14 Jan 2023 18:35:49 -0800 Subject: [PATCH 25/32] Disable Drop Dashing while on the Garden Top --- src/k_respawn.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/k_respawn.c b/src/k_respawn.c index 7d1207b10..873d00fd7 100644 --- a/src/k_respawn.c +++ b/src/k_respawn.c @@ -661,6 +661,42 @@ static void K_DropDashWait(player_t *player) } +/*-------------------------------------------------- + static boolean K_CanDropDash(player_t *player) + + Checks if you can use the Drop Dash maneuver. + + Input Arguments:- + player - Player to check. + + Return:- + Whether a Drop Dash should be allowed. +--------------------------------------------------*/ +static boolean K_CanDropDash(player_t *player) +{ + const UINT16 buttons = K_GetKartButtons(player); + + if (!(buttons & BT_ACCELERATE)) + { + return false; + } + + // Since we're letting players spin out on respawn, don't let them charge a dropdash in this state. (It wouldn't work anyway) + if (player->spinouttimer) + { + return false; + } + + // Garden Top is overpowered enough + if (player->curshield == KSHIELD_TOP) + { + return false; + } + + return true; +} + + /*-------------------------------------------------- static void K_HandleDropDash(player_t *player) @@ -699,7 +735,7 @@ static void K_HandleDropDash(player_t *player) // The old behavior was stupid and prone to accidental usage. // Let's rip off Mania instead, and turn this into a Drop Dash! - if ((buttons & BT_ACCELERATE) && !player->spinouttimer) // Since we're letting players spin out on respawn, don't let them charge a dropdash in this state. (It wouldn't work anyway) + if (K_CanDropDash(player)) { player->respawn.dropdash++; } From 1ba7842068fab271ca3aca98ebd91bc2834fc741 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 14 Jan 2023 18:57:45 -0800 Subject: [PATCH 26/32] hwr2 legacy opengl: restore fps counter etc --- src/i_video_common.cpp | 62 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/src/i_video_common.cpp b/src/i_video_common.cpp index d80818e9f..7be4ca116 100644 --- a/src/i_video_common.cpp +++ b/src/i_video_common.cpp @@ -13,6 +13,11 @@ // KILL THIS WHEN WE KILL OLD OGL SUPPORT PLEASE #include "sdl/ogl_sdl.h" +#include "st_stuff.h" // kill +#include "d_netcmd.h" // kill +#include "doomstat.h" // kill +#include "s_sound.h" // kill +#include "discord.h" // kill using namespace srb2; using namespace srb2::hwr2; @@ -28,6 +33,61 @@ static bool rhi_changed() return false; } +#ifdef HWRENDER +static void finish_legacy_ogl_update() +{ + int player; + + SCR_CalculateFPS(); + + if (st_overlay) + { + if (cv_ticrate.value) + SCR_DisplayTicRate(); + + if (cv_showping.value && netgame && + ( consoleplayer != serverplayer || ! server_lagless )) + { + if (server_lagless) + { + if (consoleplayer != serverplayer) + SCR_DisplayLocalPing(); + } + else + { + for ( + player = 1; + player < MAXPLAYERS; + player++ + ){ + if (D_IsPlayerHumanAndGaming(player)) + { + SCR_DisplayLocalPing(); + break; + } + } + } + } + if (cv_mindelay.value && consoleplayer == serverplayer && Playing()) + SCR_DisplayLocalPing(); + } + + if (marathonmode) + SCR_DisplayMarathonInfo(); + + // draw captions if enabled + if (cv_closedcaptioning.value) + SCR_ClosedCaptions(); + +#ifdef HAVE_DISCORDRPC + if (discordRequestList != NULL) + ST_AskToJoinEnvelope(); +#endif + + OglSdlFinishUpdate(cv_vidwait.value); +} +#endif + void I_FinishUpdate(void) { if (rendermode == render_none) @@ -38,7 +98,7 @@ void I_FinishUpdate(void) #ifdef HWRENDER if (rendermode == render_opengl) { - OglSdlFinishUpdate(cv_vidwait.value); + finish_legacy_ogl_update(); return; } #endif From ad50e67ae9b9e0e113b987a7ccf5ab803b867679 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 15 Jan 2023 13:10:09 +0000 Subject: [PATCH 27/32] r_data.c: Resolve defined-but-unused function warning intefering with compilation Removes `R_Init8to16` and its inline helper, `makecol15`, the last bastion of an abandoned 16-bit drawer rework --- src/r_data.c | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index 0174ee9ef..6f01510a2 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1125,40 +1125,6 @@ const char *R_NameForColormap(extracolormap_t *extra_colormap) } #endif -// -// build a table for quick conversion from 8bpp to 15bpp -// - -// -// added "static inline" keywords, linking with the debug version -// of allegro, it have a makecol15 function of it's own, now -// with "static inline" keywords,it sloves this problem ;) -// -FUNCMATH static inline int makecol15(int r, int g, int b) -{ - return (((r >> 3) << 10) | ((g >> 3) << 5) | ((b >> 3))); -} - -static void R_Init8to16(void) -{ - UINT8 *palette; - int i; - - palette = W_CacheLumpName("PLAYPAL",PU_CACHE); - - for (i = 0; i < 256; i++) - { - // PLAYPAL uses 8 bit values - color8to16[i] = (INT16)makecol15(palette[0], palette[1], palette[2]); - palette += 3; - } - - // test a big colormap - hicolormaps = Z_Malloc(16384*sizeof(*hicolormaps), PU_STATIC, NULL); - for (i = 0; i < 16384; i++) - hicolormaps[i] = (INT16)(i<<1); -} - // // R_InitTextureData // From 083d3df96f0f85a1cd991b07eb93ffc0797830f5 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 15 Jan 2023 14:00:43 +0000 Subject: [PATCH 28/32] d_main.c: Adjust `shaders.pk3` handling per my comments --- src/d_main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 94183e53d..8c55b9548 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1115,7 +1115,6 @@ static void IdentifyVersion(void) #define PATCHNAME "MISC_SCRIPTS.pk3" #define UNLOCKNAME "MISC_UNLOCKS.pk3" #define MUSICNAME "MISC_MUSIC.PK3" -#define SHADERSNAME "MISC_SHADERS.pk3" //// #else //// @@ -1124,7 +1123,6 @@ static void IdentifyVersion(void) #define PATCHNAME "scripts.pk3" #define UNLOCKNAME "unlocks.pk3" #define MUSICNAME "music.pk3" -#define SHADERSNAME "shaders.pk3" //// #endif //// @@ -1142,7 +1140,7 @@ static void IdentifyVersion(void) #if defined(DEVELOP) && defined(UNLOCKTESTING) D_AddFile(startupiwads, va(pandf,srb2waddir,UNLOCKNAME)); #endif - D_AddFile(startupiwads, va(pandf,srb2waddir,SHADERSNAME)); + D_AddFile(startupiwads, va(pandf,srb2waddir,"shaders.pk3")); //// #undef TEXTURESNAME #undef MAPSNAME @@ -1468,6 +1466,7 @@ void D_SRB2Main(void) #endif #endif //ifndef DEVELOP + mainwads++; // shaders.pk3 // Do it before P_InitMapData because PNG patch // conversion sometimes needs the palette From 5837f983e8f71381900cff8f02cff71c35a3b525 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Wed, 18 Jan 2023 02:15:18 -0700 Subject: [PATCH 29/32] Add UFO hum + hit reaction SFX --- src/objects/ufo.c | 29 +++++++++++++++++++++++++++++ src/sounds.c | 22 ++++++++++++++++++++++ src/sounds.h | 22 ++++++++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/src/objects/ufo.c b/src/objects/ufo.c index f9a44127b..0c19b8434 100644 --- a/src/objects/ufo.c +++ b/src/objects/ufo.c @@ -56,6 +56,8 @@ enum UFO_PIECE_TYPE_STEM, }; +static sfxenum_t hums[16] = {sfx_claw01, sfx_claw02, sfx_claw03, sfx_claw04, sfx_claw05, sfx_claw06, sfx_claw07, sfx_claw08, sfx_claw09, sfx_claw10, sfx_claw11, sfx_claw12, sfx_claw13, sfx_claw14, sfx_claw15, sfx_claw16}; + static void UFOMoveTo(mobj_t *ufo, fixed_t destx, fixed_t desty, fixed_t destz) { ufo->momx = destx - ufo->x; @@ -414,12 +416,33 @@ static void UFOEmeraldVFX(mobj_t *ufo) } } +static boolean UFOHumPlaying(mobj_t *ufo) { + INT32 i; + for (i = 0; i < 15; i++) + { + if (S_SoundPlaying(ufo, hums[i])) + return true; + } + return false; +} + +static void UFOUpdateSound(mobj_t *ufo) { + INT32 maxhealth = mobjinfo[MT_SPECIAL_UFO].spawnhealth; + INT32 healthlevel = 15 * ufo->health / maxhealth; + + if (!UFOEmeraldChase(ufo) && !UFOHumPlaying(ufo)) + { + S_StartSound(ufo, hums[15-healthlevel]); + } +} + void Obj_SpecialUFOThinker(mobj_t *ufo) { UFOMove(ufo); UFOUpdateAngle(ufo); UFOUpdateDistanceToFinish(ufo); UFOUpdateSpeed(ufo); + UFOUpdateSound(ufo); if (UFOEmeraldChase(ufo) == true) { @@ -609,10 +632,16 @@ boolean Obj_SpecialUFODamage(mobj_t *ufo, mobj_t *inflictor, mobj_t *source, UIN P_LinedefExecute(LE_PINCHPHASE, ufo, NULL); + S_StopSound(ufo); + S_StartSound(ufo, sfx_clawk2); + P_StartQuake(64<health -= damage; return true; } diff --git a/src/sounds.c b/src/sounds.c index b18670667..9e387f8fc 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -1152,6 +1152,28 @@ sfxinfo_t S_sfx[NUMSFX] = {"grownd", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X8AWAYSOUND {"invind", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X8AWAYSOUND + // SRB2Kart - Claw SFX + {"claw01", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X2AWAYSOUND + {"claw02", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X2AWAYSOUND + {"claw03", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X2AWAYSOUND + {"claw04", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X2AWAYSOUND + {"claw05", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X2AWAYSOUND + {"claw06", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X2AWAYSOUND + {"claw07", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X2AWAYSOUND + {"claw08", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X2AWAYSOUND + {"claw09", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X2AWAYSOUND + {"claw10", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X2AWAYSOUND + {"claw11", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X2AWAYSOUND + {"claw12", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X2AWAYSOUND + {"claw13", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X2AWAYSOUND + {"claw14", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X2AWAYSOUND + {"claw15", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X2AWAYSOUND + {"claw16", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X2AWAYSOUND + {"clawht", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X4AWAYSOUND + {"clawzm", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X4AWAYSOUND + {"clawk1", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X8AWAYSOUND + {"clawk2", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X8AWAYSOUND + // SRB2Kart - Engine sounds // Engine class A {"krta00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, diff --git a/src/sounds.h b/src/sounds.h index 0c98c8ac2..b6f910c6f 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -1220,6 +1220,28 @@ typedef enum sfx_grownd, sfx_invind, + // Claw SFX + sfx_claw01, + sfx_claw02, + sfx_claw03, + sfx_claw04, + sfx_claw05, + sfx_claw06, + sfx_claw07, + sfx_claw08, + sfx_claw09, + sfx_claw10, + sfx_claw11, + sfx_claw12, + sfx_claw13, + sfx_claw14, + sfx_claw15, + sfx_claw16, + sfx_clawht, + sfx_clawzm, + sfx_clawk1, + sfx_clawk2, + // Next up: UNIQUE ENGINE SOUNDS! Hoooooo boy... // Engine class A - Low Speed, Low Weight sfx_krta00, From eebce28b7ec81d4864c3f6312c0f0cb9b7511c29 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Wed, 18 Jan 2023 02:59:46 -0700 Subject: [PATCH 30/32] Fix bad loop on UFO pinch hit hums --- src/objects/ufo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objects/ufo.c b/src/objects/ufo.c index 0c19b8434..fae96cbc6 100644 --- a/src/objects/ufo.c +++ b/src/objects/ufo.c @@ -418,7 +418,7 @@ static void UFOEmeraldVFX(mobj_t *ufo) static boolean UFOHumPlaying(mobj_t *ufo) { INT32 i; - for (i = 0; i < 15; i++) + for (i = 0; i <= 15; i++) { if (S_SoundPlaying(ufo, hums[i])) return true; From 3165deb43b1e4d55f167e9abdff2df91c648e92b Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Thu, 19 Jan 2023 15:41:10 -0700 Subject: [PATCH 31/32] Clamp UFO hum SFX to safe values --- src/objects/ufo.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/objects/ufo.c b/src/objects/ufo.c index fae96cbc6..23e121900 100644 --- a/src/objects/ufo.c +++ b/src/objects/ufo.c @@ -57,6 +57,7 @@ enum }; static sfxenum_t hums[16] = {sfx_claw01, sfx_claw02, sfx_claw03, sfx_claw04, sfx_claw05, sfx_claw06, sfx_claw07, sfx_claw08, sfx_claw09, sfx_claw10, sfx_claw11, sfx_claw12, sfx_claw13, sfx_claw14, sfx_claw15, sfx_claw16}; +static int maxhum = sizeof(hums) / sizeof(hums[0]) - 1; static void UFOMoveTo(mobj_t *ufo, fixed_t destx, fixed_t desty, fixed_t destz) { @@ -418,7 +419,7 @@ static void UFOEmeraldVFX(mobj_t *ufo) static boolean UFOHumPlaying(mobj_t *ufo) { INT32 i; - for (i = 0; i <= 15; i++) + for (i = 0; i <= maxhum; i++) { if (S_SoundPlaying(ufo, hums[i])) return true; @@ -427,12 +428,13 @@ static boolean UFOHumPlaying(mobj_t *ufo) { } static void UFOUpdateSound(mobj_t *ufo) { - INT32 maxhealth = mobjinfo[MT_SPECIAL_UFO].spawnhealth; - INT32 healthlevel = 15 * ufo->health / maxhealth; + INT32 maxhealth = max(mobjinfo[MT_SPECIAL_UFO].spawnhealth, 1); + INT32 healthlevel = maxhum * ufo->health / maxhealth; if (!UFOEmeraldChase(ufo) && !UFOHumPlaying(ufo)) { - S_StartSound(ufo, hums[15-healthlevel]); + healthlevel = max(min(healthlevel, 1), maxhum); + S_StartSound(ufo, hums[maxhum - healthlevel]); } } From 0eba5c5a74b83d0858f581c0c53b2842a9708d34 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Thu, 19 Jan 2023 15:56:36 -0700 Subject: [PATCH 32/32] Fix UFO hum level clamping --- src/objects/ufo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objects/ufo.c b/src/objects/ufo.c index 23e121900..4921c8d52 100644 --- a/src/objects/ufo.c +++ b/src/objects/ufo.c @@ -433,7 +433,7 @@ static void UFOUpdateSound(mobj_t *ufo) { if (!UFOEmeraldChase(ufo) && !UFOHumPlaying(ufo)) { - healthlevel = max(min(healthlevel, 1), maxhum); + healthlevel = min(max(healthlevel, 1), maxhum); S_StartSound(ufo, hums[maxhum - healthlevel]); } }