random hacks to get rtshadows working in the gles/webgl port, no longer depend upon GL_ARB_shadow.

gles renderer can use fbos now.
webgl now saves configs+savedgames persistently using localstorage.
misc startup/manifest refinements.
make nacl compile again.
webgl port can now use #stuff to select different manifest files.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4733 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2014-08-27 08:41:31 +00:00
parent 957afd8c3b
commit 258a4163ae
40 changed files with 611 additions and 390 deletions

View file

@ -754,6 +754,7 @@ ifeq ($(FTE_TARGET),nacl)
BASELDFLAGS = -lm -lppapi_gles2 -lnosys -lppapi BASELDFLAGS = -lm -lppapi_gles2 -lnosys -lppapi
IMAGELDFLAGS = IMAGELDFLAGS =
GL_CFLAGS=$(GLCFLAGS)
GL_CFLAGS+=$(SPEEXCFLAGS) GL_CFLAGS+=$(SPEEXCFLAGS)
GL_CFLAGS+=-I$(realpath $(NACL_SDK_ROOT)/include) GL_CFLAGS+=-I$(realpath $(NACL_SDK_ROOT)/include)
BASELDFLAGS+=-L$(realpath $(NACL_SDK_ROOT)/lib/$(NACLLIBS)) BASELDFLAGS+=-L$(realpath $(NACL_SDK_ROOT)/lib/$(NACLLIBS))

View file

@ -3851,8 +3851,8 @@ void Host_RunFileNotify(struct dl_download *dl)
#define HRF_ABORT (1<<3) #define HRF_ABORT (1<<3)
#define HRF_OPENED (1<<4) #define HRF_OPENED (1<<4)
// (1<<5) #define HRF_DOWNLOADED (1<<5) //file was actually downloaded, and not from the local system
// (1<<6) #define HRF_WAITING (1<<6) //file looks important enough that we should wait for it to start to download or something to see what file type it is.
// (1<<7) // (1<<7)
#define HRF_DEMO_MVD (1<<8) #define HRF_DEMO_MVD (1<<8)
@ -3894,6 +3894,12 @@ void Host_BeginFileDownload(struct dl_download *dl, char *mimetype)
//at this point the file is still downloading, so don't copy it out just yet. //at this point the file is still downloading, so don't copy it out just yet.
hrf_t *f = dl->user_ctx; hrf_t *f = dl->user_ctx;
if (f->flags & HRF_WAITING)
{
f->flags &= ~HRF_WAITING;
waitingformanifest--;
}
if (mimetype && !(f->flags & HRF_FILETYPES)) if (mimetype && !(f->flags & HRF_FILETYPES))
{ {
if (!strcmp(mimetype, "application/x-qtv")) //what uses this? if (!strcmp(mimetype, "application/x-qtv")) //what uses this?
@ -3988,6 +3994,14 @@ void Host_RunFilePrompted(void *ctx, int button)
Host_DoRunFile(f); Host_DoRunFile(f);
} }
static qboolean isurl(char *url)
{
#ifdef FTE_TARGET_WEB
return true; //assume EVERYTHING is a url, because the local filesystem is pointless.
#endif
return !strncmp(url, "http://", 7) || !strncmp(url, "https://", 8);
}
void Host_DoRunFile(hrf_t *f) void Host_DoRunFile(hrf_t *f)
{ {
char qname[MAX_QPATH]; char qname[MAX_QPATH];
@ -3995,6 +4009,12 @@ void Host_DoRunFile(hrf_t *f)
char loadcommand[MAX_OSPATH]; char loadcommand[MAX_OSPATH];
qboolean isnew = false; qboolean isnew = false;
qboolean haschanged = false; qboolean haschanged = false;
if (f->flags & HRF_WAITING)
{
f->flags &= ~HRF_WAITING;
waitingformanifest--;
}
if (f->flags & HRF_ABORT) if (f->flags & HRF_ABORT)
{ {
@ -4014,15 +4034,17 @@ void Host_DoRunFile(hrf_t *f)
char *ext; char *ext;
#ifdef WEBCLIENT #ifdef WEBCLIENT
if ((!strncmp(f->fname, "http://", 7) || !strncmp(f->fname, "https://", 8)) && !f->srcfile) if (isurl(f->fname) && !f->srcfile)
{ {
if (!(f->flags & HRF_OPENED)) if (!(f->flags & HRF_OPENED))
{ {
struct dl_download *dl; struct dl_download *dl;
f->flags |= HRF_OPENED; f->flags |= HRF_OPENED|HRF_DOWNLOADED|HRF_WAITING;
dl = HTTP_CL_Get(f->fname, NULL, Host_RunFileDownloaded); dl = HTTP_CL_Get(f->fname, NULL, Host_RunFileDownloaded);
dl->notifystarted = Host_BeginFileDownload; dl->notifystarted = Host_BeginFileDownload;
dl->user_ctx = f; dl->user_ctx = f;
waitingformanifest++;
return; return;
} }
} }
@ -4105,10 +4127,20 @@ void Host_DoRunFile(hrf_t *f)
else else
{ {
man = FS_Manifest_Parse(NULL, fdata); man = FS_Manifest_Parse(NULL, fdata);
if (!man->updateurl) if (man)
man->updateurl = Z_StrDup(f->fname); {
BZ_Free(fdata); if (!man->updateurl)
FS_ChangeGame(man, true); man->updateurl = Z_StrDup(f->fname);
// if (f->flags & HRF_DOWNLOADED)
man->blockupdate = true;
BZ_Free(fdata);
FS_ChangeGame(man, true);
}
else
{
Con_Printf("Manifest file %s does not appear valid\n", f->fname);
BZ_Free(fdata);
}
} }
f->flags |= HRF_ABORT; f->flags |= HRF_ABORT;
@ -4132,7 +4164,7 @@ void Host_DoRunFile(hrf_t *f)
if (!f->srcfile) if (!f->srcfile)
{ {
#ifdef WEBCLIENT #ifdef WEBCLIENT
if (!strncmp(f->fname, "http://", 7)) if (isurl(f->fname))
{ {
struct dl_download *dl = HTTP_CL_Get(f->fname, NULL, Host_RunFileDownloaded); struct dl_download *dl = HTTP_CL_Get(f->fname, NULL, Host_RunFileDownloaded);
dl->notifystarted = Host_BeginFileDownload; dl->notifystarted = Host_BeginFileDownload;
@ -4288,6 +4320,8 @@ Runs all active servers
extern cvar_t cl_netfps; extern cvar_t cl_netfps;
extern cvar_t cl_sparemsec; extern cvar_t cl_sparemsec;
qboolean startuppending;
void CL_StartCinematicOrMenu(void);
int nopacketcount; int nopacketcount;
void SNDDMA_SetUnderWater(qboolean underwater); void SNDDMA_SetUnderWater(qboolean underwater);
double Host_Frame (double time) double Host_Frame (double time)
@ -4336,6 +4370,8 @@ double Host_Frame (double time)
Host_FinishLoading(); Host_FinishLoading();
return 0; return 0;
} }
if (startuppending)
CL_StartCinematicOrMenu();
#ifdef PLUGINS #ifdef PLUGINS
Plug_Tick(); Plug_Tick();
@ -4629,9 +4665,19 @@ void CL_ReadCDKey(void)
//============================================================================ //============================================================================
void CL_StartCinematicOrMenu(void) void CL_StartCinematicOrMenu(void)
{ {
if (cls.download)
{
startuppending = true;
return;
}
if (startuppending)
{
startuppending = false;
Key_Dest_Remove(kdm_console); //make sure console doesn't stay up weirdly.
}
//start up the ui now we have a renderer //start up the ui now we have a renderer
#ifdef VM_UI #ifdef VM_UI
UI_Start(); UI_Start();
@ -4685,9 +4731,11 @@ void CL_StartCinematicOrMenu(void)
{ {
if (qrenderer > QR_NONE && !m_state) if (qrenderer > QR_NONE && !m_state)
{ {
if (cl_demoreel.ival) if (!cls.state && !m_state && !*FS_GetGamedir(false))
M_Menu_Mods_f();
if (!cls.state && !m_state && cl_demoreel.ival)
CL_NextDemo(); CL_NextDemo();
if (!cls.state) if (!cls.state && !m_state)
M_ToggleMenu_f(); M_ToggleMenu_f();
} }
//Con_ForceActiveNow(); //Con_ForceActiveNow();

View file

@ -1458,7 +1458,7 @@ void CL_RequestNextDownload (void)
current_loading_size = cl.contentstage; current_loading_size = cl.contentstage;
if (stage < 0) if (stage < 0)
return; return;
SCR_SetLoadingFile("prespawn"); SCR_SetLoadingFile("receiving game state");
cl.sendprespawn = false; cl.sendprespawn = false;
#ifdef warningmsg #ifdef warningmsg
#pragma warningmsg("timedemo timer should start here") #pragma warningmsg("timedemo timer should start here")

View file

@ -226,6 +226,7 @@ void SCR_ScreenShot_f (void);
void SCR_RSShot_f (void); void SCR_RSShot_f (void);
void SCR_CPrint_f(void); void SCR_CPrint_f(void);
cvar_t con_stayhidden = CVARFD("con_stayhidden", "0", CVAR_NOTFROMSERVER, "0: allow console to pounce on the user\n1: console stays hidden unless explicitly invoked\n2:toggleconsole command no longer works\n3: shift+escape key no longer works");
cvar_t show_fps = SCVARF("show_fps", "0", CVAR_ARCHIVE); cvar_t show_fps = SCVARF("show_fps", "0", CVAR_ARCHIVE);
cvar_t show_fps_x = SCVAR("show_fps_x", "-1"); cvar_t show_fps_x = SCVAR("show_fps_x", "-1");
cvar_t show_fps_y = SCVAR("show_fps_y", "-1"); cvar_t show_fps_y = SCVAR("show_fps_y", "-1");
@ -245,6 +246,7 @@ void CLSCR_Init(void)
{ {
Cmd_AddCommand("cprint", SCR_CPrint_f); Cmd_AddCommand("cprint", SCR_CPrint_f);
Cvar_Register(&con_stayhidden, cl_screengroup);
Cvar_Register(&scr_loadingrefresh, cl_screengroup); Cvar_Register(&scr_loadingrefresh, cl_screengroup);
Cvar_Register(&show_fps, cl_screengroup); Cvar_Register(&show_fps, cl_screengroup);
Cvar_Register(&show_fps_x, cl_screengroup); Cvar_Register(&show_fps_x, cl_screengroup);
@ -1425,7 +1427,7 @@ void SCR_SetLoadingStage(int stage)
SCR_SetLoadingFile("starting server..."); SCR_SetLoadingFile("starting server...");
break; break;
case LS_CLIENT: case LS_CLIENT:
SCR_SetLoadingFile("initial state"); SCR_SetLoadingFile("receiving map info");
break; break;
} }
loading_stage = stage; loading_stage = stage;
@ -1706,7 +1708,7 @@ void SCR_SetUpToDrawConsole (void)
//android has an onscreen imm that we don't want to obscure //android has an onscreen imm that we don't want to obscure
fullscreenpercent = scr_consize.value; fullscreenpercent = scr_consize.value;
#endif #endif
if ((!Key_Dest_Has(~(kdm_console|kdm_game))) && (!cl.sendprespawn && cl.worldmodel && cl.worldmodel->needload)) if (!con_stayhidden.ival && (!Key_Dest_Has(~(kdm_console|kdm_game))) && (!cl.sendprespawn && cl.worldmodel && cl.worldmodel->needload))
{ {
//force console to fullscreen if we're loading stuff //force console to fullscreen if we're loading stuff
// Key_Dest_Add(kdm_console); // Key_Dest_Add(kdm_console);
@ -1720,9 +1722,25 @@ void SCR_SetUpToDrawConsole (void)
scr_con_current = scr_conlines = 0; scr_con_current = scr_conlines = 0;
else else
#endif #endif
{
if (cls.state < ca_demostart) if (cls.state < ca_demostart)
Key_Dest_Add(kdm_console); {
if (Key_Dest_Has(kdm_console)) if (con_stayhidden.ival)
{
extern qboolean startuppending;
if (SCR_GetLoadingStage() == LS_NONE)
{
if (CL_TryingToConnect()) //if we're trying to connect, make sure there's a loading/connecting screen showing instead of forcing the menu visible
SCR_SetLoadingStage(LS_CONNECTION);
else if (!m_state && !startuppending) //don't force anything until the startup stuff has been done
M_ToggleMenu_f();
}
}
else
Key_Dest_Add(kdm_console);
}
}
if (!con_stayhidden.ival && Key_Dest_Has(kdm_console))
scr_con_current = scr_conlines = vid.height * fullscreenpercent; scr_con_current = scr_conlines = vid.height * fullscreenpercent;
} }
else if (Key_Dest_Has(kdm_console) || scr_chatmode) else if (Key_Dest_Has(kdm_console) || scr_chatmode)

View file

@ -453,6 +453,7 @@ void Con_ToggleConsole_Force(void)
} }
void Con_ToggleConsole_f (void) void Con_ToggleConsole_f (void)
{ {
extern cvar_t con_stayhidden;
#ifdef CSQC_DAT #ifdef CSQC_DAT
if (!(key_dest_mask & kdm_editor) && CSQC_ConsoleCommand("toggleconsole")) if (!(key_dest_mask & kdm_editor) && CSQC_ConsoleCommand("toggleconsole"))
{ {
@ -461,6 +462,9 @@ void Con_ToggleConsole_f (void)
} }
#endif #endif
if (con_stayhidden.ival >= 2)
return; //its hiding!
Con_ToggleConsole_Force(); Con_ToggleConsole_Force();
} }

View file

@ -1968,7 +1968,8 @@ void Key_Event (int devid, int key, unsigned int unicode, qboolean down)
if (key == K_ESCAPE) if (key == K_ESCAPE)
if (shift_down) if (shift_down)
{ {
if (down) extern cvar_t con_stayhidden;
if (down && con_stayhidden.ival < 3)
{ {
if (!Key_Dest_Has(kdm_console)) //don't toggle it when the console is already down. this allows typing blind to not care if its already active. if (!Key_Dest_Has(kdm_console)) //don't toggle it when the console is already down. this allows typing blind to not care if its already active.
Con_ToggleConsole_Force(); Con_ToggleConsole_Force();

View file

@ -1912,15 +1912,21 @@ static qboolean MC_GuiKey(int key, menu_t *menu)
qboolean MC_Main_Key (int key, menu_t *menu) //here purly to restart demos. qboolean MC_Main_Key (int key, menu_t *menu) //here purly to restart demos.
{ {
if (key == K_ESCAPE) if (key == K_ESCAPE || key == K_MOUSE2)
{ {
extern int m_save_demonum; extern int m_save_demonum;
extern cvar_t cl_demoreel; extern cvar_t cl_demoreel, con_stayhidden;
if (cls.demonum != -1 && !cls.demoplayback && cls.state == ca_disconnected && cl_demoreel.ival)
CL_NextDemo ();
//don't spam menu open+close events if we're not going to be allowing the console to appear
if (con_stayhidden.ival && cls.state == ca_disconnected)
if (!CL_TryingToConnect())
return true;
Key_Dest_Remove(kdm_menu); Key_Dest_Remove(kdm_menu);
m_state = m_none; m_state = m_none;
cls.demonum = m_save_demonum; cls.demonum = m_save_demonum;
if (cls.demonum != -1 && !cls.demoplayback && cls.state == ca_disconnected && cl_demoreel.ival)
CL_NextDemo ();
return true; return true;
} }
return false; return false;
@ -2087,14 +2093,18 @@ void M_Menu_Main_f (void)
MC_AddCenterPicture(mainm, 4, 24, "gfx/ttl_main.lmp"); MC_AddCenterPicture(mainm, 4, 24, "gfx/ttl_main.lmp");
mainm->selecteditem = (menuoption_t *) mainm->selecteditem = (menuoption_t *)
MC_AddConsoleCommandQBigFont (mainm, 72, 32, "Single ", "menu_single\n"); MC_AddConsoleCommandQBigFont (mainm, 72, 32, "Single ", "menu_single\n");
MC_AddConsoleCommandQBigFont (mainm, 72, 52, "Multiplayer", "menu_multi\n"); MC_AddConsoleCommandQBigFont (mainm, 72, 52, "Multiplayer ", "menu_multi\n");
MC_AddConsoleCommandQBigFont (mainm, 72, 72, "Options ", "menu_options\n"); MC_AddConsoleCommandQBigFont (mainm, 72, 72, "Options ", "menu_options\n");
if (m_helpismedia.value) if (m_helpismedia.value)
MC_AddConsoleCommandQBigFont(mainm, 72, 92, "Media ", "menu_media\n"); MC_AddConsoleCommandQBigFont(mainm, 72, 92, "Media ", "menu_media\n");
else else
MC_AddConsoleCommandQBigFont(mainm, 72, 92, "Help ", "help\n"); MC_AddConsoleCommandQBigFont(mainm, 72, 92, "Help ", "help\n");
MC_AddConsoleCommandQBigFont (mainm, 72, 112,"Quit ", "menu_quit\n"); #ifdef FTE_TARGET_WEB
MC_AddConsoleCommandQBigFont (mainm, 72, 112,"Save Settings", "menu_quit\n");
#else
MC_AddConsoleCommandQBigFont (mainm, 72, 112,"Quit ", "menu_quit\n");
#endif
mainm->cursoritem = (menuoption_t *)MC_AddCursor(mainm, &resel, 54, 32); mainm->cursoritem = (menuoption_t *)MC_AddCursor(mainm, &resel, 54, 32);
} }
@ -2150,7 +2160,11 @@ void M_Menu_Main_f (void)
b->common.width = p->width; b->common.width = p->width;
b->common.height = 20; b->common.height = 20;
b=MC_AddConsoleCommand (mainm, 72, 312, 112, "", "menu_quit\n"); b=MC_AddConsoleCommand (mainm, 72, 312, 112, "", "menu_quit\n");
#ifdef FTE_TARGET_WEB
b->common.tooltip = "Save settings to local storage.";
#else
b->common.tooltip = "Exit to DOS."; b->common.tooltip = "Exit to DOS.";
#endif
b->common.width = p->width; b->common.width = p->width;
b->common.height = 20; b->common.height = 20;

View file

@ -1438,9 +1438,10 @@ void M_Menu_Singleplayer_Cheats_Quake (void)
cursorpositionY = (y + 24); cursorpositionY = (y + 24);
#ifndef CLIENTONLY #ifndef CLIENTONLY
currentskill = skill.value; if ( !*skill.string )
if ( !currentskill )
currentskill = 4; // no skill selected currentskill = 4; // no skill selected
else
currentskill = skill.value;
for (currentmap = sizeof(maplist_q1)/sizeof(maplist_q1[0]) - 1; currentmap > 0; currentmap--) for (currentmap = sizeof(maplist_q1)/sizeof(maplist_q1[0]) - 1; currentmap > 0; currentmap--)
if (!strcmp(host_mapname.string, maplist_q1[currentmap])) if (!strcmp(host_mapname.string, maplist_q1[currentmap]))
@ -1551,10 +1552,10 @@ void M_Menu_Singleplayer_Cheats_Quake2 (void)
cursorpositionY = (y + 24); cursorpositionY = (y + 24);
#ifndef CLIENTONLY #ifndef CLIENTONLY
currentskill = skill.value; if ( !*skill.string )
currentskill = 3; // no skill selected
if ( !currentskill ) else
currentskill = 4; // no skill selected currentskill = skill.value;
for (currentmap = sizeof(maplist_q2)/sizeof(maplist_q2[0]) - 1; currentmap > 0; currentmap--) for (currentmap = sizeof(maplist_q2)/sizeof(maplist_q2[0]) - 1; currentmap > 0; currentmap--)
if (!strcmp(host_mapname.string, maplist_q2[currentmap])) if (!strcmp(host_mapname.string, maplist_q2[currentmap]))
@ -1835,10 +1836,10 @@ void M_Menu_Singleplayer_Cheats_Hexen2 (void)
cursorpositionY = (y + 24); cursorpositionY = (y + 24);
#ifndef CLIENTONLY #ifndef CLIENTONLY
currentskill = skill.value; if ( !*skill.string )
if ( !currentskill )
currentskill = 4; // no skill selected currentskill = 4; // no skill selected
else
currentskill = skill.value;
#endif #endif
if ( strcmp ( host_mapname.string, "" ) == 0) if ( strcmp ( host_mapname.string, "" ) == 0)

View file

@ -573,7 +573,7 @@ void M_Menu_Help_f (void)
{ {
for (i = 0; i < sizeof(helpstyles)/sizeof(helpstyles[0]); i++) for (i = 0; i < sizeof(helpstyles)/sizeof(helpstyles[0]); i++)
{ {
if (COM_FDepthFile(va(helpstyles[i].pattern, num_help_pages+helpstyles[i].base), true)) if (COM_FCheckExists(va(helpstyles[i].pattern, num_help_pages+helpstyles[i].base)))
break; break;
} }
if (i == sizeof(helpstyles)/sizeof(helpstyles[0])) if (i == sizeof(helpstyles)/sizeof(helpstyles[0]))
@ -602,11 +602,13 @@ void M_Help_Key (int key)
switch (key) switch (key)
{ {
case K_ESCAPE: case K_ESCAPE:
case K_MOUSE2:
M_Menu_Main_f (); M_Menu_Main_f ();
break; break;
case K_UPARROW: case K_UPARROW:
case K_RIGHTARROW: case K_RIGHTARROW:
case K_MOUSE1:
S_LocalSound ("misc/menu2.wav"); S_LocalSound ("misc/menu2.wav");
if (++help_page >= num_help_pages) if (++help_page >= num_help_pages)
help_page = 0; help_page = 0;
@ -893,7 +895,10 @@ qboolean MC_SaveQuit_Key (int key, menu_t *menu)
{ {
switch (key) switch (key)
{ {
case 'o':
case 'O':
case K_ESCAPE: case K_ESCAPE:
case K_MOUSE2:
M_RemoveMenu(menu); M_RemoveMenu(menu);
break; break;
@ -902,16 +907,20 @@ qboolean MC_SaveQuit_Key (int key, menu_t *menu)
case 'n': case 'n':
case 'N': case 'N':
M_RemoveMenu(menu); M_RemoveMenu(menu);
#ifndef FTE_TARGET_WEB
CL_Disconnect (); CL_Disconnect ();
Sys_Quit (); Sys_Quit ();
#endif
break; break;
case 'Y': case 'Y':
case 'y': case 'y':
M_RemoveMenu(menu); M_RemoveMenu(menu);
Cmd_ExecuteString("cfg_save", RESTRICT_LOCAL); Cmd_ExecuteString("cfg_save", RESTRICT_LOCAL);
#ifndef FTE_TARGET_WEB
CL_Disconnect (); CL_Disconnect ();
Sys_Quit (); Sys_Quit ();
#endif
break; break;
default: default:
@ -921,6 +930,7 @@ qboolean MC_SaveQuit_Key (int key, menu_t *menu)
return true; return true;
} }
//quit menu
void M_Menu_Quit_f (void) void M_Menu_Quit_f (void)
{ {
menu_t *quitmenu; menu_t *quitmenu;
@ -946,17 +956,19 @@ void M_Menu_Quit_f (void)
if (!strcmp(arg, "prompt")) if (!strcmp(arg, "prompt"))
mode = 1; mode = 1;
else if (!strcmp(arg, "noprompt")) else if (!strcmp(arg, "noprompt"))
mode = 1;
else
mode = 0; mode = 0;
else
mode = 1;
} }
} }
switch(mode) switch(mode)
{ {
case 0: case 0:
#ifndef FTE_TARGET_WEB
CL_Disconnect (); CL_Disconnect ();
Sys_Quit (); Sys_Quit ();
#endif
break; break;
case 2: case 2:
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_menu);
@ -971,9 +983,14 @@ void M_Menu_Quit_f (void)
MC_AddWhiteText(quitmenu, 64, 0, 100, " save them now? ", false); MC_AddWhiteText(quitmenu, 64, 0, 100, " save them now? ", false);
quitmenu->selecteditem = (menuoption_t *) quitmenu->selecteditem = (menuoption_t *)
#ifdef FTE_TARGET_WEB
MC_AddConsoleCommand (quitmenu, 64, 0, 116, "Yes", "cfg_save; menupop\n");
MC_AddConsoleCommand (quitmenu, 224,0, 116, "Cancel", "menupop\n");
#else
MC_AddConsoleCommand (quitmenu, 64, 0, 116, "Yes", "menu_quit forcesave\n"); MC_AddConsoleCommand (quitmenu, 64, 0, 116, "Yes", "menu_quit forcesave\n");
MC_AddConsoleCommand (quitmenu, 144,0, 116, "No", "menu_quit force\n"); MC_AddConsoleCommand (quitmenu, 144,0, 116, "No", "menu_quit force\n");
MC_AddConsoleCommand (quitmenu, 224,0, 116, "Cancel", "menupop\n"); MC_AddConsoleCommand (quitmenu, 224,0, 116, "Cancel", "menupop\n");
#endif
MC_AddBox (quitmenu, 56, 76, 25, 5); MC_AddBox (quitmenu, 56, 76, 25, 5);
break; break;
@ -986,17 +1003,25 @@ void M_Menu_Quit_f (void)
quitmenu->key = MC_Quit_Key; quitmenu->key = MC_Quit_Key;
i = rand()&7; #ifdef FTE_TARGET_WEB
// MC_AddWhiteText(quitmenu, 64, 0, 84, " ", false);
MC_AddWhiteText(quitmenu, 64, 0, 92, " There is nothing to save ", false);
// MC_AddWhiteText(quitmenu, 64, 0, 100, " ", false);
quitmenu->selecteditem = (menuoption_t *)
MC_AddConsoleCommand (quitmenu, 120, 0, 116, "Oh", "menupop\n");
#else
i = rand()&7;
MC_AddWhiteText(quitmenu, 64, 0, 84, quitMessage[i*4+0], false); MC_AddWhiteText(quitmenu, 64, 0, 84, quitMessage[i*4+0], false);
MC_AddWhiteText(quitmenu, 64, 0, 92, quitMessage[i*4+1], false); MC_AddWhiteText(quitmenu, 64, 0, 92, quitMessage[i*4+1], false);
MC_AddWhiteText(quitmenu, 64, 0, 100, quitMessage[i*4+2], false); MC_AddWhiteText(quitmenu, 64, 0, 100, quitMessage[i*4+2], false);
MC_AddWhiteText(quitmenu, 64, 0, 108, quitMessage[i*4+3], false); MC_AddWhiteText(quitmenu, 64, 0, 108, quitMessage[i*4+3], false);
quitmenu->selecteditem = (menuoption_t *) quitmenu->selecteditem = (menuoption_t *)
MC_AddConsoleCommand (quitmenu, 120, 0, 116, "Yes", "menu_quit force\n"); MC_AddConsoleCommand (quitmenu, 100, 0, 116, "Quit", "menu_quit force\n");
MC_AddConsoleCommand (quitmenu, 208, 0, 116, "No", "menupop\n"); MC_AddConsoleCommand (quitmenu, 194, 0, 116, "Cancel", "menupop\n");
#endif
MC_AddBox (quitmenu, 56, 76, 24, 5); MC_AddBox (quitmenu, 56, 76, 24, 5);
break; break;
} }

View file

@ -108,6 +108,7 @@ void M_Keydown (int key, int unicode);
void M_Keyup (int key, int unicode); void M_Keyup (int key, int unicode);
void M_Draw (int uimenu); void M_Draw (int uimenu);
void M_ToggleMenu_f (void); void M_ToggleMenu_f (void);
void M_Menu_Mods_f (void); //used at startup if the current gamedirs look dodgy.
mpic_t *M_CachePic (char *path); mpic_t *M_CachePic (char *path);
void M_DrawTextBox (int x, int y, int width, int lines); void M_DrawTextBox (int x, int y, int width, int lines);
void M_Menu_Quit_f (void); void M_Menu_Quit_f (void);

View file

@ -2319,14 +2319,6 @@ void MP_Keydown(int key, int unicode)
return; return;
} }
} }
if (key == K_ESCAPE)
{
if (keydown[K_LSHIFT] || keydown[K_RSHIFT])
{
Con_ToggleConsole_Force();
return;
}
}
menutime = Sys_DoubleTime(); menutime = Sys_DoubleTime();
if (menu_world.g.time) if (menu_world.g.time)

View file

@ -14,8 +14,6 @@ entity_t *currententity; //nnggh
int r_framecount; int r_framecount;
struct texture_s *r_notexture_mip; struct texture_s *r_notexture_mip;
r_config_t r_config;
qboolean r_blockvidrestart; qboolean r_blockvidrestart;
int r_regsequence; int r_regsequence;
@ -1036,8 +1034,6 @@ qboolean R_ApplyRenderer_Load (rendererstate_t *newr)
pmove.numphysent = 0; pmove.numphysent = 0;
memset(&r_config, 0, sizeof(r_config));
if (qrenderer != QR_NONE) //graphics stuff only when not dedicated if (qrenderer != QR_NONE) //graphics stuff only when not dedicated
{ {
qbyte *data; qbyte *data;
@ -1169,17 +1165,16 @@ TRACE(("dbg: R_ApplyRenderer: initing mods\n"));
TRACE(("dbg: R_ApplyRenderer: reloading server map\n")); TRACE(("dbg: R_ApplyRenderer: reloading server map\n"));
sv.world.worldmodel = Mod_ForName (sv.modelname, MLV_WARN); sv.world.worldmodel = Mod_ForName (sv.modelname, MLV_WARN);
TRACE(("dbg: R_ApplyRenderer: loaded\n")); TRACE(("dbg: R_ApplyRenderer: loaded\n"));
if (sv.world.worldmodel->needload)
{
SV_Error("Bsp went missing on render restart\n");
}
TRACE(("dbg: R_ApplyRenderer: doing that funky phs thang\n")); TRACE(("dbg: R_ApplyRenderer: doing that funky phs thang\n"));
SV_CalcPHS (); SV_CalcPHS ();
TRACE(("dbg: R_ApplyRenderer: clearing world\n")); TRACE(("dbg: R_ApplyRenderer: clearing world\n"));
World_ClearWorld (&sv.world); World_ClearWorld (&sv.world);
if (svs.gametype == GT_PROGS) if (sv.world.worldmodel->needload)
SV_UnspawnServer();
else if (svs.gametype == GT_PROGS)
{ {
for (i = 0; i < MAX_MODELS; i++) for (i = 0; i < MAX_MODELS; i++)
{ {

View file

@ -297,10 +297,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#undef Q3SERVER //trying to trim memory use #undef Q3SERVER //trying to trim memory use
#undef Q2BSPS //emscripten can't cope with bss, leading to increased download time. too lazy to fix. #undef Q2BSPS //emscripten can't cope with bss, leading to increased download time. too lazy to fix.
#undef Q3BSPS //emscripten can't cope with bss, leading to increased download time. too lazy to fix. #undef Q3BSPS //emscripten can't cope with bss, leading to increased download time. too lazy to fix.
#undef PSET_SCRIPT //bss+size // #undef PSET_SCRIPT //bss+size
#define GLSLONLY //pointless having the junk #define GLSLONLY //pointless having the junk
#define GLESONLY //should reduce the conditions a little
#define R_MAX_RECURSE 2 //less bss #define R_MAX_RECURSE 2 //less bss
#undef RTLIGHTS // #undef RTLIGHTS
#endif #endif
#ifdef WINRT #ifdef WINRT
#undef TCPCONNECT //err... #undef TCPCONNECT //err...
@ -319,6 +320,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#undef VOICECHAT #undef VOICECHAT
#endif #endif
#undef TEXTEDITOR #undef TEXTEDITOR
#define GLESONLY //should reduce the conditions a little
#endif #endif
#if defined(NACL) #if defined(NACL)
#undef SUPPORT_ICE #undef SUPPORT_ICE
@ -327,6 +329,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#undef WEBSERVER //no sockets support (certainly no servers) #undef WEBSERVER //no sockets support (certainly no servers)
#undef TCPCONNECT #undef TCPCONNECT
#undef IRCCONNECT #undef IRCCONNECT
#define GLSLONLY //pointless having the junk
#define GLESONLY //should reduce the conditions a little
#endif #endif
#ifndef MULTITHREAD #ifndef MULTITHREAD

View file

@ -2855,7 +2855,7 @@ void Cmd_WriteConfig_f(void)
snprintf(fname, sizeof(fname), "fte.cfg"); snprintf(fname, sizeof(fname), "fte.cfg");
FS_NativePath(fname, FS_GAMEONLY, sysname, sizeof(sysname)); FS_NativePath(fname, FS_GAMEONLY, sysname, sizeof(sysname));
FS_CreatePath(fname, FS_GAMEONLY); FS_CreatePath(fname, FS_GAMEONLY);
f = FS_OpenVFS(fname, "wb", FS_GAMEONLY); f = FS_OpenVFS(fname, "wbp", FS_GAMEONLY);
} }
else else
{ {
@ -2869,7 +2869,7 @@ void Cmd_WriteConfig_f(void)
FS_NativePath(fname, FS_BASEGAMEONLY, sysname, sizeof(sysname)); FS_NativePath(fname, FS_BASEGAMEONLY, sysname, sizeof(sysname));
FS_CreatePath(fname, FS_BASEGAMEONLY); FS_CreatePath(fname, FS_BASEGAMEONLY);
f = FS_OpenVFS(fname, "wb", FS_BASEGAMEONLY); f = FS_OpenVFS(fname, "wbp", FS_BASEGAMEONLY);
} }
if (!f) if (!f)
{ {

View file

@ -12,7 +12,7 @@
#include "winquake.h" #include "winquake.h"
#endif #endif
void fs_game_callback(cvar_t *var, char *oldvalue); static void fs_game_callback(cvar_t *var, char *oldvalue);
hashtable_t filesystemhash; hashtable_t filesystemhash;
qboolean com_fschanged = true; qboolean com_fschanged = true;
qboolean fs_readonly; qboolean fs_readonly;
@ -28,7 +28,7 @@ static int fs_referencetype;
int fs_finds; int fs_finds;
void COM_CheckRegistered (void); void COM_CheckRegistered (void);
void fs_game_callback(cvar_t *var, char *oldvalue) static void fs_game_callback(cvar_t *var, char *oldvalue)
{ {
static qboolean runaway = false; static qboolean runaway = false;
char buf[MAX_OSPATH]; char buf[MAX_OSPATH];
@ -1363,13 +1363,15 @@ vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative r
if (!filename) if (!filename)
return NULL; return NULL;
#ifdef _DEBUG
if (strcmp(mode, "rb")) if (strcmp(mode, "rb"))
if (strcmp(mode, "r+b")) if (strcmp(mode, "r+b"))
if (strcmp(mode, "wb")) if (strcmp(mode, "wb"))
if (strcmp(mode, "w+b")) if (strcmp(mode, "w+b"))
if (strcmp(mode, "ab")) if (strcmp(mode, "ab"))
return NULL; //urm, unable to write/append if (strcmp(mode, "wbp"))
return NULL; //urm, unable to write/append
#endif
//if there can only be one file (eg: write access) find out where it is. //if there can only be one file (eg: write access) find out where it is.
switch (relativeto) switch (relativeto)
@ -1538,7 +1540,7 @@ qboolean FS_Copy(const char *source, const char *dest, enum fs_relative relative
s = FS_OpenVFS(source, "rb", relativesource); s = FS_OpenVFS(source, "rb", relativesource);
if (s) if (s)
{ {
d = FS_OpenVFS(dest, "wb", relativedest); d = FS_OpenVFS(dest, "wbp", relativedest);
if (d) if (d)
{ {
result = true; result = true;
@ -2027,11 +2029,16 @@ void COM_FlushFSCache(void)
} }
} }
if (com_fs_cache.ival) #ifdef FTE_TARGET_WEB
//web target doesn't support filesystem enumeration, so make sure the cache is kept invalid and disabled.
com_fschanged = true;
#else
if (com_fs_cache.ival && com_fschanged)
{ {
//rebuild it if needed //rebuild it if needed
FS_RebuildFSHash(); FS_RebuildFSHash();
} }
#endif
} }
/*since should start as 0, otherwise this can be used to poll*/ /*since should start as 0, otherwise this can be used to poll*/
@ -2210,128 +2217,6 @@ void COM_Gamedir (const char *dir)
Z_Free(dup); Z_Free(dup);
} }
FS_ChangeGame(man, cfg_reload_on_gamedir.ival); FS_ChangeGame(man, cfg_reload_on_gamedir.ival);
#if 0
char thispath[64];
searchpath_t *next;
qboolean isbase;
//don't allow leading dots, hidden files are evil.
//don't allow complex paths. those are evil too.
if (!*dir || *dir == '.' || !strcmp(dir, ".") || strstr(dir, "..") || strstr(dir, "/")
|| strstr(dir, "\\") || strstr(dir, ":") )
{
Con_TPrintf (TL_GAMEDIRAINTPATH);
return;
}
isbase = false;
for (next = com_searchpaths; next; next = next->next)
{
if (next == com_base_searchpaths)
isbase = true;
if (next->funcs == &osfilefuncs)
{
FS_CleanDir(next->purepath, thispath, sizeof(thispath));
if (!strcmp(dir, thispath))
{
if (isbase && com_searchpaths == com_base_searchpaths)
{
Q_strncpyz (gamedirfile, dir, sizeof(gamedirfile));
return;
}
if (!isbase)
return;
break;
}
}
}
FS_ForceToPure(NULL, NULL, 0);
#ifndef SERVERONLY
// Host_WriteConfiguration(); //before we change anything.
#endif
Q_strncpyz (gamedirfile, dir, sizeof(gamedirfile));
#ifndef CLIENTONLY
sv.gamedirchanged = true;
#endif
#ifndef SERVERONLY
cl.gamedirchanged = true;
#endif
FS_FlushFSHashReally();
//
// free up any current game dir info
//
while (com_searchpaths != com_base_searchpaths)
{
com_searchpaths->handle->ClosePath(com_searchpaths->handle);
next = com_searchpaths->next;
Z_Free (com_searchpaths);
com_searchpaths = next;
}
com_fschanged = true;
//
// flush all data, so it will be forced to reload
//
Cache_Flush ();
if (strchr(dir, ';'))
{
//separate case because parsestringset splits by whitespace too
while ((dir = COM_ParseStringSet(dir)))
{
if (!strcmp(dir, ";"))
continue;
if (!*dir)
continue;
FS_AddGameDirectory(dir, va("%s%s", com_gamepath, com_token), ~0, SPF_EXPLICIT);
if (com_homepathenabled)
FS_AddGameDirectory(dir, va("%s%s", com_homepath, com_token), ~0, SPF_EXPLICIT);
}
}
else
{
FS_AddGameDirectory(dir, va("%s%s", com_gamepath, dir), ~0, SPF_EXPLICIT);
if (com_homepathenabled)
FS_AddGameDirectory(dir, va("%s%s", com_homepath, dir), ~0, SPF_EXPLICIT);
}
#ifndef SERVERONLY
if (!isDedicated)
{
// if (qrenderer != QR_NONE) //only do this if we have already started the renderer
// Cbuf_InsertText("vid_restart\n", RESTRICT_LOCAL);
if (COM_FDepthFile("config.cfg", true) <= (com_homepathenabled?1:0))
{
Cbuf_InsertText("cl_warncmd 0\n"
"exec config.cfg\n"
"exec fte.cfg\n"
"cl_warncmd 1\n", RESTRICT_LOCAL, false);
}
}
Shader_Init(); //FIXME!
COM_Effectinfo_Clear();
Validation_FlushFileList(); //prevent previous hacks from making a difference.
//FIXME: load new palette, if different cause a vid_restart.
#endif
#endif
} }
#define QCFG "set allow_download_refpackages 0\n" #define QCFG "set allow_download_refpackages 0\n"
@ -3722,7 +3607,7 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs)
"FTEMANIFEST 1\n" "FTEMANIFEST 1\n"
"game \"\"\n" "game \"\"\n"
"name \"" FULLENGINENAME "\"\n" "name \"" FULLENGINENAME "\"\n"
"defaultexec \\\"vid_fullscreen 0; gl_font cour;vid_width 640; vid_height 480; menu_mods\"\n" "defaultexec \\\"vid_fullscreen 0; gl_font cour;vid_width 640; vid_height 480\"\n"
); );
} }
} }

View file

@ -772,7 +772,7 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
tinheight = inheight; tinheight = inheight;
//don't make scaled width any larger than it needs to be //don't make scaled width any larger than it needs to be
if (r_config.texture_non_power_of_two) if (gl_config.texture_non_power_of_two)
{ {
scaled_width = tinwidth; scaled_width = tinwidth;
scaled_height = tinheight; scaled_height = tinheight;

View file

@ -230,6 +230,7 @@ static void BE_PolyOffset(qboolean pushdepth)
} }
} }
#ifndef GLSLONLY
void GL_TexEnv(GLenum mode) void GL_TexEnv(GLenum mode)
{ {
#ifndef FORCESTATE #ifndef FORCESTATE
@ -302,6 +303,7 @@ static void BE_SetPassBlendMode(int tmu, int pbm)
} }
} }
} }
#endif
/*OpenGL requires glDepthMask(GL_TRUE) or glClear(GL_DEPTH_BUFFER_BIT) will fail*/ /*OpenGL requires glDepthMask(GL_TRUE) or glClear(GL_DEPTH_BUFFER_BIT) will fail*/
void GL_ForceDepthWritable(void) void GL_ForceDepthWritable(void)
@ -927,7 +929,7 @@ static void RevertToKnownState(void)
} }
GL_SelectTexture(0); GL_SelectTexture(0);
#ifndef GLSLONLY
if (!gl_config_nofixedfunc) if (!gl_config_nofixedfunc)
{ {
BE_SetPassBlendMode(0, PBM_REPLACE); BE_SetPassBlendMode(0, PBM_REPLACE);
@ -935,6 +937,7 @@ static void RevertToKnownState(void)
GL_DeSelectProgram(); GL_DeSelectProgram();
} }
#endif
shaderstate.shaderbits &= ~(SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY|SBITS_MASK_BITS|SBITS_AFFINE); shaderstate.shaderbits &= ~(SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY|SBITS_MASK_BITS|SBITS_AFFINE);
shaderstate.shaderbits |= SBITS_MISC_DEPTHWRITE; shaderstate.shaderbits |= SBITS_MISC_DEPTHWRITE;
@ -989,7 +992,6 @@ int GLBE_SetupForShadowMap(texid_t shadowmaptex, int texwidth, int texheight, fl
if (qglShadeModel) if (qglShadeModel)
qglShadeModel(GL_FLAT); qglShadeModel(GL_FLAT);
BE_SetPassBlendMode(0, PBM_REPLACE);
GL_ForceDepthWritable(); GL_ForceDepthWritable();
// qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
@ -1007,7 +1009,7 @@ static void T_Gen_CurrentRender(int tmu)
if (r_refdef.recurse) if (r_refdef.recurse)
return; return;
if (r_config.texture_non_power_of_two) if (gl_config.texture_non_power_of_two_limited)
{ {
vwidth = pwidth; vwidth = pwidth;
vheight = pheight; vheight = pheight;
@ -3040,7 +3042,7 @@ static void BE_Program_Set_Attributes(const program_t *prog, unsigned int perm,
break; break;
case SP_RENDERTEXTURESCALE: case SP_RENDERTEXTURESCALE:
if (r_config.texture_non_power_of_two) if (gl_config.texture_non_power_of_two_limited)
{ {
param4[0] = 1; param4[0] = 1;
param4[1] = 1; param4[1] = 1;
@ -3317,7 +3319,20 @@ void GLBE_SelectMode(backendmode_t mode)
default: default:
break; break;
case BEM_DEPTHONLY: case BEM_DEPTHONLY:
GL_DeSelectProgram(); #ifndef GLSLONLY
if (!gl_config_nofixedfunc)
{
BE_SetPassBlendMode(0, PBM_REPLACE);
GL_DeSelectProgram();
}
else
#endif
if (!shaderstate.allblackshader)
{
const char *defs[] = {NULL};
shaderstate.allblackshader = GLSlang_CreateProgram("allblackprogram", gl_config_gles?100:110, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false, NULL);
shaderstate.allblack_mvp = qglGetUniformLocationARB(shaderstate.allblackshader, "m_modelviewprojection");
}
/*BEM_DEPTHONLY does support mesh writing, but its not the only way its used... FIXME!*/ /*BEM_DEPTHONLY does support mesh writing, but its not the only way its used... FIXME!*/
while(shaderstate.lastpasstmus>0) while(shaderstate.lastpasstmus>0)
{ {
@ -3327,7 +3342,6 @@ void GLBE_SelectMode(backendmode_t mode)
//we don't write or blend anything (maybe alpha test... but mneh) //we don't write or blend anything (maybe alpha test... but mneh)
BE_SendPassBlendDepthMask(SBITS_MISC_DEPTHWRITE | SBITS_MASK_BITS); BE_SendPassBlendDepthMask(SBITS_MISC_DEPTHWRITE | SBITS_MASK_BITS);
BE_SetPassBlendMode(0, PBM_REPLACE);
GL_CullFace(SHADER_CULL_FRONT); GL_CullFace(SHADER_CULL_FRONT);
break; break;
@ -3348,6 +3362,7 @@ void GLBE_SelectMode(backendmode_t mode)
{ {
GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex); GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex);
} }
#ifndef GLSLONLY
if (!gl_config_nofixedfunc) if (!gl_config_nofixedfunc)
{ {
GL_DeSelectProgram(); GL_DeSelectProgram();
@ -3355,6 +3370,7 @@ void GLBE_SelectMode(backendmode_t mode)
//replace mode please //replace mode please
BE_SetPassBlendMode(0, PBM_REPLACE); BE_SetPassBlendMode(0, PBM_REPLACE);
} }
#endif
//we don't write or blend anything (maybe alpha test... but mneh) //we don't write or blend anything (maybe alpha test... but mneh)
BE_SendPassBlendDepthMask(SBITS_MISC_DEPTHCLOSERONLY | SBITS_MASK_BITS); BE_SendPassBlendDepthMask(SBITS_MISC_DEPTHCLOSERONLY | SBITS_MASK_BITS);
@ -3400,7 +3416,10 @@ void GLBE_SelectMode(backendmode_t mode)
Vector4Set(shaderstate.pendingcolourflat, 1, 1, 1, 1); Vector4Set(shaderstate.pendingcolourflat, 1, 1, 1, 1);
shaderstate.pendingcolourvbo = 0; shaderstate.pendingcolourvbo = 0;
shaderstate.pendingcolourpointer = NULL; shaderstate.pendingcolourpointer = NULL;
BE_SetPassBlendMode(0, PBM_MODULATE); #ifndef GLSLONLY
if (!gl_config_nofixedfunc)
BE_SetPassBlendMode(0, PBM_MODULATE);
#endif
BE_SendPassBlendDepthMask(SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA | SBITS_MISC_DEPTHEQUALONLY); BE_SendPassBlendDepthMask(SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA | SBITS_MISC_DEPTHEQUALONLY);
break; break;
} }
@ -3451,10 +3470,12 @@ static qboolean GLBE_RegisterLightShader(int mode)
{ {
if (!shaderstate.inited_shader_light[mode]) if (!shaderstate.inited_shader_light[mode])
{ {
char *name = va("rtlight%s%s%s", char *name = va("rtlight%s%s%s%s",
(mode & LSHADER_SMAP)?"#PCF":"", (mode & LSHADER_SMAP)?"#PCF":"",
(mode & LSHADER_SPOT)?"#SPOT":"", (mode & LSHADER_SPOT)?"#SPOT":"",
(mode & LSHADER_CUBE)?"#CUBE":""); (mode & LSHADER_CUBE)?"#CUBE":"",
(gl_config.arb_shadow && (mode & (LSHADER_SMAP|LSHADER_SPOT|LSHADER_CUBE)))?"#USE_ARB_SHADOW":""
);
shaderstate.inited_shader_light[mode] = true; shaderstate.inited_shader_light[mode] = true;
shaderstate.shader_light[mode] = R_RegisterCustom(name, SUF_NONE, Shader_LightPass, NULL); shaderstate.shader_light[mode] = R_RegisterCustom(name, SUF_NONE, Shader_LightPass, NULL);
@ -3847,7 +3868,18 @@ static void DrawMeshes(void)
case BEM_WIREFRAME: case BEM_WIREFRAME:
//FIXME: do this with a shader instead? its not urgent as we can draw the shader normally anyway, just faster. //FIXME: do this with a shader instead? its not urgent as we can draw the shader normally anyway, just faster.
//FIXME: we need to use a shader for vertex blending. not really an issue with mdl, but more significant with iqms (base pose!). //FIXME: we need to use a shader for vertex blending. not really an issue with mdl, but more significant with iqms (base pose!).
GL_DeSelectProgram(); #ifndef GLSLONLY
if (!gl_config_nofixedfunc)
{
BE_SetPassBlendMode(0, PBM_REPLACE);
GL_DeSelectProgram();
}
else
#endif
{
break;
}
shaderstate.pendingcolourvbo = 0; shaderstate.pendingcolourvbo = 0;
shaderstate.pendingcolourpointer = NULL; shaderstate.pendingcolourpointer = NULL;
Vector4Set(shaderstate.pendingcolourflat, 1, 1, 1, 1); Vector4Set(shaderstate.pendingcolourflat, 1, 1, 1, 1);
@ -3855,14 +3887,13 @@ static void DrawMeshes(void)
{ {
GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex); GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex);
} }
BE_SetPassBlendMode(0, PBM_REPLACE);
BE_SendPassBlendDepthMask(shaderstate.curshader->passes[0].shaderbits | SBITS_MISC_NODEPTHTEST); BE_SendPassBlendDepthMask(shaderstate.curshader->passes[0].shaderbits | SBITS_MISC_NODEPTHTEST);
BE_EnableShaderAttributes((1u<<VATTR_LEG_VERTEX) | (1u<<VATTR_LEG_COLOUR), 0); BE_EnableShaderAttributes((1u<<VATTR_LEG_VERTEX) | (1u<<VATTR_LEG_COLOUR), 0);
BE_SubmitMeshChain(); BE_SubmitMeshChain();
break; break;
case BEM_DEPTHDARK: case BEM_DEPTHDARK:
if ((shaderstate.curshader->flags & SHADER_HASLIGHTMAP) && !TEXVALID(shaderstate.curtexnums->fullbright) && !gl_config_nofixedfunc) if ((shaderstate.curshader->flags & SHADER_HASLIGHTMAP) && !TEXVALID(shaderstate.curtexnums->fullbright))
{ {
if (gl_config.arb_shader_objects) if (gl_config.arb_shader_objects)
{ {
@ -3875,7 +3906,7 @@ static void DrawMeshes(void)
GL_SelectProgram(shaderstate.allblackshader); GL_SelectProgram(shaderstate.allblackshader);
BE_SendPassBlendDepthMask(shaderstate.curshader->passes[0].shaderbits); BE_SendPassBlendDepthMask(shaderstate.curshader->passes[0].shaderbits);
BE_EnableShaderAttributes(1u<<VATTR_LEG_VERTEX, 0); BE_EnableShaderAttributes(gl_config_nofixedfunc?(1u<<VATTR_VERTEX1):(1u<<VATTR_LEG_VERTEX), 0);
if (shaderstate.allblackshader != shaderstate.lastuniform && shaderstate.allblack_mvp != -1) if (shaderstate.allblackshader != shaderstate.lastuniform && shaderstate.allblack_mvp != -1)
{ {
float m16[16]; float m16[16];
@ -3885,8 +3916,10 @@ static void DrawMeshes(void)
BE_SubmitMeshChain(); BE_SubmitMeshChain();
shaderstate.lastuniform = shaderstate.allblackshader; shaderstate.lastuniform = shaderstate.allblackshader;
break;
} }
else #ifndef GLSLONLY
else if (!gl_config_nofixedfunc)
{ {
GL_DeSelectProgram(); GL_DeSelectProgram();
shaderstate.pendingcolourvbo = 0; shaderstate.pendingcolourvbo = 0;
@ -3902,8 +3935,9 @@ static void DrawMeshes(void)
BE_EnableShaderAttributes((1u<<VATTR_LEG_VERTEX) | (1u<<VATTR_LEG_COLOUR), 0); BE_EnableShaderAttributes((1u<<VATTR_LEG_VERTEX) | (1u<<VATTR_LEG_COLOUR), 0);
BE_SubmitMeshChain(); BE_SubmitMeshChain();
break;
} }
break; #endif
} }
//fallthrough //fallthrough
case BEM_STANDARD: case BEM_STANDARD:
@ -4613,6 +4647,8 @@ void GLBE_FBO_Destroy(fbostate_t *state)
//state->colour is created if usedepth is set and it doesn't previously exist //state->colour is created if usedepth is set and it doesn't previously exist
int GLBE_FBO_Update(fbostate_t *state, unsigned int enables, texid_t *destcol, int mrt, texid_t destdepth, int width, int height) int GLBE_FBO_Update(fbostate_t *state, unsigned int enables, texid_t *destcol, int mrt, texid_t destdepth, int width, int height)
{ {
GLenum allcolourattachments[] ={GL_COLOR_ATTACHMENT0_EXT,GL_COLOR_ATTACHMENT1_EXT,GL_COLOR_ATTACHMENT2_EXT,GL_COLOR_ATTACHMENT3_EXT,
GL_COLOR_ATTACHMENT4_EXT,GL_COLOR_ATTACHMENT5_EXT,GL_COLOR_ATTACHMENT6_EXT,GL_COLOR_ATTACHMENT7_EXT};
int i; int i;
int old; int old;
@ -4635,12 +4671,10 @@ int GLBE_FBO_Update(fbostate_t *state, unsigned int enables, texid_t *destcol, i
{ {
qglGenFramebuffersEXT(1, &state->fbo); qglGenFramebuffersEXT(1, &state->fbo);
old = GLBE_FBO_Push(state); old = GLBE_FBO_Push(state);
enables |= FBO_RESET; enables |= FBO_RESET;
} }
else else
old = GLBE_FBO_Push(state); old = GLBE_FBO_Push(state);
if (state->rb_size[0] != width || state->rb_size[1] != height || (enables & FBO_RESET)) if (state->rb_size[0] != width || state->rb_size[1] != height || (enables & FBO_RESET))
{ {
if (state->rb_depth && !(enables & FBO_RB_DEPTH)) if (state->rb_depth && !(enables & FBO_RB_DEPTH))
@ -4657,19 +4691,25 @@ int GLBE_FBO_Update(fbostate_t *state, unsigned int enables, texid_t *destcol, i
state->rb_size[1] = height; state->rb_size[1] = height;
enables |= FBO_RESET; enables |= FBO_RESET;
if (mrt) if (mrt)
{ { //be careful here, gles2 doesn't support glDrawBuffer. hopefully it'll make things up, but this is worrying.
qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); if (qglDrawBuffers)
qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT); qglDrawBuffers(mrt, allcolourattachments);
else if (qglDrawBuffer)
qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
if (qglReadBuffer)
qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
} }
else else
{ {
qglDrawBuffer(GL_NONE); if (qglDrawBuffers)
qglReadBuffer(GL_NONE); qglDrawBuffers(0, NULL);
else if (qglDrawBuffer)
qglDrawBuffer(GL_NONE);
if (qglReadBuffer)
qglReadBuffer(GL_NONE);
} }
} }
if (enables & FBO_TEX_DEPTH) if (enables & FBO_TEX_DEPTH)
{ {
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, destdepth.num, 0); qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, destdepth.num, 0);
@ -4681,9 +4721,8 @@ int GLBE_FBO_Update(fbostate_t *state, unsigned int enables, texid_t *destcol, i
{ {
//create an unnamed depth buffer //create an unnamed depth buffer
qglGenRenderbuffersEXT(1, &state->rb_depth); qglGenRenderbuffersEXT(1, &state->rb_depth);
qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, state->rb_depth); // if (!gl_config.ext_packed_depth_stencil)
if (!gl_config.ext_packed_depth_stencil) // qglGenRenderbuffersEXT(1, &state->rb_stencil);
qglGenRenderbuffersEXT(1, &state->rb_stencil);
enables |= FBO_RESET; //make sure it gets instanciated enables |= FBO_RESET; //make sure it gets instanciated
} }
@ -4694,10 +4733,9 @@ int GLBE_FBO_Update(fbostate_t *state, unsigned int enables, texid_t *destcol, i
qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, state->rb_size[0], state->rb_size[1]); qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, state->rb_size[0], state->rb_size[1]);
else else
{ {
qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24_ARB, state->rb_size[0], state->rb_size[1]); qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16_ARB, state->rb_size[0], state->rb_size[1]);
// qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, state->rb_stencil);
qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, state->rb_stencil); // qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8_EXT, state->rb_size[0], state->rb_size[1]);
qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8_EXT, state->rb_size[0], state->rb_size[1]);
} }
qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, state->rb_depth); qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, state->rb_depth);
if (gl_config.ext_packed_depth_stencil) if (gl_config.ext_packed_depth_stencil)
@ -4709,6 +4747,38 @@ int GLBE_FBO_Update(fbostate_t *state, unsigned int enables, texid_t *destcol, i
for (i = 0; i < mrt; i++) for (i = 0; i < mrt; i++)
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, GL_TEXTURE_2D, destcol[i].num, 0); qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, GL_TEXTURE_2D, destcol[i].num, 0);
i = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (GL_FRAMEBUFFER_COMPLETE_EXT != i)
{
switch(i)
{
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
Con_Printf("glCheckFramebufferStatus reported GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
Con_Printf("glCheckFramebufferStatus reported GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
Con_Printf("glCheckFramebufferStatus reported GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
Con_Printf("glCheckFramebufferStatus reported GL_FRAMEBUFFER_INCOMPLETE_FORMATS\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
Con_Printf("glCheckFramebufferStatus reported GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
Con_Printf("glCheckFramebufferStatus reported GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER\n");
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
Con_Printf("glCheckFramebufferStatus reported GL_FRAMEBUFFER_UNSUPPORTED\n");
break;
default:
Con_Printf("glCheckFramebufferStatus returned %#x\n", i);
break;
}
}
return old; return old;
} }
/* /*

View file

@ -114,7 +114,7 @@ static void R_SetupBloomTextures(int w, int h)
if (!TEXVALID(pingtex[i][j])) if (!TEXVALID(pingtex[i][j]))
{ {
sprintf(name, "***bloom*%c*%i***", 'a'+i, j); sprintf(name, "***bloom*%c*%i***", 'a'+i, j);
TEXASSIGN(pingtex[i][j], GL_AllocNewTexture(name, texwidth[j], texheight[j], IF_NOMIPMAP|IF_NOPICMIP|IF_LINEAR)); TEXASSIGN(pingtex[i][j], GL_AllocNewTexture(name, texwidth[j], texheight[j], IF_CLAMP|IF_NOMIPMAP|IF_NOPICMIP|IF_LINEAR));
} }
GL_MTBind(0, GL_TEXTURE_2D, pingtex[i][j]); GL_MTBind(0, GL_TEXTURE_2D, pingtex[i][j]);
qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, texwidth[j], texheight[j], 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, texwidth[j], texheight[j], 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
@ -180,7 +180,7 @@ qboolean R_CanBloom(void)
return false; return false;
if (!gl_config.arb_shader_objects) if (!gl_config.arb_shader_objects)
return false; return false;
if (!r_config.texture_non_power_of_two) if (!gl_config.texture_non_power_of_two_limited)
return false; return false;
return true; return true;

View file

@ -1075,10 +1075,14 @@ static qboolean GL_UploadCompressed (qbyte *file, int *out_width, int *out_heigh
void GL_RoundDimensions(int *scaled_width, int *scaled_height, unsigned int flags) void GL_RoundDimensions(int *scaled_width, int *scaled_height, unsigned int flags)
{ {
if (r_config.texture_non_power_of_two) //NPOT is a simple extension that relaxes errors. if (gl_config.texture_non_power_of_two) //NPOT is a simple extension that relaxes errors.
{ {
TRACE(("dbg: GL_RoundDimensions: GL_ARB_texture_non_power_of_two\n")); TRACE(("dbg: GL_RoundDimensions: GL_ARB_texture_non_power_of_two\n"));
} }
else if (gl_config.texture_non_power_of_two_limited && (flags&IF_NOMIPMAP) && (flags&IF_CLAMP))
{
//clamped mipless textures will work as-is in gles2/webgl
}
else else
{ {
int width = *scaled_width; int width = *scaled_width;
@ -1089,6 +1093,7 @@ void GL_RoundDimensions(int *scaled_width, int *scaled_height, unsigned int flag
; ;
/*round npot textures down if we're running on an embedded system*/ /*round npot textures down if we're running on an embedded system*/
/*
if (gl_config.gles) if (gl_config.gles)
{ {
if (*scaled_width != width) if (*scaled_width != width)
@ -1096,6 +1101,7 @@ void GL_RoundDimensions(int *scaled_width, int *scaled_height, unsigned int flag
if (*scaled_height != height) if (*scaled_height != height)
*scaled_height >>= 1; *scaled_height >>= 1;
} }
*/
} }
if (flags & IF_NOMIPMAP) if (flags & IF_NOMIPMAP)
@ -1251,10 +1257,10 @@ static void GL_Upload32_Int (const char *name, unsigned *data, int width, int he
{ {
glcolormode = GL_RGBA; /*our input is RGBA or RGBX, with the internal format restriction, we must therefore always have an alpha value*/ glcolormode = GL_RGBA; /*our input is RGBA or RGBX, with the internal format restriction, we must therefore always have an alpha value*/
if (gl_config.webgl_ie) if (1)//gl_config.webgl_ie)
{ { //fixme: I think my npot mips don't work properly.
type = GL_UNSIGNED_BYTE; type = GL_UNSIGNED_BYTE;
glcolormode = GL_RGBA; //I hope its 1. note that samples matching colormode means we can't use packed formats, and I'm too lazy to strip it glcolormode = GL_RGBA; //I hope alpha is 1. note that samples matching colormode means we can't use packed formats, and I'm too lazy to strip it
} }
else if (flags & IF_NOALPHA) else if (flags & IF_NOALPHA)
{ {

View file

@ -544,7 +544,7 @@ void R_RenderScene (void)
#ifdef GL_STEREO #ifdef GL_STEREO
GLint glb; GLint glb;
qglGetIntegerv(GL_STEREO, &glb); qglGetIntegerv(GL_STEREO, &glb);
if (!glb) if (!glb || !qglDrawBuffer)
#endif #endif
stereomode = 0; //we are not a stereo context, so no stereoscopic rendering (this encourages it to otherwise be left enabled, which means the user is more likely to spot that they asked it to give a slower context. stereomode = 0; //we are not a stereo context, so no stereoscopic rendering (this encourages it to otherwise be left enabled, which means the user is more likely to spot that they asked it to give a slower context.
} }
@ -1283,7 +1283,7 @@ static void R_RenderMotionBlur(void)
shader_t *shader; shader_t *shader;
//figure out the size of our texture. //figure out the size of our texture.
if (r_config.texture_non_power_of_two) if (gl_config.texture_non_power_of_two_limited)
{ //we can use any size, supposedly { //we can use any size, supposedly
vwidth = vid.pixelwidth; vwidth = vid.pixelwidth;
vheight = vid.pixelheight; vheight = vid.pixelheight;
@ -1402,7 +1402,7 @@ qboolean R_RenderScene_Cubemap(void)
// prect.y = (vrect.y * vid.pixelheight)/vid.height; // prect.y = (vrect.y * vid.pixelheight)/vid.height;
// prect.height = (vrect.height * vid.pixelheight)/vid.height; // prect.height = (vrect.height * vid.pixelheight)/vid.height;
if (r_config.texture_non_power_of_two) if (r_config.texture_non_power_of_two_limited)
{ {
if (prect.width < prect.height) if (prect.width < prect.height)
cmapsize = prect.width; cmapsize = prect.width;
@ -1596,7 +1596,7 @@ void GLR_RenderView (void)
} }
//disable stuff if its simply not supported. //disable stuff if its simply not supported.
if (dofbo || !gl_config.arb_shader_objects || !gl_config.ext_framebuffer_objects || !r_config.texture_non_power_of_two) if (dofbo || !gl_config.arb_shader_objects || !gl_config.ext_framebuffer_objects || !gl_config.texture_non_power_of_two_limited)
r_refdef.flags &= ~(RDF_ALLPOSTPROC); //block all of this stuff r_refdef.flags &= ~(RDF_ALLPOSTPROC); //block all of this stuff

View file

@ -314,20 +314,21 @@ static qboolean Shader_EvaluateCondition(shader_t *shader, char **ptr)
else else
{ {
float lhs; float lhs;
cv = Cvar_Get(token, "", 0, "Shader Conditions"); if (*token >= '0' && *token <= '9')
if (cv) lhs = strtod(token, NULL);
{
cv->flags |= CVAR_SHADERSYSTEM;
lhs = cv->value;
}
else else
{ {
if (*token < '0' || *token > '9') cv = Cvar_Get(token, "", 0, "Shader Conditions");
if (cv)
{
cv->flags |= CVAR_SHADERSYSTEM;
lhs = cv->value;
}
else
{ {
Con_Printf("Shader_EvaluateCondition: '%s' is not a cvar\n", token); Con_Printf("Shader_EvaluateCondition: '%s' is not a cvar\n", token);
return conditiontrue; return conditiontrue;
} }
lhs = strtod(token, NULL);
} }
if (*token) if (*token)
token = COM_ParseExt(ptr, false, false); token = COM_ParseExt(ptr, false, false);
@ -356,7 +357,7 @@ static qboolean Shader_EvaluateCondition(shader_t *shader, char **ptr)
else else
{ {
if (cv) if (cv)
conditiontrue = conditiontrue == !!cv->value; conditiontrue = conditiontrue == !!lhs;
} }
} }
if (*token) if (*token)

View file

@ -52,23 +52,23 @@ cvar_t r_shadow_shadowmapping_nearclip = CVAR("r_shadow_shadowmapping_nearclip",
cvar_t r_shadow_shadowmapping_bias = CVAR("r_shadow_shadowmapping_bias", "0.03"); cvar_t r_shadow_shadowmapping_bias = CVAR("r_shadow_shadowmapping_bias", "0.03");
cvar_t r_shadow_scissor = CVAR("r_shadow_scissor", "1"); cvar_t r_shadow_scissor = CVAR("r_shadow_scissor", "1");
cvar_t r_shadow_realtime_world = SCVARF ("r_shadow_realtime_world", "0", CVAR_ARCHIVE); cvar_t r_shadow_realtime_world = CVARF ("r_shadow_realtime_world", "0", CVAR_ARCHIVE);
cvar_t r_shadow_realtime_world_shadows = SCVARF ("r_shadow_realtime_world_shadows", "1", CVAR_ARCHIVE); cvar_t r_shadow_realtime_world_shadows = CVARF ("r_shadow_realtime_world_shadows", "1", CVAR_ARCHIVE);
cvar_t r_shadow_realtime_world_lightmaps = SCVARF ("r_shadow_realtime_world_lightmaps", "0", 0); cvar_t r_shadow_realtime_world_lightmaps = CVARF ("r_shadow_realtime_world_lightmaps", "0", 0);
#ifdef FTE_TARGET_WEB #ifdef FTE_TARGET_WEB
cvar_t r_shadow_realtime_dlight = SCVARF ("r_shadow_realtime_dlight", "0", CVAR_ARCHIVE); cvar_t r_shadow_realtime_dlight = CVARF ("r_shadow_realtime_dlight", "0", CVAR_ARCHIVE);
#else #else
cvar_t r_shadow_realtime_dlight = SCVARF ("r_shadow_realtime_dlight", "1", CVAR_ARCHIVE); cvar_t r_shadow_realtime_dlight = CVARF ("r_shadow_realtime_dlight", "1", CVAR_ARCHIVE);
#endif #endif
cvar_t r_shadow_realtime_dlight_shadows = SCVARF ("r_shadow_realtime_dlight_shadows", "1", CVAR_ARCHIVE); cvar_t r_shadow_realtime_dlight_shadows = CVARF ("r_shadow_realtime_dlight_shadows", "1", CVAR_ARCHIVE);
cvar_t r_shadow_realtime_dlight_ambient = SCVAR ("r_shadow_realtime_dlight_ambient", "0"); cvar_t r_shadow_realtime_dlight_ambient = CVAR ("r_shadow_realtime_dlight_ambient", "0");
cvar_t r_shadow_realtime_dlight_diffuse = SCVAR ("r_shadow_realtime_dlight_diffuse", "1"); cvar_t r_shadow_realtime_dlight_diffuse = CVAR ("r_shadow_realtime_dlight_diffuse", "1");
cvar_t r_shadow_realtime_dlight_specular = SCVAR ("r_shadow_realtime_dlight_specular", "4"); //excessive, but noticable. its called stylized, okay? shiesh, some people cvar_t r_shadow_realtime_dlight_specular = CVAR ("r_shadow_realtime_dlight_specular", "4"); //excessive, but noticable. its called stylized, okay? shiesh, some people
cvar_t r_editlights_import_radius = SCVAR ("r_editlights_import_radius", "1"); cvar_t r_editlights_import_radius = CVAR ("r_editlights_import_radius", "1");
cvar_t r_editlights_import_ambient = SCVAR ("r_editlights_import_ambient", "0"); cvar_t r_editlights_import_ambient = CVAR ("r_editlights_import_ambient", "0");
cvar_t r_editlights_import_diffuse = SCVAR ("r_editlights_import_diffuse", "1"); cvar_t r_editlights_import_diffuse = CVAR ("r_editlights_import_diffuse", "1");
cvar_t r_editlights_import_specular = SCVAR ("r_editlights_import_specular", "1"); //excessive, but noticable. its called stylized, okay? shiesh, some people cvar_t r_editlights_import_specular = CVAR ("r_editlights_import_specular", "1"); //excessive, but noticable. its called stylized, okay? shiesh, some people
cvar_t r_shadow_shadowmapping = SCVARF ("r_shadow_shadowmapping", "1", 0); cvar_t r_shadow_shadowmapping = CVARD ("r_shadow_shadowmapping", "1", "Enables soft shadows");
cvar_t r_shadow_shadowmapping_precision = CVARD ("r_shadow_shadowmapping_precision", "1", "Scales the shadowmap detail level up or down."); cvar_t r_shadow_shadowmapping_precision = CVARD ("r_shadow_shadowmapping_precision", "1", "Scales the shadowmap detail level up or down.");
extern cvar_t r_shadow_shadowmapping_nearclip; extern cvar_t r_shadow_shadowmapping_nearclip;
extern cvar_t r_shadow_shadowmapping_bias; extern cvar_t r_shadow_shadowmapping_bias;
@ -88,7 +88,7 @@ void Sh_Reset(void)
#ifdef GLQUAKE #ifdef GLQUAKE
if (shadow_fbo_id) if (shadow_fbo_id)
{ {
qglDeleteRenderbuffersEXT(1, &shadow_fbo_id); qglDeleteFramebuffersEXT(1, &shadow_fbo_id);
shadow_fbo_id = 0; shadow_fbo_id = 0;
shadow_fbo_depth_num = 0; shadow_fbo_depth_num = 0;
} }
@ -109,7 +109,7 @@ void Sh_Reset(void)
} }
if (crepuscular_fbo_id) if (crepuscular_fbo_id)
{ {
qglDeleteRenderbuffersEXT(1, &crepuscular_fbo_id); qglDeleteFramebuffersEXT(1, &crepuscular_fbo_id);
crepuscular_fbo_id = 0; crepuscular_fbo_id = 0;
} }
#endif #endif
@ -772,6 +772,7 @@ static void SHM_RecursiveWorldNodeQ1_r (dlight_t *dl, mnode_t *node)
SHM_RecursiveWorldNodeQ1_r (dl, node->children[!side]); SHM_RecursiveWorldNodeQ1_r (dl, node->children[!side]);
} }
#ifdef Q2BSPS
static void SHM_RecursiveWorldNodeQ2_r (dlight_t *dl, mnode_t *node) static void SHM_RecursiveWorldNodeQ2_r (dlight_t *dl, mnode_t *node)
{ {
int c, side; int c, side;
@ -966,7 +967,6 @@ static void SHM_RecursiveWorldNodeQ2_r (dlight_t *dl, mnode_t *node)
SHM_RecursiveWorldNodeQ2_r (dl, node->children[!side]); SHM_RecursiveWorldNodeQ2_r (dl, node->children[!side]);
} }
#ifdef Q2BSPS
static void SHM_MarkLeavesQ2(dlight_t *dl, unsigned char *lvis, unsigned char *vvis) static void SHM_MarkLeavesQ2(dlight_t *dl, unsigned char *lvis, unsigned char *vvis)
{ {
mnode_t *node; mnode_t *node;
@ -2025,8 +2025,10 @@ void GL_BeginRenderBuffer_DepthOnly(texid_t depthtexture)
// qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24_ARB, SHADOWMAP_SIZE*3, SHADOWMAP_SIZE*2); // qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24_ARB, SHADOWMAP_SIZE*3, SHADOWMAP_SIZE*2);
// qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, drb); // qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, drb);
qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); if (qglDrawBuffer)
qglReadBuffer(GL_NONE); qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
if (qglReadBuffer)
qglReadBuffer(GL_NONE);
} }
else else
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shadow_fbo_id); qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shadow_fbo_id);
@ -2044,8 +2046,12 @@ void GL_BeginRenderBuffer_DepthOnly(texid_t depthtexture)
{ {
qglGenFramebuffersEXT(1, &shadow_fbo_id); qglGenFramebuffersEXT(1, &shadow_fbo_id);
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shadow_fbo_id); qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shadow_fbo_id);
qglDrawBuffer(GL_NONE); if (qglDrawBuffers)
qglReadBuffer(GL_NONE); qglDrawBuffers(0, NULL);
else if (qglDrawBuffer)
qglDrawBuffer(GL_NONE);
if (qglReadBuffer)
qglReadBuffer(GL_NONE);
} }
else else
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shadow_fbo_id); qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shadow_fbo_id);
@ -2370,24 +2376,28 @@ qboolean Sh_GenShadowMap (dlight_t *l, qbyte *lvis, int smsize)
#ifdef DBG_COLOURNOTDEPTH #ifdef DBG_COLOURNOTDEPTH
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SHADOWMAP_SIZE*3, SHADOWMAP_SIZE*2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SHADOWMAP_SIZE*3, SHADOWMAP_SIZE*2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
#else #else
qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16_ARB, SHADOWMAP_SIZE*3, SHADOWMAP_SIZE*2, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); if (gl_config.gles)
qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, SHADOWMAP_SIZE*3, SHADOWMAP_SIZE*2, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL);
else
qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16_ARB, SHADOWMAP_SIZE*3, SHADOWMAP_SIZE*2, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL);
#endif #endif
} }
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
#if 1//def DBG_COLOURNOTDEPTH #if 0//def DBG_COLOURNOTDEPTH
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
#else #else
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#endif #endif
//in case we're using shadow samplers //in case we're using shadow samplers
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); if (gl_config.arb_shadow)
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); {
qglTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
qglTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
}
} }
/*set framebuffer*/ /*set framebuffer*/
@ -3230,6 +3240,7 @@ void Sh_PurgeShadowMeshes(void)
} }
free(edge); free(edge);
edge = NULL; edge = NULL;
maxedge = 0;
} }
void Sh_PreGenerateLights(void) void Sh_PreGenerateLights(void)
@ -3309,8 +3320,14 @@ void Sh_CheckSettings(void)
{ {
#ifdef GLQUAKE #ifdef GLQUAKE
case QR_OPENGL: case QR_OPENGL:
canshadowless = true; //falls back to crappy texture env canshadowless = gl_config.arb_shader_objects || !gl_config_nofixedfunc; //falls back to crappy texture env
if (gl_config.arb_shader_objects && gl_config.ext_framebuffer_objects && gl_config.arb_shadow) if (!gl_config.arb_shader_objects)
Con_Printf("No arb_shader_objects\n");
if (!gl_config.ext_framebuffer_objects)
Con_Printf("No ext_framebuffer_objects\n");
if (!gl_config.arb_depth_texture)
Con_Printf("No arb_depth_texture\n");
if (gl_config.arb_shader_objects && gl_config.ext_framebuffer_objects && gl_config.arb_depth_texture)// && gl_config.arb_shadow)
cansmap = true; cansmap = true;
if (gl_stencilbits) if (gl_stencilbits)
canstencil = true; canstencil = true;
@ -3337,14 +3354,12 @@ void Sh_CheckSettings(void)
break; break;
#endif #endif
default: default:
r_shadow_realtime_world.ival = 0; break;
r_shadow_realtime_dlight.ival = 0;
return;
} }
if (!canstencil && !cansmap && !canshadowless) if (!canstencil && !cansmap && !canshadowless)
{ {
//no shadow methods available at all. //can't even do lighting
if (r_shadow_realtime_world.ival || r_shadow_realtime_dlight.ival) if (r_shadow_realtime_world.ival || r_shadow_realtime_dlight.ival)
Con_Printf("Missing driver extensions: realtime lighting is not possible.\n"); Con_Printf("Missing driver extensions: realtime lighting is not possible.\n");
r_shadow_realtime_world.ival = 0; r_shadow_realtime_world.ival = 0;

View file

@ -181,8 +181,9 @@ void (APIENTRY *qglBindVertexArray)(GLuint vaoarray);
const GLubyte * (APIENTRY * qglGetStringi) (GLenum name, GLuint index); const GLubyte * (APIENTRY * qglGetStringi) (GLenum name, GLuint index);
void (APIENTRY * qglGetPointerv) (GLenum pname, GLvoid **parms); void (APIENTRY * qglGetPointerv) (GLenum pname, GLvoid **parms);
void (APIENTRY *qglDrawBuffers)(GLsizei n, GLsizei *ids); //gl2
#ifndef GL_STATIC #ifndef GL_STATIC
void (APIENTRY *qglGenRenderbuffersEXT)(GLsizei n, GLuint* ids); void (APIENTRY *qglGenRenderbuffersEXT)(GLsizei n, GLuint *ids);
void (APIENTRY *qglBindRenderbufferEXT)(GLenum target, GLuint id); void (APIENTRY *qglBindRenderbufferEXT)(GLenum target, GLuint id);
void (APIENTRY *qglRenderbufferStorageEXT)(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height); void (APIENTRY *qglRenderbufferStorageEXT)(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height);
void (APIENTRY *qglFramebufferRenderbufferEXT)(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint textureId); void (APIENTRY *qglFramebufferRenderbufferEXT)(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint textureId);
@ -442,8 +443,20 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
s++; s++;
gl_minor_version = atoi(s); gl_minor_version = atoi(s);
} }
if (webgl) if (webgl) //webgl version 1 equates to gles 2.
gl_major_version+=1; {
if (gl_major_version < 1)
{ //ie reports a bollocks version. don't try using fixed function stuff.
gl_major_version = 2;
gl_minor_version = 0;
}
else if (gl_major_version == 1)
gl_major_version += 1;
//webgl2 is not defined yet. either 2 will be gles3 or they'll skip it or something I don't know.
//so assume webgl2 is still equivelent to gles2, to avoid confusions.
}
//FIXME: verify gles3 works properly.
//yes, I know, this can't cope with minor versions of 10+... I don't care yet. //yes, I know, this can't cope with minor versions of 10+... I don't care yet.
gl_config.glversion += gl_major_version + (gl_minor_version/10.f); gl_config.glversion += gl_major_version + (gl_minor_version/10.f);
@ -577,22 +590,6 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
qglGenProgramsARB = NULL; qglGenProgramsARB = NULL;
*/ */
r_config.texture_non_power_of_two = false;
gl_config.sgis_generate_mipmap = false;
gl_config.tex_env_combine = false;
gl_config.env_add = false;
gl_config.nv_tex_env_combine4 = false;
gl_config.arb_texture_env_combine = false;
gl_config.arb_texture_env_dot3 = false;
gl_config.arb_texture_cube_map = false;
gl_config.arb_shader_objects = false;
gl_config.ext_framebuffer_objects = false;
gl_config.ext_texture_filter_anisotropic = 0;
gl_config.ext_packed_depth_stencil = GL_CheckExtension("GL_EXT_packed_depth_stencil"); gl_config.ext_packed_depth_stencil = GL_CheckExtension("GL_EXT_packed_depth_stencil");
if (GL_CheckExtension("GL_EXT_texture_filter_anisotropic")) if (GL_CheckExtension("GL_EXT_texture_filter_anisotropic"))
@ -603,7 +600,10 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
} }
if (GL_CheckExtension("GL_ARB_texture_non_power_of_two") || GL_CheckExtension("GL_OES_texture_npot")) if (GL_CheckExtension("GL_ARB_texture_non_power_of_two") || GL_CheckExtension("GL_OES_texture_npot"))
r_config.texture_non_power_of_two = true; gl_config.texture_non_power_of_two = true;
//gles2 has limited npot as standard, which is sufficient to make the hud not look like poo. lets use it.
if ((gl_config.gles && gl_config.glversion >= 2) || gl_config.texture_non_power_of_two)
gl_config.texture_non_power_of_two_limited = true;
// if (GL_CheckExtension("GL_SGIS_generate_mipmap")) //a suprising number of implementations have this broken. // if (GL_CheckExtension("GL_SGIS_generate_mipmap")) //a suprising number of implementations have this broken.
// gl_config.sgis_generate_mipmap = true; // gl_config.sgis_generate_mipmap = true;
@ -950,11 +950,25 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
qglBindVertexArray = NULL; qglBindVertexArray = NULL;
} }
if (gl_config.gles)
{ //gles has different TexImage2D arguments for specifying quality.
gl_config.arb_depth_texture = GL_CheckExtension("GL_OES_depth_texture"); //gles2
gl_config.arb_depth_texture |= GL_CheckExtension("GL_CHROMIUM_depth_texture"); //nacl
gl_config.arb_depth_texture |= GL_CheckExtension("GL_WEBGL_depth_texture"); //webgl. duh.
}
else
{
gl_config.arb_depth_texture = GL_CheckExtension("GL_ARB_depth_texture");
}
gl_config.arb_shadow = GL_CheckExtension("GL_ARB_shadow"); gl_config.arb_shadow = GL_CheckExtension("GL_ARB_shadow");
gl_config.arb_shadow |= GL_CheckExtension("GL_EXT_shadow_samplers"); //gles2 //gl_config.arb_shadow |= GL_CheckExtension("GL_EXT_shadow_samplers"); //gles2. nvidia fucks up. depend on brute-force. :s
#ifndef GL_STATIC #ifdef GL_STATIC
if (GL_CheckExtension("GL_ARB_framebuffer_object")) gl_config.ext_framebuffer_objects = true; //exists as core in gles2
#else
if ((gl_config.gles && gl_config.glversion >= 2) || //exists as core in gles2
(!gl_config.gles && gl_config.glversion >= 3) || //exists as core in gl3
GL_CheckExtension("GL_ARB_framebuffer_object")) //exists as an extension in gl2
{ {
gl_config.ext_framebuffer_objects = true; gl_config.ext_framebuffer_objects = true;
qglGenFramebuffersEXT = (void *)getglext("glGenFramebuffers"); qglGenFramebuffersEXT = (void *)getglext("glGenFramebuffers");
@ -2012,13 +2026,19 @@ void GL_Init(void *(*getglfunction) (char *name))
GL_CheckExtensions (getglfunction); GL_CheckExtensions (getglfunction);
if ((gl_config.gles && gl_config.glversion >= 3) || (!gl_config.gles && gl_config.glversion >= 2))
qglDrawBuffers = (void *)getglext("glDrawBuffers");
else
qglDrawBuffers = NULL;
if (gl_config.gles && gl_config.glversion >= 2) if (gl_config.gles && gl_config.glversion >= 2)
{ {
/*no matricies in gles, so don't try!*/ /*these functions do not exist in gles2, they only exist on some platforms because they were provided for gl1*/
qglLoadMatrixf = NULL; qglLoadMatrixf = NULL;
qglPolygonMode = NULL; qglPolygonMode = NULL;
qglShadeModel = NULL; qglShadeModel = NULL;
qglDepthRange = NULL; qglDepthRange = NULL;
qglDrawBuffer = NULL;
qglEnableClientState = GL_ClientStateStub; qglEnableClientState = GL_ClientStateStub;
qglDisableClientState = GL_ClientStateStub; qglDisableClientState = GL_ClientStateStub;
@ -2031,6 +2051,7 @@ void GL_Init(void *(*getglfunction) (char *name))
qglPolygonMode = NULL; qglPolygonMode = NULL;
qglShadeModel = NULL; qglShadeModel = NULL;
qglDepthRange = NULL; qglDepthRange = NULL;
qglDrawBuffer = NULL;
qglEnableClientState = GL_ClientStateStub; qglEnableClientState = GL_ClientStateStub;
qglDisableClientState = GL_ClientStateStub; qglDisableClientState = GL_ClientStateStub;
@ -2044,11 +2065,6 @@ void GL_Init(void *(*getglfunction) (char *name))
if (qglShadeModel) if (qglShadeModel)
qglShadeModel (GL_FLAT); qglShadeModel (GL_FLAT);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
#ifdef DEBUG #ifdef DEBUG
if (qglDebugMessageControlARB) if (qglDebugMessageControlARB)
qglDebugMessageControlARB(0, 0, 0, 0, NULL, true); qglDebugMessageControlARB(0, 0, 0, 0, NULL, true);

View file

@ -52,12 +52,6 @@ void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs);
qboolean BoundsIntersect (vec3_t mins1, vec3_t maxs1, vec3_t mins2, vec3_t maxs2); qboolean BoundsIntersect (vec3_t mins1, vec3_t maxs1, vec3_t mins2, vec3_t maxs2);
void ClearBounds (vec3_t mins, vec3_t maxs); void ClearBounds (vec3_t mins, vec3_t maxs);
//optional features common to all renderers, so I don't have to check to see which one it is all the time.
typedef struct {
qboolean texture_non_power_of_two;
} r_config_t;
extern r_config_t r_config;
#ifdef GLQUAKE #ifdef GLQUAKE
#if defined(ANDROID) /*FIXME: actually just to use standard GLES headers instead of full GL*/ #if defined(ANDROID) /*FIXME: actually just to use standard GLES headers instead of full GL*/
#if 1 #if 1
@ -218,10 +212,14 @@ typedef struct {
qboolean arb_texture_env_dot3; qboolean arb_texture_env_dot3;
qboolean arb_texture_cube_map; qboolean arb_texture_cube_map;
qboolean texture_non_power_of_two; //full npot support.
qboolean texture_non_power_of_two_limited; //mipless,clamped npot works, but generic npot doesn't.
qboolean arb_texture_compression; qboolean arb_texture_compression;
// qboolean arb_fragment_program; // qboolean arb_fragment_program;
qboolean arb_shader_objects; qboolean arb_shader_objects;
qboolean arb_shadow; qboolean arb_shadow;
qboolean arb_depth_texture;
qboolean ext_framebuffer_objects; qboolean ext_framebuffer_objects;
qboolean ext_stencil_wrap; qboolean ext_stencil_wrap;
qboolean ext_packed_depth_stencil; qboolean ext_packed_depth_stencil;
@ -731,6 +729,7 @@ extern void *(APIENTRY *qglMapBufferARB)(GLenum target, GLenum access);
extern GLboolean (APIENTRY *qglUnmapBufferARB)(GLenum target); extern GLboolean (APIENTRY *qglUnmapBufferARB)(GLenum target);
#endif #endif
extern void (APIENTRY *qglDrawBuffers)(GLsizei n, GLsizei *ids); //gl2
//non-gles2 gl functions //non-gles2 gl functions
extern void (APIENTRY *qglAccum) (GLenum op, GLfloat value); extern void (APIENTRY *qglAccum) (GLenum op, GLfloat value);

View file

@ -13,8 +13,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
//modifier: RIPPLEMAP (s_t3 contains a ripplemap //modifier: RIPPLEMAP (s_t3 contains a ripplemap
//modifier: TINT (some colour value) //modifier: TINT (some colour value)
"uniform float cvar_r_glsl_turbscale;\n"
"#ifndef FRESNEL\n" "#ifndef FRESNEL\n"
"#define FRESNEL 5.0\n" "#define FRESNEL 5.0\n"
"#endif\n" "#endif\n"
@ -49,6 +47,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"}\n" "}\n"
"#endif\n" "#endif\n"
"#ifdef FRAGMENT_SHADER\n" "#ifdef FRAGMENT_SHADER\n"
"uniform float cvar_r_glsl_turbscale;\n"
"uniform sampler2D s_t0; //refract\n" "uniform sampler2D s_t0; //refract\n"
"uniform sampler2D s_t1; //normalmap\n" "uniform sampler2D s_t1; //normalmap\n"
"uniform sampler2D s_t2; //diffuse/reflection\n" "uniform sampler2D s_t2; //diffuse/reflection\n"
@ -176,7 +175,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
//the bloom filter //the bloom filter
//filter out any texels which are not to bloom //filter out any texels which are not to bloom
"uniform vec3 cvar_r_bloom_filter;\n"
"varying vec2 tc;\n" "varying vec2 tc;\n"
"#ifdef VERTEX_SHADER\n" "#ifdef VERTEX_SHADER\n"
@ -188,6 +186,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"}\n" "}\n"
"#endif\n" "#endif\n"
"#ifdef FRAGMENT_SHADER\n" "#ifdef FRAGMENT_SHADER\n"
"uniform vec3 cvar_r_bloom_filter;\n"
"uniform sampler2D s_t0;\n" "uniform sampler2D s_t0;\n"
"void main ()\n" "void main ()\n"
"{\n" "{\n"
@ -199,7 +198,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef GLQUAKE #ifdef GLQUAKE
{QR_OPENGL, 110, "bloom_final", {QR_OPENGL, 110, "bloom_final",
"!!cvarf r_bloom\n" "!!cvarf r_bloom\n"
"uniform float cvar_r_bloom;\n"
//add them together //add them together
//optionally apply tonemapping //optionally apply tonemapping
@ -218,6 +216,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"uniform sampler2D s_t1;\n" "uniform sampler2D s_t1;\n"
"uniform sampler2D s_t2;\n" "uniform sampler2D s_t2;\n"
"uniform sampler2D s_t3;\n" "uniform sampler2D s_t3;\n"
"uniform float cvar_r_bloom;\n"
"void main ()\n" "void main ()\n"
"{\n" "{\n"
"gl_FragColor = \n" "gl_FragColor = \n"
@ -1695,6 +1694,11 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"!!cvardf r_glsl_pcf\n" "!!cvardf r_glsl_pcf\n"
"#ifndef USE_ARB_SHADOW\n"
//fall back on regular samplers if we must
"#define sampler2DShadow sampler2D\n"
"#endif\n"
//this is the main shader responsible for realtime dlights. //this is the main shader responsible for realtime dlights.
//texture units: //texture units:
@ -1706,7 +1710,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
//CUBESHADOW //CUBESHADOW
"#ifndef r_glsl_pcf\n" "#ifndef r_glsl_pcf\n"
"#error r_glsl_pcf wasn't defined\n" "#error r_glsl_pcf wasnt defined\n"
"#endif\n" "#endif\n"
"#if r_glsl_pcf < 1\n" "#if r_glsl_pcf < 1\n"
"#undef r_glsl_pcf\n" "#undef r_glsl_pcf\n"
@ -1728,12 +1732,15 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#if defined(SPECULAR) || defined(OFFSETMAPPING)\n" "#if defined(SPECULAR) || defined(OFFSETMAPPING)\n"
"varying vec3 eyevector;\n" "varying vec3 eyevector;\n"
"#endif\n" "#endif\n"
"#if defined(PCF) || defined(CUBE) || defined(SPOT)\n" "#if defined(PCF) || defined(CUBE) || defined(SPOT)\n"
"varying vec4 vtexprojcoord;\n" "varying vec4 vtexprojcoord;\n"
"#endif\n"
"#ifdef VERTEX_SHADER\n"
"#if defined(PCF) || defined(CUBE) || defined(SPOT)\n"
"uniform mat4 l_cubematrix;\n" "uniform mat4 l_cubematrix;\n"
"#endif\n" "#endif\n"
"#ifdef VERTEX_SHADER\n"
"#include \"sys/skeletal.h\"\n" "#include \"sys/skeletal.h\"\n"
"uniform vec3 l_lightposition;\n" "uniform vec3 l_lightposition;\n"
"attribute vec2 v_texcoord;\n" "attribute vec2 v_texcoord;\n"
@ -1872,7 +1879,13 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"return dot(mix(col.rgb, col.agb, fpart.x), vec3(1.0/9.0)); //blend r+a, gb are mixed because its pretty much free and gives a nicer dot instruction instead of lots of adds.\n" "return dot(mix(col.rgb, col.agb, fpart.x), vec3(1.0/9.0)); //blend r+a, gb are mixed because its pretty much free and gives a nicer dot instruction instead of lots of adds.\n"
"#else\n" "#else\n"
"#ifdef USE_ARB_SHADOW\n"
//with arb_shadow, we can benefit from hardware acclerated pcf, for smoother shadows
"#define dosamp(x,y) shadow2D(s_t4, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx)).r\n" "#define dosamp(x,y) shadow2D(s_t4, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx)).r\n"
"#else\n"
//this will probably be a bit blocky.
"#define dosamp(x,y) float(texture2D(s_t4, shadowcoord.xy + (vec2(x,y)*l_shadowmapscale.xy)).r >= shadowcoord.z)\n"
"#endif\n"
"float s = 0.0;\n" "float s = 0.0;\n"
"#if r_glsl_pcf >= 1 && r_glsl_pcf < 5\n" "#if r_glsl_pcf >= 1 && r_glsl_pcf < 5\n"
"s += dosamp(0.0, 0.0);\n" "s += dosamp(0.0, 0.0);\n"
@ -1973,6 +1986,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"gl_FragColor.rgb = fog3additive(diff*colorscale*l_lightcolour);\n" "gl_FragColor.rgb = fog3additive(diff*colorscale*l_lightcolour);\n"
"}\n" "}\n"
"#endif\n" "#endif\n"
}, },
#endif #endif
#ifdef D3D9QUAKE #ifdef D3D9QUAKE

View file

@ -638,11 +638,14 @@ typedef struct
extern sh_config_t sh_config; extern sh_config_t sh_config;
#ifdef GLSLONLY #ifdef GLSLONLY
#define gl_config_nofixedfunc true #define gl_config_nofixedfunc true
#define gl_config_gles true
#else #else
#define gl_config_nofixedfunc gl_config.nofixedfunc #define gl_config_nofixedfunc gl_config.nofixedfunc
#define gl_config_gles gl_config.gles #endif
#ifdef GLESONLY
#define gl_config_gles true
#else
#define gl_config_gles gl_config.gles
#endif #endif
#ifdef GLQUAKE #ifdef GLQUAKE

View file

@ -265,7 +265,7 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
glClearColor(1.0f, 0.0f, 0.0f, 1.0f); glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
GL_EndRendering(); GL_EndRendering();
GL_DoSwap(); GLVID_SwapBuffers();
// vid.pixelwidth = info->width; // vid.pixelwidth = info->width;
// vid.pixelheight = info->height; // vid.pixelheight = info->height;
@ -280,7 +280,7 @@ void GLVID_Shutdown (void)
glClearColor(1.0f, 0.0f, 0.0f, 1.0f); glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
GL_EndRendering(); GL_EndRendering();
GL_DoSwap(); GLVID_SwapBuffers();
ppb_core->ReleaseResource(glcontext); ppb_core->ReleaseResource(glcontext);
// glTerminatePPAPI(); // glTerminatePPAPI();

View file

@ -319,7 +319,7 @@ void startquake(char *manif)
args[parms.argc++] = manif; args[parms.argc++] = manif;
} }
Sys_Printf("Starting up\n"); Sys_Printf("Starting up (Built "__DATE__ ", " __TIME__")\n");
COM_InitArgv(parms.argc, parms.argv); COM_InitArgv(parms.argc, parms.argv);
TL_InitLanguages(); TL_InitLanguages();

View file

@ -2295,7 +2295,7 @@ int PDECL PR_LoadEnts(pubprogfuncs_t *ppf, const char *file, float killonspawnfl
} }
} }
else else
Sys_Error("Command %s not recognised", qcc_token); Sys_Error("Bad entity lump: '%s' not recognised (last ent was %i)", qcc_token, ed?ed->entnum:0);
} }
if (resethunk) if (resethunk)
{ {

View file

@ -891,7 +891,7 @@ void SV_SaveLevelCache(char *savedir, qboolean dontharmgame)
} }
#endif #endif
f = FS_OpenVFS (name, "wb", FS_GAMEONLY); f = FS_OpenVFS (name, "wbp", FS_GAMEONLY);
if (!f) if (!f)
{ {
Con_TPrintf ("ERROR: couldn't open %s.\n", name); Con_TPrintf ("ERROR: couldn't open %s.\n", name);

View file

@ -1325,7 +1325,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
#ifdef VM_Q1 #ifdef VM_Q1
if (svs.gametype != GT_Q1QVM) //we cannot do this with qvm if (svs.gametype != GT_Q1QVM) //we cannot do this with qvm
#endif #endif
svprogfuncs->SetStringField(svprogfuncs, ent, &ent->v->model, sv.world.worldmodel->name, true); svprogfuncs->SetStringField(svprogfuncs, ent, &ent->v->model, sv.strings.model_precache[1], true);
ent->v->modelindex = 1; // world model ent->v->modelindex = 1; // world model
ent->v->solid = SOLID_BSP; ent->v->solid = SOLID_BSP;
ent->v->movetype = MOVETYPE_PUSH; ent->v->movetype = MOVETYPE_PUSH;
@ -1400,6 +1400,8 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
// load and spawn all other entities // load and spawn all other entities
SCR_SetLoadingFile("entities"); SCR_SetLoadingFile("entities");
if (!deathmatch.value && !*skill.string) //skill was left blank so it doesn't polute serverinfo on deathmatch servers. in single player, we ensure that it gets a proper value.
Cvar_Set(&skill, "1");
if (progstype == PROG_H2) if (progstype == PROG_H2)
{ {
extern cvar_t coop; extern cvar_t coop;

View file

@ -6,8 +6,6 @@
//modifier: RIPPLEMAP (s_t3 contains a ripplemap //modifier: RIPPLEMAP (s_t3 contains a ripplemap
//modifier: TINT (some colour value) //modifier: TINT (some colour value)
uniform float cvar_r_glsl_turbscale;
#ifndef FRESNEL #ifndef FRESNEL
#define FRESNEL 5.0 #define FRESNEL 5.0
#endif #endif
@ -42,6 +40,7 @@ void main (void)
} }
#endif #endif
#ifdef FRAGMENT_SHADER #ifdef FRAGMENT_SHADER
uniform float cvar_r_glsl_turbscale;
uniform sampler2D s_t0; //refract uniform sampler2D s_t0; //refract
uniform sampler2D s_t1; //normalmap uniform sampler2D s_t1; //normalmap
uniform sampler2D s_t2; //diffuse/reflection uniform sampler2D s_t2; //diffuse/reflection

View file

@ -2,7 +2,6 @@
//the bloom filter //the bloom filter
//filter out any texels which are not to bloom //filter out any texels which are not to bloom
uniform vec3 cvar_r_bloom_filter;
varying vec2 tc; varying vec2 tc;
#ifdef VERTEX_SHADER #ifdef VERTEX_SHADER
@ -14,6 +13,7 @@ void main ()
} }
#endif #endif
#ifdef FRAGMENT_SHADER #ifdef FRAGMENT_SHADER
uniform vec3 cvar_r_bloom_filter;
uniform sampler2D s_t0; uniform sampler2D s_t0;
void main () void main ()
{ {

View file

@ -1,5 +1,4 @@
!!cvarf r_bloom !!cvarf r_bloom
uniform float cvar_r_bloom;
//add them together //add them together
//optionally apply tonemapping //optionally apply tonemapping
@ -18,6 +17,7 @@ uniform sampler2D s_t0;
uniform sampler2D s_t1; uniform sampler2D s_t1;
uniform sampler2D s_t2; uniform sampler2D s_t2;
uniform sampler2D s_t3; uniform sampler2D s_t3;
uniform float cvar_r_bloom;
void main () void main ()
{ {
gl_FragColor = gl_FragColor =

View file

@ -7,6 +7,11 @@
!!cvardf r_glsl_pcf !!cvardf r_glsl_pcf
#ifndef USE_ARB_SHADOW
//fall back on regular samplers if we must
#define sampler2DShadow sampler2D
#endif
//this is the main shader responsible for realtime dlights. //this is the main shader responsible for realtime dlights.
//texture units: //texture units:
@ -18,7 +23,7 @@
//CUBESHADOW //CUBESHADOW
#ifndef r_glsl_pcf #ifndef r_glsl_pcf
#error r_glsl_pcf wasn't defined #error r_glsl_pcf wasnt defined
#endif #endif
#if r_glsl_pcf < 1 #if r_glsl_pcf < 1
#undef r_glsl_pcf #undef r_glsl_pcf
@ -40,12 +45,15 @@ varying vec3 lightvector;
#if defined(SPECULAR) || defined(OFFSETMAPPING) #if defined(SPECULAR) || defined(OFFSETMAPPING)
varying vec3 eyevector; varying vec3 eyevector;
#endif #endif
#if defined(PCF) || defined(CUBE) || defined(SPOT) #if defined(PCF) || defined(CUBE) || defined(SPOT)
varying vec4 vtexprojcoord; varying vec4 vtexprojcoord;
#endif
#ifdef VERTEX_SHADER
#if defined(PCF) || defined(CUBE) || defined(SPOT)
uniform mat4 l_cubematrix; uniform mat4 l_cubematrix;
#endif #endif
#ifdef VERTEX_SHADER
#include "sys/skeletal.h" #include "sys/skeletal.h"
uniform vec3 l_lightposition; uniform vec3 l_lightposition;
attribute vec2 v_texcoord; attribute vec2 v_texcoord;
@ -184,7 +192,13 @@ float ShadowmapFilter(void)
return dot(mix(col.rgb, col.agb, fpart.x), vec3(1.0/9.0)); //blend r+a, gb are mixed because its pretty much free and gives a nicer dot instruction instead of lots of adds. return dot(mix(col.rgb, col.agb, fpart.x), vec3(1.0/9.0)); //blend r+a, gb are mixed because its pretty much free and gives a nicer dot instruction instead of lots of adds.
#else #else
#ifdef USE_ARB_SHADOW
//with arb_shadow, we can benefit from hardware acclerated pcf, for smoother shadows
#define dosamp(x,y) shadow2D(s_t4, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx)).r #define dosamp(x,y) shadow2D(s_t4, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx)).r
#else
//this will probably be a bit blocky.
#define dosamp(x,y) float(texture2D(s_t4, shadowcoord.xy + (vec2(x,y)*l_shadowmapscale.xy)).r >= shadowcoord.z)
#endif
float s = 0.0; float s = 0.0;
#if r_glsl_pcf >= 1 && r_glsl_pcf < 5 #if r_glsl_pcf >= 1 && r_glsl_pcf < 5
s += dosamp(0.0, 0.0); s += dosamp(0.0, 0.0);
@ -285,3 +299,4 @@ void main ()
gl_FragColor.rgb = fog3additive(diff*colorscale*l_lightcolour); gl_FragColor.rgb = fog3additive(diff*colorscale*l_lightcolour);
} }
#endif #endif

View file

@ -64,6 +64,15 @@ static qboolean QDECL VFSWEB_Close(vfsfile_t *file)
Z_Free(file); Z_Free(file);
return true; return true;
} }
static qboolean QDECL VFSWEB_ClosePersist(vfsfile_t *file)
{
vfswebfile_t *intfile = (vfswebfile_t*)file;
#ifdef _DEBUG
Con_DPrintf("Persisting file %s\n", file->dbgname);
#endif
emscriptenfte_buf_pushtolocalstore(intfile->handle);
return VFSWEB_Close(file);
}
vfsfile_t *FSWEB_OpenTemp(void) vfsfile_t *FSWEB_OpenTemp(void)
{ {
@ -99,11 +108,13 @@ vfsfile_t *VFSWEB_Open(const char *osname, const char *mode, qboolean *needsflus
vfswebfile_t *file; vfswebfile_t *file;
//qboolean read = !!strchr(mode, 'r'); //qboolean read = !!strchr(mode, 'r');
qboolean write = !!strchr(mode, 'w'); qboolean write = !!strchr(mode, 'w');
qboolean update = !!strchr(mode, '+');
qboolean append = !!strchr(mode, 'a'); qboolean append = !!strchr(mode, 'a');
qboolean persist = !!strchr(mode, 'p');
if (needsflush) if (needsflush)
*needsflush = false; *needsflush = false;
f = emscriptenfte_buf_open(osname, write||append); f = emscriptenfte_buf_open(osname, (write && !update)?2:(write||append));
if (f == -1) if (f == -1)
return NULL; return NULL;
@ -122,7 +133,10 @@ vfsfile_t *VFSWEB_Open(const char *osname, const char *mode, qboolean *needsflus
file->funcs.Seek = VFSWEB_Seek; file->funcs.Seek = VFSWEB_Seek;
file->funcs.Tell = VFSWEB_Tell; file->funcs.Tell = VFSWEB_Tell;
file->funcs.GetLen = VFSWEB_GetSize; file->funcs.GetLen = VFSWEB_GetSize;
file->funcs.Close = VFSWEB_Close; if (persist && (write || append))
file->funcs.Close = VFSWEB_ClosePersist;
else
file->funcs.Close = VFSWEB_Close;
file->funcs.Flush = VFSWEB_Flush; file->funcs.Flush = VFSWEB_Flush;
file->handle = f; file->handle = f;
@ -233,7 +247,7 @@ static void QDECL FSWEB_ReadFile(searchpathfuncs_t *handle, flocation_t *loc, ch
result = VFS_READ(f, buffer, loc->len); // do soemthing with result result = VFS_READ(f, buffer, loc->len); // do soemthing with result
if (result != loc->len) if (result != loc->len)
Con_Printf("FSWEB_ReadFile() fread: Filename: %s, expected %i, result was %u \n",loc->rawname,loc->len,(unsigned int)result); Con_Printf("FSWEB_ReadFile() fread: Filename: %s, expected %u, result was %u \n",loc->rawname,(unsigned int)loc->len,(unsigned int)result);
VFS_CLOSE(f); VFS_CLOSE(f);
} }

View file

@ -1,23 +1,25 @@
//emscripten's download mechanism lacks usable progress indicators.
void emscriptenfte_async_wget_data2(const char *url, void *ctx, void (*onload)(void*ctx,void*buf,int sz), void (*onerror)(void*ctx,int code), void (*onprogress)(void*ctx,int prog,int total)); void emscriptenfte_async_wget_data2(const char *url, void *ctx, void (*onload)(void*ctx,void*buf,int sz), void (*onerror)(void*ctx,int code), void (*onprogress)(void*ctx,int prog,int total));
//filesystem buffers are implemented in javascript so that we are not bound by power-of-two heap limitations quite so much. //filesystem buffers are implemented in javascript so that we are not bound by power-of-two heap limitations quite so much.
//also, we can't use emscripten's stdio because it reserves 16m file handles or something. //also, we can't use emscripten's stdio because it reserves 16m file handles or something.
//these buffers do not track file offsets nor file access permissions.
int emscriptenfte_buf_create(void); int emscriptenfte_buf_create(void);
int emscriptenfte_buf_open(const char *name, int createifneeded); int emscriptenfte_buf_open(const char *name, int createifneeded); //open
int emscriptenfte_buf_rename(const char *oldname, const char *newname); int emscriptenfte_buf_rename(const char *oldname, const char *newname); //rename files (if it was open, the handle now refers to the new file instead)
int emscriptenfte_buf_delete(const char *fname); int emscriptenfte_buf_delete(const char *fname); //delete the named file. there may be problems if its currently open
void emscriptenfte_buf_release(int handle); void emscriptenfte_buf_release(int handle); //close
unsigned int emscriptenfte_buf_getsize(int handle); void emscriptenfte_buf_pushtolocalstore(int handle); //make a copy in the browser's local storage, if possible.
int emscriptenfte_buf_read(int handle, int offset, void *data, int len); unsigned int emscriptenfte_buf_getsize(int handle); //get the size of the file buffer
int emscriptenfte_buf_write(int handle, int offset, const void *data, int len); int emscriptenfte_buf_read(int handle, int offset, void *data, int len);//read data
int emscriptenfte_buf_write(int handle, int offset, const void *data, int len);//write data. no access checks.
//websocket is implemented in javascript because there is no usable C api (emscripten's javascript implementation is shite). //websocket is implemented in javascript because there is no usable C api (emscripten's javascript implementation is shite and has fatal errors).
int emscriptenfte_ws_connect(const char *url); int emscriptenfte_ws_connect(const char *url); //open a websocket connect to a specific host
void emscriptenfte_ws_close(int sockid); void emscriptenfte_ws_close(int sockid); //close it again
int emscriptenfte_ws_cansend(int sockid, int extra, int maxpending); int emscriptenfte_ws_cansend(int sockid, int extra, int maxpending); //returns false if we're blocking for some reason. avoids overflowing. everything is otherwise reliable.
int emscriptenfte_ws_send(int sockid, const void *data, int len); int emscriptenfte_ws_send(int sockid, const void *data, int len); //send data to the peer. queues data. never dropped.
int emscriptenfte_ws_recv(int sockid, void *data, int len); int emscriptenfte_ws_recv(int sockid, void *data, int len); //receive data from the peer.
//misc stuff for printf replacements //misc stuff for printf replacements
void emscriptenfte_alert(const char *msg); void emscriptenfte_alert(const char *msg);
@ -33,6 +35,7 @@ int emscriptenfte_setupcanvas(
void(*Resized)(int newwidth, int newheight), void(*Resized)(int newwidth, int newheight),
void(*Mouse)(int devid,int abs,float x,float y,float z,float size), void(*Mouse)(int devid,int abs,float x,float y,float z,float size),
void(*Button)(int devid, int down, int mbutton), void(*Button)(int devid, int down, int mbutton),
int(*Keyboard)(int devid, int down, int keycode, int unicode) int(*Keyboard)(int devid, int down, int keycode, int unicode),
void(*Hash)(char *newhash)
); );

View file

@ -11,13 +11,14 @@ mergeInto(LibraryManager.library,
$FTEC: $FTEC:
{ {
linebuffer:'',
w: -1, w: -1,
h: -1, h: -1,
donecb:0, donecb:0,
evcb: { evcb: {
resize:0, resize:0,
mouse:0, mouse:0,
key:0, key:0
}, },
handleevent : function(event) handleevent : function(event)
@ -101,12 +102,13 @@ mergeInto(LibraryManager.library,
} }
}, },
emscriptenfte_setupcanvas__deps: ['$FTEC', '$Browser'], emscriptenfte_setupcanvas__deps: ['$FTEC', '$Browser'],
emscriptenfte_setupcanvas : function(nw,nh,evresz,evm,evb,evk) emscriptenfte_setupcanvas : function(nw,nh,evresz,evm,evb,evk,evh)
{ {
FTEC.evcb.resize = evresz; FTEC.evcb.resize = evresz;
FTEC.evcb.mouse = evm; FTEC.evcb.mouse = evm;
FTEC.evcb.button = evb; FTEC.evcb.button = evb;
FTEC.evcb.key = evk; FTEC.evcb.key = evk;
FTEC.evcb.hashchange = evh;
if (!FTEC.donecb) if (!FTEC.donecb)
{ {
FTEC.donecb = 1; FTEC.donecb = 1;
@ -128,21 +130,36 @@ mergeInto(LibraryManager.library,
var ctx = Browser.createContext(Module['canvas'], true, true); var ctx = Browser.createContext(Module['canvas'], true, true);
if (!ctx) if (!ctx)
return 0; return 0;
Browser.setCanvasSize(nw, nh, false); // Browser.setCanvasSize(nw, nh, false);
window.onresize = function() window.onresize = function()
{ {
//emscripten's browser library will revert sizes wrongly or something when we're fullscreen, so make sure that doesn't happen. //emscripten's browser library will revert sizes wrongly or something when we're fullscreen, so make sure that doesn't happen.
if (Browser.isFullScreen) // if (Browser.isFullScreen)
{ // {
Browser.windowedWidth = window.innerWidth; // Browser.windowedWidth = window.innerWidth;
Browser.windowedHeight = window.innerHeight; // Browser.windowedHeight = window.innerHeight;
} // }
else // else
Browser.setCanvasSize(window.innerWidth, window.innerHeight, false); Browser.setCanvasSize(window.innerWidth, window.innerHeight, false);
if (FTEC.evcb.resize != 0)
Runtime.dynCall('vii', FTEC.evcb.resize, [Module['canvas'].width, Module['canvas'].height]);
}; };
window.onresize(); window.onresize();
if (FTEC.evcb.hashchange)
window.onhashchange = function()
{
if (FTEC.evcb.hashchange != 0)
{
var val = location.hash;
var ptr = _malloc(val.length);
writeStringToMemory(val, ptr);
Runtime.dynCall('vi', FTEC.evcb.hashchange, [ptr]);
_free(ptr);
}
};
return 1; return 1;
}, },
@ -161,7 +178,15 @@ mergeInto(LibraryManager.library,
//FIXME: split+merge by \n //FIXME: split+merge by \n
emscriptenfte_print : function(msg) emscriptenfte_print : function(msg)
{ {
console.log(Pointer_stringify(msg)); FTEC.linebuffer += Pointer_stringify(msg);
for(;;)
{
nl = FTEC.linebuffer.indexOf("\n");
if (nl == -1)
break;
console.log(FTEC.linebuffer.substring(0, nl));
FTEC.linebuffer = FTEC.linebuffer.substring(nl+1);
}
}, },
emscriptenfte_ticks_ms : function() emscriptenfte_ticks_ms : function()
{ {
@ -192,7 +217,7 @@ mergeInto(LibraryManager.library,
b.h = _emscriptenfte_handle_alloc(b); b.h = _emscriptenfte_handle_alloc(b);
return b.h; return b.h;
}, },
//temp files //filesystem emulation
emscriptenfte_buf_open__deps : ['emscriptenfte_buf_create'], emscriptenfte_buf_open__deps : ['emscriptenfte_buf_create'],
emscriptenfte_buf_open : function(name, createifneeded) emscriptenfte_buf_open : function(name, createifneeded)
{ {
@ -201,6 +226,25 @@ mergeInto(LibraryManager.library,
var r = -1; var r = -1;
if (f == null) if (f == null)
{ {
if (window.localStorage && createifneeded != 2)
{
var str = window.localStorage.getItem(name);
if (str != null)
{
console.log('read file '+name+': ' + str);
var len = str.length;
var buf = new Uint8Array(len);
for (var i = 0; i < len; i++)
buf[i] = str.charCodeAt(i);
var b = {h:-1, r:2, l:len,m:len,d:buf, n:name};
r = b.h = _emscriptenfte_handle_alloc(b);
FTEH.f[name] = b;
return b.h;
}
}
if (createifneeded) if (createifneeded)
r = _emscriptenfte_buf_create(); r = _emscriptenfte_buf_create();
if (r != -1) if (r != -1)
@ -218,6 +262,8 @@ mergeInto(LibraryManager.library,
f.r+=1; f.r+=1;
r = f.h; r = f.h;
} }
if (f != null && createifneeded == 2)
f.l = 0; //truncate it.
return r; return r;
}, },
emscriptenfte_buf_rename : function(oldname, newname) emscriptenfte_buf_rename : function(oldname, newname)
@ -248,6 +294,30 @@ console.log('deleted '+name);
} }
return 0; return 0;
}, },
emscriptenfte_buf_pushtolocalstore : function(handle)
{
var b = FTEH.h[handle];
if (b == null)
{
Module.printError('emscriptenfte_buf_pushtolocalstore with invalid handle');
return;
}
if (b.n == null)
return;
var data = b.d;
var len = b.l;
if (window.localStorage)
{
var foo = "";
//use a divide and conquer implementation instead for speed?
for (var i = 0; i < len; i++)
foo += String.fromCharCode(data[i]);
window.localStorage.setItem(b.n, foo);
console.log('saved '+b.n+' persistantly: '+foo);
}
else
console.log('local storage not supported');
},
emscriptenfte_buf_release : function(handle) emscriptenfte_buf_release : function(handle)
{ {
var b = FTEH.h[handle]; var b = FTEH.h[handle];

View file

@ -35,7 +35,7 @@ static unsigned int domkeytoquake(unsigned int code)
/* 0*/ 0,0,0,0,0,0,0,0, K_BACKSPACE,K_TAB,0,0,0,K_ENTER,0,0, /* 0*/ 0,0,0,0,0,0,0,0, K_BACKSPACE,K_TAB,0,0,0,K_ENTER,0,0,
/* 16*/ K_SHIFT,K_CTRL,K_ALT,K_PAUSE,K_CAPSLOCK,0,0,0,0,0,0,K_ESCAPE,0,0,0,0, /* 16*/ K_SHIFT,K_CTRL,K_ALT,K_PAUSE,K_CAPSLOCK,0,0,0,0,0,0,K_ESCAPE,0,0,0,0,
/* 32*/ ' ',K_PGUP,K_PGDN,K_END,K_HOME,K_LEFTARROW,K_UPARROW,K_RIGHTARROW, K_DOWNARROW,0,0,0,K_PRINTSCREEN,K_INS,K_DEL,0, /* 32*/ ' ',K_PGUP,K_PGDN,K_END,K_HOME,K_LEFTARROW,K_UPARROW,K_RIGHTARROW, K_DOWNARROW,0,0,0,K_PRINTSCREEN,K_INS,K_DEL,0,
/* 48*/ '0','1','2','3','4','5','6','7', '8','9',0,0,0,0,0,0, /* 48*/ '0','1','2','3','4','5','6','7', '8','9',0,0,0,'=',0,0,
/* 64*/ 0,'a','b','c','d','e','f','g', 'h','i','j','k','l','m','n','o', /* 64*/ 0,'a','b','c','d','e','f','g', 'h','i','j','k','l','m','n','o',
/* 80*/ 'p','q','r','s','t','u','v','w', 'x','y','z',K_LWIN,K_RWIN,K_APP,0,0, /* 80*/ 'p','q','r','s','t','u','v','w', 'x','y','z',K_LWIN,K_RWIN,K_APP,0,0,
@ -43,7 +43,7 @@ static unsigned int domkeytoquake(unsigned int code)
/*112*/ K_F1,K_F2,K_F3,K_F4,K_F5,K_F6,K_F7,K_F8,K_F9,K_F10,K_F11,K_F12,0,0,0,0, /*112*/ K_F1,K_F2,K_F3,K_F4,K_F5,K_F6,K_F7,K_F8,K_F9,K_F10,K_F11,K_F12,0,0,0,0,
/*128*/ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /*128*/ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
/*144*/ K_KP_NUMLOCK,K_SCRLCK,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /*144*/ K_KP_NUMLOCK,K_SCRLCK,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
/*160*/ 0,0,0,'#',0,0,0,0, 0,0,0,0,0,0,0,0, /*160*/ 0,0,0,'#',0,0,0,0, 0,0,0,0,0,'-',0,0,
/*176*/ 0,0,0,0,0,0,0,0, 0,0,';','=',',','-','.','/', /*176*/ 0,0,0,0,0,0,0,0, 0,0,';','=',',','-','.','/',
/*192*/ '`',0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /*192*/ '`',0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
/*208*/ 0,0,0,0,0,0,0,0, 0,0,0,'[','\\',']','\'','`', /*208*/ 0,0,0,0,0,0,0,0, 0,0,0,'[','\\',']','\'','`',
@ -70,7 +70,7 @@ static unsigned int domkeytoshift(unsigned int code)
/* 0*/ 0,0,0,0,0,0,0,0, K_BACKSPACE,K_TAB,0,0,0,K_ENTER,0,0, /* 0*/ 0,0,0,0,0,0,0,0, K_BACKSPACE,K_TAB,0,0,0,K_ENTER,0,0,
/* 16*/ K_SHIFT,K_CTRL,K_ALT,K_PAUSE,K_CAPSLOCK,0,0,0,0,0,0,K_ESCAPE,0,0,0,0, /* 16*/ K_SHIFT,K_CTRL,K_ALT,K_PAUSE,K_CAPSLOCK,0,0,0,0,0,0,K_ESCAPE,0,0,0,0,
/* 32*/ ' ',K_PGUP,K_PGDN,K_END,K_HOME,K_LEFTARROW,K_UPARROW,K_RIGHTARROW, K_DOWNARROW,0,0,0,K_PRINTSCREEN,K_INS,K_DEL,0, /* 32*/ ' ',K_PGUP,K_PGDN,K_END,K_HOME,K_LEFTARROW,K_UPARROW,K_RIGHTARROW, K_DOWNARROW,0,0,0,K_PRINTSCREEN,K_INS,K_DEL,0,
/* 48*/ ')','!','\"',0/*£*/,'$','%','^','&', '*','(',0,0,0,0,0,0, /* 48*/ ')','!','\"',0/*£*/,'$','%','^','&', '*','(',0,0,0,'+',0,0,
/* 64*/ 0,'A','B','C','D','E','F','G', 'H','I','J','K','L','M','N','O', /* 64*/ 0,'A','B','C','D','E','F','G', 'H','I','J','K','L','M','N','O',
/* 80*/ 'P','Q','R','S','T','U','V','W', 'X','Y','Z',K_LWIN,K_RWIN,K_APP,0,0, /* 80*/ 'P','Q','R','S','T','U','V','W', 'X','Y','Z',K_LWIN,K_RWIN,K_APP,0,0,
@ -78,7 +78,7 @@ static unsigned int domkeytoshift(unsigned int code)
/*112*/ K_F1,K_F2,K_F3,K_F4,K_F5,K_F6,K_F7,K_F8,K_F9,K_F10,K_F11,K_F12,0,0,0,0, /*112*/ K_F1,K_F2,K_F3,K_F4,K_F5,K_F6,K_F7,K_F8,K_F9,K_F10,K_F11,K_F12,0,0,0,0,
/*128*/ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /*128*/ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
/*144*/ K_KP_NUMLOCK,K_SCRLCK,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /*144*/ K_KP_NUMLOCK,K_SCRLCK,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
/*160*/ 0,0,0,'~',0,0,0,0, 0,0,0,0,0,0,0,0, /*160*/ 0,0,0,'~',0,0,0,0, 0,0,0,0,0,'_',0,0,
/*176*/ 0,0,0,0,0,0,0,0, 0,0,':','+','<','_','>','?', /*176*/ 0,0,0,0,0,0,0,0, 0,0,':','+','<','_','>','?',
/*192*/ '`',0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /*192*/ '`',0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
/*208*/ 0,0,0,0,0,0,0,0, 0,0,0,'{','|','}','@','`', /*208*/ 0,0,0,0,0,0,0,0, 0,0,0,'{','|','}','@','`',
@ -151,7 +151,11 @@ static void DOM_ButtonEvent(int devid, int down, int button)
IN_KeyEvent(0, down, K_MOUSE1+button, 0); IN_KeyEvent(0, down, K_MOUSE1+button, 0);
} }
} }
void DOM_HashChanged(char *loc)
{
//try and open it. generally downloading it from the server.
Host_RunFile(loc+1, strlen(loc+1), NULL);
}
qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette) qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
{ {
int flags; int flags;
@ -164,7 +168,8 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
VID_Resized, VID_Resized,
IN_MouseMove, IN_MouseMove,
DOM_ButtonEvent, DOM_ButtonEvent,
DOM_KeyEvent DOM_KeyEvent,
DOM_HashChanged
)) ))
{ {
Con_Printf("Couldn't set up canvas\n"); Con_Printf("Couldn't set up canvas\n");
@ -177,6 +182,8 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
qglViewport (0, 0, vid.pixelwidth, vid.pixelheight); qglViewport (0, 0, vid.pixelwidth, vid.pixelheight);
VID_Resized(vid.pixelwidth, vid.pixelheight);
mouseactive = false; mouseactive = false;
return true; return true;
@ -186,7 +193,7 @@ void GLVID_DeInit (void)
{ {
ActiveApp = false; ActiveApp = false;
emscriptenfte_setupcanvas(-1, -1, NULL, NULL, NULL, NULL); emscriptenfte_setupcanvas(-1, -1, NULL, NULL, NULL, NULL, NULL);
} }

View file

@ -1,20 +1,18 @@
Module['preRun'] = function() Module['preRun'] = function()
{ {
//FS.createPath('/', 'id1', true, true);
//FS.createPath('/', 'qw', true, true);
//FS.createPath('/', 'fte', true, true);
//FS.createPath('/', 'tmp', true, true);
//FS.createPreloadedFile('/id1/', 'pak0.pak', '/pak0.pak', true, false);
//FS.createPreloadedFile('/id1/', 'pak1.pak', '/pak1.pak', true, false);
//FS.createPreloadedFile('/id1/', 'pak2.pak', '/pak2.pak', true, false);
//FS.createPreloadedFile('/id1/', 'pak3.pak', '/pak3.pak', true, false);
}; };
Module['arguments'] = ['-nohome', '-manifest', document.location + '.fmf']; {
// use query string in URL as command line Module['arguments'] = ['-nohome'];
if (!document.referrer) {
qstring = decodeURIComponent(window.location.search.substring(1)).split(" "); var man = window.location.protocol+'//'+window.location.host+window.location.pathname + '.fmf';
Module['arguments'] = Module['arguments'].concat(qstring); if (window.location.hash != "")
} man = window.location.hash.substring(1);
Module['arguments'] = Module['arguments'].concat(['-manifest', man]);
// use query string in URL as command line
if (!document.referrer) {
qstring = decodeURIComponent(window.location.search.substring(1)).split(" ");
Module['arguments'] = Module['arguments'].concat(qstring);
}
}