rework loading screen for legacy mods that don't have their own.

fix sound issue not reusing distant sounds (fixes massive cut-off sounds in xonotic).
fix crash issue with skeletal objects holding invalid model pointers over vid_restarts.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5163 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2017-11-05 13:15:08 +00:00
parent 39e124f72c
commit 1206244ebb
20 changed files with 1251 additions and 1065 deletions

View File

@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "glquake.h"//would prefer not to have this
#endif
#include "shader.h"
#include "gl_draw.h"
//name of the current backdrop for the loading screen
char levelshotname[MAX_QPATH];
@ -237,10 +238,15 @@ cvar_t show_gameclock_y = CVAR("cl_gameclock_y", "-1");
cvar_t show_speed = CVAR("show_speed", "0");
cvar_t show_speed_x = CVAR("show_speed_x", "-1");
cvar_t show_speed_y = CVAR("show_speed_y", "-9");
cvar_t scr_loadingrefresh = CVAR("scr_loadingrefresh", "0");
cvar_t scr_showloading = CVAR("scr_showloading", "1");
cvar_t scr_showobituaries = CVAR("scr_showobituaries", "0");
cvar_t scr_loadingrefresh = CVARD("scr_loadingrefresh", "0", "Force redrawing of the loading screen, in order to display EVERY resource that is loaded");
cvar_t scr_showloading = CVAR("scr_showloading", "1");
//things to configure the legacy loading screen
cvar_t scr_loadingscreen_picture = CVAR("scr_loadingscreen_picture", "gfx/loading");
cvar_t scr_loadingscreen_scale = CVAR("scr_loadingscreen_scale", "1");
cvar_t scr_loadingscreen_scale_limit = CVAR("scr_loadingscreen_scale_limit", "2");
void *scr_curcursor;
@ -261,6 +267,9 @@ void CLSCR_Init(void)
Cvar_Register(&con_stayhidden, cl_screengroup);
Cvar_Register(&scr_loadingrefresh, cl_screengroup);
Cvar_Register(&scr_showloading, cl_screengroup);
Cvar_Register(&scr_loadingscreen_picture, cl_screengroup);
Cvar_Register(&scr_loadingscreen_scale, cl_screengroup);
Cvar_Register(&scr_loadingscreen_scale_limit, cl_screengroup);
Cvar_Register(&show_fps, cl_screengroup);
Cvar_Register(&show_fps_x, cl_screengroup);
Cvar_Register(&show_fps_y, cl_screengroup);
@ -1645,6 +1654,9 @@ void SCR_DrawFPS (void)
switch (sfps)
{
case 1:
default:
break;
case 2: // lowest FPS, highest MS encountered
if (lastfps > 1/frametime)
{
@ -1856,8 +1868,6 @@ void SCR_DrawLoading (qboolean opaque)
int sizex, x, y, w, h;
mpic_t *pic;
char *s;
int qdepth;
int h2depth;
if (CSQC_UseGamecodeLoadingScreen())
return; //will be drawn as part of the regular screen updates
@ -1876,73 +1886,29 @@ void SCR_DrawLoading (qboolean opaque)
if (*levelshotname)
{
pic = R2D_SafeCachePic (levelshotname);
R_GetShaderSizes(pic, NULL, NULL, true);
R2D_ImageColours(1, 1, 1, 1);
R2D_ScalePic (0, 0, vid.width, vid.height, pic);
if (!R_GetShaderSizes(pic, &w, &h, true))
w = h = 1;
R2D_Letterbox(0, 0, vid.width, vid.height, pic, w, h);
}
else if (opaque)
{
R2D_ImageColours(0, 0, 0, 1);
R2D_FillBlock(0, 0, vid.width, vid.height);
R2D_ImageColours(1, 1, 1, 1);
R2D_ConsoleBackground (0, vid.height, true);
}
if (scr_showloading.ival)
{
qdepth = COM_FDepthFile("gfx/loading.lmp", true);
h2depth = COM_FDepthFile("gfx/menu/loading.lmp", true);
char *qname = scr_loadingscreen_picture.string;
if (qdepth < h2depth || h2depth > 0xffffff)
{ //quake files
#ifdef HEXEN2
int qdepth = COM_FDepthFile(qname, true);
int h2depth = COM_FDepthFile("gfx/menu/loading.lmp", true);
pic = R2D_SafeCachePic ("gfx/loading.lmp");
if (R_GetShaderSizes(pic, &w, &h, true))
{
x = (vid.width - w)/2;
y = (vid.height - 48 - h)/2;
R2D_ScalePic (x, y, w, h, pic);
x = (vid.width/2) - 96;
y += h + 8;
}
else
{
x = (vid.width/2) - 96;
y = (vid.height/2) - 8;
Draw_FunString((vid.width-7*8)/2, y-16, "Loading");
}
if (!total_loading_size)
total_loading_size = 1;
if (loading_stage > LS_CONNECTION)
{
sizex = current_loading_size * 192 / total_loading_size;
if (loading_stage == LS_SERVER)
{
R2D_ImageColours(1.0, 0.0, 0.0, 1.0);
R2D_FillBlock(x, y, sizex, 16);
R2D_ImageColours(0.0, 0.0, 0.0, 1.0);
R2D_FillBlock(x+sizex, y, 192-sizex, 16);
}
else
{
R2D_ImageColours(1.0, 1.0, 0.0, 1.0);
R2D_FillBlock(x, y, sizex, 16);
R2D_ImageColours(1.0, 0.0, 0.0, 1.0);
R2D_FillBlock(x+sizex, y, 192-sizex, 16);
}
R2D_ImageColours(1, 1, 1, 1);
Draw_FunString(x+8, y+4, va("Loading %s... %i%%",
(loading_stage == LS_SERVER) ? "server" : "client",
current_loading_size * 100 / total_loading_size));
}
y += 16;
if (loadingfile)
{
Draw_FunString(x+8, y+4, loadingfile);
y+=8;
}
}
else
{ //hexen2 files
if (!(qdepth < h2depth || h2depth > 0xffffff))
{ //hexen2 files.
//hexen2 has some fancy sliders built into its graphics in specific places. so this is messy.
pic = R2D_SafeCachePic ("gfx/menu/loading.lmp");
if (R_GetShaderSizes(pic, &w, &h, true))
{
@ -1987,6 +1953,88 @@ void SCR_DrawLoading (qboolean opaque)
y = 104;
}
}
else
#endif
{ //quake files
pic = R2D_SafeCachePic (qname);
if (R_GetShaderSizes(pic, &w, &h, true))
{
float f = 1;
w *= scr_loadingscreen_scale.value;
h *= scr_loadingscreen_scale.value;
switch(scr_loadingscreen_scale_limit.ival)
{
default:
break;
case 1:
f = max(w/vid.width,h/vid.height);
break;
case 2:
f = min(w/vid.width,h/vid.height);
break;
case 3:
f = w/vid.width;
break;
case 4:
f = h/vid.height;
break;
}
if (f > 1)
{
w /= f;
h /= f;
}
x = ((int)vid.width - w)/2;
y = ((int)vid.height - 48 - h)/2;
R2D_ScalePic (x, y, w, h, pic);
x = (vid.width/2) - 96;
y += h + 8;
//make sure our loading crap will be displayed.
if (y > vid.height-32)
y = vid.height-32;
}
else
{
x = (vid.width/2) - 96;
y = (vid.height/2) - 8;
Draw_FunString((vid.width-7*8)/2, y-16, "Loading");
}
if (!total_loading_size)
total_loading_size = 1;
if (loading_stage > LS_CONNECTION)
{
sizex = current_loading_size * 192 / total_loading_size;
if (loading_stage == LS_SERVER)
{
R2D_ImageColours(1.0, 0.0, 0.0, 1.0);
R2D_FillBlock(x, y, sizex, 16);
R2D_ImageColours(0.0, 0.0, 0.0, 1.0);
R2D_FillBlock(x+sizex, y, 192-sizex, 16);
}
else
{
R2D_ImageColours(1.0, 1.0, 0.0, 1.0);
R2D_FillBlock(x, y, sizex, 16);
R2D_ImageColours(1.0, 0.0, 0.0, 1.0);
R2D_FillBlock(x+sizex, y, 192-sizex, 16);
}
R2D_ImageColours(1, 1, 1, 1);
Draw_FunString(x+8, y+4, va("Loading %s... %i%%",
(loading_stage == LS_SERVER) ? "server" : "client",
current_loading_size * 100 / total_loading_size));
}
y += 16;
if (loadingfile)
{
Draw_FunString(x+8, y+4, loadingfile);
y+=16;
}
}
}
R2D_ImageColours(1, 1, 1, 1);
@ -2096,32 +2144,12 @@ void SCR_ImageName (const char *mapname)
return;
}
if (!scr_disabled_for_loading)
scr_drawloading = true;
if (qrenderer != QR_NONE)
{
scr_drawloading = true;
if (qrenderer != QR_NONE)
{
Sbar_Changed ();
SCR_UpdateScreen ();
}
scr_drawloading = false;
scr_disabled_for_loading = true;
Sbar_Changed ();
SCR_UpdateScreen ();
}
else
{
scr_disabled_for_loading = false;
scr_drawloading = true;
#ifdef GLQUAKE
if (qrenderer == QR_OPENGL)
{
SCR_DrawLoading(false);
SCR_SetUpToDrawConsole();
if (Key_Dest_Has(kdm_console) || !*levelshotname)
SCR_DrawConsole(!!*levelshotname);
}
#endif
}
scr_drawloading = false;
scr_disabled_time = Sys_DoubleTime(); //realtime tends to change... Hmmm....
scr_disabled_for_loading = true;

View File

@ -10,6 +10,7 @@
#include "../vk/vkrenderer.h"
#endif
#include "shader.h"
#include "gl_draw.h"
#if defined(HAVE_JUKEBOX)
#if defined(_WIN32) && !defined(WINRT) && !defined(NOMEDIAMENU)
@ -2569,7 +2570,7 @@ qboolean Media_ShowFilm(void)
else if (cin)
{
int cw, ch;
float ratiox, ratioy, aspect;
float aspect;
if (cin->cursormove)
cin->cursormove(cin, mousecursor_x/(float)vid.width, mousecursor_y/(float)vid.height);
if (cin->setsize)
@ -2584,40 +2585,7 @@ qboolean Media_ShowFilm(void)
ch = 3;
}
ratiox = (float)cw / vid.pixelwidth;
ratioy = (float)ch / vid.pixelheight;
if (!ch || !cw)
{
R2D_ImageColours(0, 0, 0, 1);
R2D_FillBlock(0, 0, vid.width, vid.height);
R2D_ScalePic(0, 0, 0, 0, videoshader);
}
else if (ratiox > ratioy)
{
int h = (vid.width * ch) / cw;
int p = vid.height - h;
//letterbox
R2D_ImageColours(0, 0, 0, 1);
R2D_FillBlock(0, 0, vid.width, p/2);
R2D_FillBlock(0, h + (p/2), vid.width, p/2);
R2D_ImageColours(1, 1, 1, 1);
R2D_ScalePic(0, p/2, vid.width, h, videoshader);
}
else
{
int w = (vid.height * cw) / ch;
int p = vid.width - w;
//sidethingies
R2D_ImageColours(0, 0, 0, 1);
R2D_FillBlock(0, 0, (p/2), vid.height);
R2D_FillBlock(w + (p/2), 0, p/2, vid.height);
R2D_ImageColours(1, 1, 1, 1);
R2D_ScalePic(p/2, 0, w, vid.height, videoshader);
}
R2D_Letterbox(0, 0, vid.pixelwidth, vid.pixelheight, videoshader, cw, ch);
SCR_SetUpToDrawConsole();
if (scr_con_current)
@ -4892,72 +4860,75 @@ sfxcache_t *QDECL S_MP3_Locate(sfx_t *sfx, sfxcache_t *buf, ssamplepos_t start,
extern cvar_t snd_linearresample_stream;
int framesz = (dec->srcwidth/8 * dec->srcchannels);
if (dec->dststart > start)
if (length)
{
/*I don't know where the compressed data is for each sample. acm doesn't have a seek. so reset to start, for music this should be the most common rewind anyway*/
dec->dststart = 0;
dec->dstcount = 0;
dec->srcoffset = 0;
}
if (dec->dstcount > snd_speed*6)
{
int trim = dec->dstcount - snd_speed; //retain a second of buffer in case we have multiple sound devices
if (dec->dststart + trim > start)
if (dec->dststart > start)
{
trim = start - dec->dststart;
if (trim < 0)
trim = 0;
}
// if (trim < 0)
// trim = 0;
/// if (trim > dec->dstcount)
// trim = dec->dstcount;
memmove(dec->dstdata, dec->dstdata + trim*framesz, (dec->dstcount - trim)*framesz);
dec->dststart += trim;
dec->dstcount -= trim;
}
while(start+length >= dec->dststart+dec->dstcount)
{
memset(&strhdr, 0, sizeof(strhdr));
strhdr.cbStruct = sizeof(strhdr);
strhdr.pbSrc = dec->srcdata + dec->srcoffset;
strhdr.cbSrcLength = dec->srclen - dec->srcoffset;
if (!strhdr.cbSrcLength)
break;
strhdr.pbDst = buffer;
strhdr.cbDstLength = sizeof(buffer);
qacmStreamPrepareHeader(dec->acm, &strhdr, 0);
qacmStreamConvert(dec->acm, &strhdr, ACM_STREAMCONVERTF_BLOCKALIGN);
qacmStreamUnprepareHeader(dec->acm, &strhdr, 0);
dec->srcoffset += strhdr.cbSrcLengthUsed;
if (!strhdr.cbDstLengthUsed)
{
if (strhdr.cbSrcLengthUsed)
continue;
break;
/*I don't know where the compressed data is for each sample. acm doesn't have a seek. so reset to start, for music this should be the most common rewind anyway*/
dec->dststart = 0;
dec->dstcount = 0;
dec->srcoffset = 0;
}
newlen = dec->dstcount + (strhdr.cbDstLengthUsed * ((float)snd_speed / dec->srcspeed))/framesz;
if (dec->dstbuffer < newlen+64)
if (dec->dstcount > snd_speed*6)
{
dec->dstbuffer = newlen+64 + snd_speed;
dec->dstdata = BZ_Realloc(dec->dstdata, dec->dstbuffer*framesz);
int trim = dec->dstcount - snd_speed; //retain a second of buffer in case we have multiple sound devices
if (dec->dststart + trim > start)
{
trim = start - dec->dststart;
if (trim < 0)
trim = 0;
}
// if (trim < 0)
// trim = 0;
/// if (trim > dec->dstcount)
// trim = dec->dstcount;
memmove(dec->dstdata, dec->dstdata + trim*framesz, (dec->dstcount - trim)*framesz);
dec->dststart += trim;
dec->dstcount -= trim;
}
SND_ResampleStream(strhdr.pbDst,
dec->srcspeed,
dec->srcwidth/8,
dec->srcchannels,
strhdr.cbDstLengthUsed / framesz,
dec->dstdata+dec->dstcount*framesz,
snd_speed,
dec->srcwidth/8,
dec->srcchannels,
snd_linearresample_stream.ival);
dec->dstcount = newlen;
while(start+length >= dec->dststart+dec->dstcount)
{
memset(&strhdr, 0, sizeof(strhdr));
strhdr.cbStruct = sizeof(strhdr);
strhdr.pbSrc = dec->srcdata + dec->srcoffset;
strhdr.cbSrcLength = dec->srclen - dec->srcoffset;
if (!strhdr.cbSrcLength)
break;
strhdr.pbDst = buffer;
strhdr.cbDstLength = sizeof(buffer);
qacmStreamPrepareHeader(dec->acm, &strhdr, 0);
qacmStreamConvert(dec->acm, &strhdr, ACM_STREAMCONVERTF_BLOCKALIGN);
qacmStreamUnprepareHeader(dec->acm, &strhdr, 0);
dec->srcoffset += strhdr.cbSrcLengthUsed;
if (!strhdr.cbDstLengthUsed)
{
if (strhdr.cbSrcLengthUsed)
continue;
break;
}
newlen = dec->dstcount + (strhdr.cbDstLengthUsed * ((float)snd_speed / dec->srcspeed))/framesz;
if (dec->dstbuffer < newlen+64)
{
dec->dstbuffer = newlen+64 + snd_speed;
dec->dstdata = BZ_Realloc(dec->dstdata, dec->dstbuffer*framesz);
}
SND_ResampleStream(strhdr.pbDst,
dec->srcspeed,
dec->srcwidth/8,
dec->srcchannels,
strhdr.cbDstLengthUsed / framesz,
dec->dstdata+dec->dstcount*framesz,
snd_speed,
dec->srcwidth/8,
dec->srcchannels,
snd_linearresample_stream.ival);
dec->dstcount = newlen;
}
}
buf->data = dec->dstdata;

View File

@ -2763,10 +2763,14 @@ void MP_Draw(void)
((float *)pr_globals)[OFS_PARM0+1] = vid.height;
((float *)pr_globals)[OFS_PARM0+2] = 0;
((float *)pr_globals)[OFS_PARM1+0] = vid.height; //dp compat, ish
if (mp_drawloading_function && (scr_drawloading||scr_disabled_for_loading))
{
((float *)pr_globals)[OFS_PARM1] = scr_disabled_for_loading;
PR_ExecuteProgram(menu_world.progs, mp_drawloading_function);
if (scr_drawloading||scr_disabled_for_loading)
{ //don't draw the menu if we're meant to be drawing a loading screen
//the menu should provide a special function if it wants to draw custom loading screens. this is for compat with old/dp/lazy/crappy menus.
if (mp_drawloading_function)
{
((float *)pr_globals)[OFS_PARM1] = scr_disabled_for_loading;
PR_ExecuteProgram(menu_world.progs, mp_drawloading_function);
}
}
else if (mp_draw_function)
PR_ExecuteProgram(menu_world.progs, mp_draw_function);

View File

@ -84,6 +84,7 @@ typedef struct skelobject_s
{
int inuse;
int modelindex; //for vid_restarts
model_t *model;
world_t *world; /*be it ssqc or csqc*/
skeltype_t type;
@ -990,6 +991,21 @@ void skel_info_f(void)
}
}
/*models were purged. reset any pointers to them*/
void skel_reload(void)
{
int i;
for (i = 0; i < countof(skelobjects); i++)
{
if (!skelobjects[i].model)
continue;
if (skelobjects[i].modelindex && skelobjects[i].world)
skelobjects[i].model = skelobjects[i].world->Get_CModel(skelobjects[i].world, skelobjects[i].modelindex);
else
skelobjects[i].model = NULL;
}
}
/*destroys all skeletons*/
void skel_reset(world_t *world)
{
@ -1069,6 +1085,7 @@ static skelobject_t *skel_create(world_t *world, int bonecount)
skelobjects[skelidx].world = world;
if (numskelobjectsused <= skelidx)
numskelobjectsused = skelidx + 1;
skelobjects[skelidx].modelindex = 0;
skelobjects[skelidx].model = NULL;
skelobjects[skelidx].inuse = 1;
return &skelobjects[skelidx];
@ -1444,6 +1461,7 @@ void rag_removedeltaent(lerpents_t *le)
if (skelobj)
{
skelobj->inuse = 2; //2 means don't reuse yet.
skelobj->modelindex = 0;
skelobj->model = NULL;
pendingkill = true;
}
@ -1466,6 +1484,7 @@ void rag_lerpdeltaent(lerpents_t *le, unsigned int bonecount, short *newstate, f
if (sko->numbones != bonecount)
{ //unusable, discard it and create a new one.
sko->inuse = 2; //2 means don't reuse yet.
sko->modelindex = 0;
sko->model = NULL;
pendingkill = true;
sko = NULL;
@ -1479,6 +1498,7 @@ void rag_lerpdeltaent(lerpents_t *le, unsigned int bonecount, short *newstate, f
sko = skel_create(&csqc_world, bonecount);
if (!sko)
return; //couldn't get one, ran out of memory or something?
sko->modelindex = 0;
sko->model = NULL;
sko->type = SKEL_RELATIVE;
le->skeletalobject = (sko - skelobjects) + 1;
@ -1541,6 +1561,7 @@ void rag_updatedeltaent(world_t *w, entity_t *ent, lerpents_t *le)
sko = skel_create(w, Mod_GetNumBones(mod, false));
if (!sko)
return; //couldn't get one, ran out of memory or something?
sko->modelindex = 0;
sko->model = mod;
sko->type = SKEL_RELATIVE;
le->skeletalobject = (sko - skelobjects) + 1;
@ -1563,6 +1584,7 @@ void rag_updatedeltaent(world_t *w, entity_t *ent, lerpents_t *le)
else if (sko->doll)
sko->numanimated = sko->doll->numdefaultanimated;
Mod_GetBoneRelations(mod, 0, skorel.numbones, &ent->framestate, skorel.bonematrix);
skorel.modelindex = sko->modelindex;
skorel.model = sko->model;
if (sko->numanimated || sko->doll != mod->dollinfo)
{
@ -1789,6 +1811,7 @@ void QCBUILTIN PF_skel_create (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
if (!skelobj)
return; //couldn't get one, ran out of memory or something?
skelobj->modelindex = midx;
skelobj->model = model;
skelobj->type = type;
@ -2271,6 +2294,7 @@ void QCBUILTIN PF_skel_delete (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
if (skelobj)
{
skelobj->inuse = 2; //2 means don't reuse yet.
skelobj->modelindex = 0;
skelobj->model = NULL;
pendingkill = true;
}

View File

@ -758,6 +758,45 @@ void R2D_SubPic(float x, float y, float width, float height, mpic_t *pic, float
R2D_Image(x, y, width, height, newsl, newtl, newsh, newth, pic);
}
void R2D_Letterbox(float sx, float sy, float sw, float sh, mpic_t *pic, float pw, float ph)
{
float ratiox = (float)pw / sw;
float ratioy = (float)ph / sh;
if (pw<=0 || ph<=0)
{ //no size info...
R2D_ImageColours(0, 0, 0, 1);
R2D_FillBlock(sx, sy, sw, sh);
R2D_ScalePic(sx, sy, 0, 0, pic); //in case its a videoshader with audio
}
else if (ratiox > ratioy)
{ //x ratio is greatest
float h = (sw * ph) / pw;
float p = sh - h;
//letterbox
R2D_ImageColours(0, 0, 0, 1);
R2D_FillBlock(sx, sy, sw, p/2);
R2D_FillBlock(sx, sy + h + (p/2), sw, p/2);
R2D_ImageColours(1, 1, 1, 1);
R2D_ScalePic(sx, sy + p/2, sw, h, pic);
}
else
{ //y ratio is greatest
float w = (sh * pw) / ph;
float p = sw - w;
//sidethingies
R2D_ImageColours(0, 0, 0, 1);
R2D_FillBlock(sx, sy, (p/2), sh);
R2D_FillBlock(sx + w + (p/2), sy, p/2, sh);
R2D_ImageColours(1, 1, 1, 1);
R2D_ScalePic(sx + p/2, sy, w, sh, pic);
}
}
/* this is an ugly special case drawing func that's only used for the player color selection menu */
void R2D_TransPicTranslate (float x, float y, int width, int height, qbyte *pic, unsigned int *palette)
{

View File

@ -1698,6 +1698,10 @@ TRACE(("dbg: R_ApplyRenderer: efrags\n"));
#endif
}
#ifdef SKELETALOBJECTS
skel_reload();
#endif
if (newr && qrenderer != QR_NONE)
{
if (!r_forceheadless || newr->renderer->rtype != QR_HEADLESS)

View File

@ -192,23 +192,23 @@ void S_PaintChannels(soundcardinfo_t *sc, int endtime)
//does it still make a sound if it cannot be heard?...
//technically no...
//this code is hacky.
if (!s->decoder.decodedata && s->decoder.buf)
{
if (s->decoder.decodedata)
scache = s->decoder.decodedata(s, &scachebuf, ch->pos>>PITCHSHIFT, 0); /*1 for luck - balances audio termination below*/
else
scache = s->decoder.buf;
ch->pos += (end-sc->paintedtime)*ch->rate;
if ((ch->pos>>PITCHSHIFT) > scache->length)
ch->pos += (end-sc->paintedtime)*ch->rate;
if (!scache || (ch->pos>>PITCHSHIFT) > scache->soundoffset+scache->length)
{
ch->pos = 0;
if (s->loopstart != -1)
ch->pos = s->loopstart<<PITCHSHIFT;
else if (!(ch->flags & CF_FORCELOOP))
{
ch->pos = 0;
if (s->loopstart != -1)
ch->pos = s->loopstart<<PITCHSHIFT;
else if (!(ch->flags & CF_FORCELOOP))
ch->sfx = NULL;
if (s->decoder.ended)
{
ch->sfx = NULL;
if (s->decoder.ended)
{
if (!S_IsPlayingSomewhere(s))
s->decoder.ended(s);
}
if (!S_IsPlayingSomewhere(s))
s->decoder.ended(s);
}
}
}

View File

@ -175,128 +175,131 @@ static sfxcache_t *QDECL OV_DecodeSome(struct sfx_s *sfx, struct sfxcache_s *buf
start *= 2*dec->srcchannels;
length *= 2*dec->srcchannels;
if (start < dec->decodedbytestart)
if (length)
{
// Con_Printf("Rewound to %i\n", start);
dec->failed = false;
if (start < dec->decodedbytestart)
{
// Con_Printf("Rewound to %i\n", start);
dec->failed = false;
//check pos
if (p_ov_pcm_seek(&dec->vf, start * (dec->srcspeed/(2.0*dec->srcchannels*outspeed))) == 0)
{
/*something rewound, purge clear the buffer*/
dec->decodedbytecount = 0;
dec->decodedbytestart = start;
}
}
/* if (start > dec->decodedbytestart + dec->decodedbytecount)
{
dec->decodedbytestart = start;
p_ov_pcm_seek(&dec->vf, (dec->decodedbytestart * dec->srcspeed) / outspeed);
}
*/
if (dec->decodedbytecount > outspeed*8)
{
/*everything is okay, but our buffer is getting needlessly large.
keep anything after the 'new' position, but discard all before that
trim shouldn't be able to go negative
*/
int trim = start - dec->decodedbytestart;
if (trim < 0)
{
dec->decodedbytecount = 0;
dec->decodedbytestart = start;
// Con_Printf("trim < 0\n");
}
else if (trim > dec->decodedbytecount)
{
if (0==p_ov_pcm_seek(&dec->vf, start * (dec->srcspeed/(2.0*dec->srcchannels*outspeed))))
//check pos
if (p_ov_pcm_seek(&dec->vf, start * (dec->srcspeed/(2.0*dec->srcchannels*outspeed))) == 0)
{
/*something rewound, purge clear the buffer*/
dec->decodedbytecount = 0;
dec->decodedbytestart = start;
}
// Con_Printf("trim > count\n");
}
else
{
// Con_Printf("trim retain\n");
//FIXME: retain an extra half-second for dual+ sound devices running slightly out of sync
memmove(dec->decodedbuffer, dec->decodedbuffer + trim, dec->decodedbytecount - trim);
dec->decodedbytecount -= trim;
dec->decodedbytestart += trim;
}
}
for (;;)
{
if (dec->failed || start+length <= dec->decodedbytestart + dec->decodedbytecount)
break;
if (dec->decodedbufferbytes < start+length - dec->decodedbytestart + 128) //expand if needed.
{
// Con_Printf("Expand buffer\n");
dec->decodedbufferbytes = (start+length - dec->decodedbytestart) + outspeed;
dec->decodedbuffer = BZ_Realloc(dec->decodedbuffer, dec->decodedbufferbytes);
}
if (outspeed == dec->srcspeed)
/* if (start > dec->decodedbytestart + dec->decodedbytecount)
{
bytesread = p_ov_read(&dec->vf, dec->decodedbuffer+dec->decodedbytecount, (start+length) - (dec->decodedbytestart+dec->decodedbytecount), bigendianp, 2, 1, &current_section);
if (bytesread <= 0)
dec->decodedbytestart = start;
p_ov_pcm_seek(&dec->vf, (dec->decodedbytestart * dec->srcspeed) / outspeed);
}
*/
if (dec->decodedbytecount > outspeed*8)
{
/*everything is okay, but our buffer is getting needlessly large.
keep anything after the 'new' position, but discard all before that
trim shouldn't be able to go negative
*/
int trim = start - dec->decodedbytestart;
if (trim < 0)
{
if (bytesread != 0) //0==eof
dec->decodedbytecount = 0;
dec->decodedbytestart = start;
// Con_Printf("trim < 0\n");
}
else if (trim > dec->decodedbytecount)
{
if (0==p_ov_pcm_seek(&dec->vf, start * (dec->srcspeed/(2.0*dec->srcchannels*outspeed))))
{
dec->failed = true;
Con_Printf("ogg decoding failed %i\n", bytesread);
dec->decodedbytecount = 0;
dec->decodedbytestart = start;
}
// Con_Printf("trim > count\n");
}
else
{
// Con_Printf("trim retain\n");
//FIXME: retain an extra half-second for dual+ sound devices running slightly out of sync
memmove(dec->decodedbuffer, dec->decodedbuffer + trim, dec->decodedbytecount - trim);
dec->decodedbytecount -= trim;
dec->decodedbytestart += trim;
}
}
for (;;)
{
if (dec->failed || start+length <= dec->decodedbytestart + dec->decodedbytecount)
break;
if (dec->decodedbufferbytes < start+length - dec->decodedbytestart + 128) //expand if needed.
{
// Con_Printf("Expand buffer\n");
dec->decodedbufferbytes = (start+length - dec->decodedbytestart) + outspeed;
dec->decodedbuffer = BZ_Realloc(dec->decodedbuffer, dec->decodedbufferbytes);
}
if (outspeed == dec->srcspeed)
{
bytesread = p_ov_read(&dec->vf, dec->decodedbuffer+dec->decodedbytecount, (start+length) - (dec->decodedbytestart+dec->decodedbytecount), bigendianp, 2, 1, &current_section);
if (bytesread <= 0)
{
if (bytesread != 0) //0==eof
{
dec->failed = true;
Con_Printf("ogg decoding failed %i\n", bytesread);
break;
}
if (start >= dec->decodedbytestart+dec->decodedbytecount)
return NULL; //let the mixer know that we hit the end
break;
}
if (start >= dec->decodedbytestart+dec->decodedbytecount)
return NULL; //let the mixer know that we hit the end
break;
}
}
else
{
double scale = dec->srcspeed / (double)outspeed;
int decodesize = ceil((dec->decodedbufferbytes-dec->decodedbytecount) * scale);
/*round down...*/
decodesize &= ~(2 * dec->srcchannels - 1);
if (decodesize > dec->tempbufferbytes)
else
{
dec->tempbuffer = BZ_Realloc(dec->tempbuffer, decodesize);
dec->tempbufferbytes = decodesize;
}
bytesread = p_ov_read(&dec->vf, dec->tempbuffer, decodesize, bigendianp, 2, 1, &current_section);
if (bytesread <= 0)
{
if (bytesread != 0) //0==eof
double scale = dec->srcspeed / (double)outspeed;
int decodesize = ceil((dec->decodedbufferbytes-dec->decodedbytecount) * scale);
/*round down...*/
decodesize &= ~(2 * dec->srcchannels - 1);
if (decodesize > dec->tempbufferbytes)
{
dec->failed = true;
Con_Printf("ogg decoding failed %i\n", bytesread);
return NULL;
dec->tempbuffer = BZ_Realloc(dec->tempbuffer, decodesize);
dec->tempbufferbytes = decodesize;
}
if (start >= dec->decodedbytestart+dec->decodedbytecount)
return NULL; //let the mixer know that we hit the end
break;
bytesread = p_ov_read(&dec->vf, dec->tempbuffer, decodesize, bigendianp, 2, 1, &current_section);
if (bytesread <= 0)
{
if (bytesread != 0) //0==eof
{
dec->failed = true;
Con_Printf("ogg decoding failed %i\n", bytesread);
return NULL;
}
if (start >= dec->decodedbytestart+dec->decodedbytecount)
return NULL; //let the mixer know that we hit the end
break;
}
SND_ResampleStream(dec->tempbuffer,
dec->srcspeed,
2,
dec->srcchannels,
bytesread / (2 * dec->srcchannels),
dec->decodedbuffer+dec->decodedbytecount,
outspeed,
2,
dec->srcchannels,
snd_linearresample_stream.ival);
bytesread = (int)floor(bytesread / scale) & ~(2 * dec->srcchannels - 1);
}
SND_ResampleStream(dec->tempbuffer,
dec->srcspeed,
2,
dec->srcchannels,
bytesread / (2 * dec->srcchannels),
dec->decodedbuffer+dec->decodedbytecount,
outspeed,
2,
dec->srcchannels,
snd_linearresample_stream.ival);
bytesread = (int)floor(bytesread / scale) & ~(2 * dec->srcchannels - 1);
dec->decodedbytecount += bytesread;
}
dec->decodedbytecount += bytesread;
}
if (buf)

View File

@ -274,6 +274,7 @@ void QCBUILTIN PF_setattachment(pubprogfuncs_t *prinst, struct globalvars_s *pr_
void skel_lookup(world_t *prinst, int skelidx, framestate_t *out);
void skel_dodelete(world_t *world);
void skel_reset(world_t *world);
void skel_reload(void);
#endif
void QCBUILTIN PF_physics_supported(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_physics_enable(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);

View File

@ -5531,6 +5531,9 @@ void GLBE_DrawLightPrePass(void)
*/
int oldfbo;
if (r_refdef.recurse)
return; //fixme: messy stuff...
/*do portals*/
BE_SelectMode(BEM_STANDARD);
GLBE_SubmitMeshes(cl.worldmodel->batches, SHADER_SORT_PORTAL, SHADER_SORT_PORTAL);
@ -5557,49 +5560,119 @@ void GLBE_DrawLightPrePass(void)
static const char *defualtfmts[countof(shaderstate.tex_gbuf)] =
//depth, normals, difflight, speclight
{"depth", "rgba16f", "rgba16f", "rgba8", "", "", "", ""};
checkglerror();
for (i = 0; i < countof(shaderstate.tex_gbuf); i++)
{
GLint ifmt = 0;
GLenum dfmt = GL_RGBA;
GLenum dtype = GL_UNSIGNED_BYTE;
var = Cvar_Get(va("gl_deferred_gbuffmt_%i", i), defualtfmts[i]?defualtfmts[i]:"", 0, "Deferred Rendering");
if (!var)
continue;
if (!strcmp(var->string, "rgba32f"))
ifmt = GL_RGBA32F_ARB;
{
if (gl_config_gles)
{ //gles3
ifmt = GL_RGBA32F_ARB;
dfmt = GL_RGBA;
dtype = GL_FLOAT;
}
else
ifmt = GL_RGBA32F_ARB;
}
else if (!strcmp(var->string, "rgba16f"))
ifmt = GL_RGBA16F_ARB;
{
if (gl_config_gles)
{ //gles3
ifmt = GL_RGBA16F_ARB;
dfmt = GL_RGBA;
dtype = GL_FLOAT;
}
else
ifmt = GL_RGBA16F_ARB;
}
// else if (!strcmp(var->string, "rgba8s"))
// ifmt = GL_RGBA8_SNORM;
else if (!strcmp(var->string, "depth"))
{
dtype = GL_UNSIGNED_INT;
ifmt = GL_DEPTH_COMPONENT;
dfmt = GL_DEPTH_COMPONENT;
}
else if (!strcmp(var->string, "depth16"))
{
ifmt = GL_DEPTH_COMPONENT16_ARB;
if (gl_config_gles)
{
dtype = GL_UNSIGNED_SHORT;
ifmt = GL_DEPTH_COMPONENT;
}
else
ifmt = GL_DEPTH_COMPONENT16_ARB;
dfmt = GL_DEPTH_COMPONENT;
}
else if (!strcmp(var->string, "depth24"))
{
ifmt = GL_DEPTH_COMPONENT24_ARB;
if (gl_config_gles)
{
dtype = GL_UNSIGNED_INT;
ifmt = GL_DEPTH_COMPONENT;
}
else
ifmt = GL_DEPTH_COMPONENT24_ARB;
dfmt = GL_DEPTH_COMPONENT;
}
else if (!strcmp(var->string, "depth32"))
{
ifmt = GL_DEPTH_COMPONENT32_ARB;
if (gl_config_gles)
{
dtype = GL_FLOAT;
ifmt = GL_DEPTH_COMPONENT;
}
else
ifmt = GL_DEPTH_COMPONENT32_ARB;
dfmt = GL_DEPTH_COMPONENT;
}
else if (!strcmp(var->string, "rgb565"))
{
dtype = GL_UNSIGNED_SHORT_5_6_5;
ifmt = GL_RGB;
dfmt = GL_RGB;
}
else if (!strcmp(var->string, "rgba4"))
{
dtype = GL_UNSIGNED_SHORT_4_4_4_4;
ifmt = GL_RGBA;
dfmt = GL_RGBA;
}
else if (!strcmp(var->string, "rgba5551"))
{
dtype = GL_UNSIGNED_SHORT_5_5_5_1;
ifmt = GL_RGBA;
dfmt = GL_RGBA;
}
else if (!strcmp(var->string, "rgba8") || *var->string)
ifmt = GL_RGBA8;
{
#ifndef GLESONLY
if (!gl_config_gles)
ifmt = GL_RGBA8;
else
#endif
ifmt = GL_RGBA;
dfmt = GL_RGBA;
}
else
continue;
shaderstate.tex_gbuf[i]->status = TEX_LOADED;
GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_gbuf[i]);
qglTexImage2D(GL_TEXTURE_2D, 0, ifmt, w, h, 0, dfmt, GL_UNSIGNED_BYTE, NULL);
qglTexImage2D(GL_TEXTURE_2D, 0, ifmt, w, h, 0, dfmt, dtype, NULL);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
if (qglGetError())
Con_Printf("unable to configure gbuffer image as '%s'\n", var->string);
}
}
@ -5660,7 +5733,7 @@ void GLBE_DrawLightPrePass(void)
/*final reconfigure - now drawing final surface data onto true framebuffer*/
GLBE_FBO_Pop(oldfbo);
if (!oldfbo)
if (!oldfbo && qglDrawBuffer)
qglDrawBuffer(GL_BACK);
/*now draw the postlight passes (this includes blended stuff which will NOT be lit)*/

View File

@ -33,6 +33,7 @@ void R2D_Image(float x, float y, float w, float h, float s1, float t1, float s2,
void R2D_Line(float x1, float y1, float x2, float y2, mpic_t *pic);
void R2D_ScalePic (float x, float y, float width, float height, mpic_t *pic);
void R2D_SubPic(float x, float y, float width, float height, mpic_t *pic, float srcx, float srcy, float srcwidth, float srcheight);
void R2D_Letterbox(float sx, float sy, float sw, float sh, mpic_t *pic, float pw, float ph);
void R2D_ConsoleBackground (int firstline, int lastline, qboolean forceopaque);
void R2D_EditorBackground (void);
void R2D_TileClear (float x, float y, float w, float h);

View File

@ -86,12 +86,12 @@ qboolean GLSCR_UpdateScreen (void)
}
else
{
scr_drawloading = true;
// scr_drawloading = true;
SCR_DrawLoading (true);
SCR_SetUpToDrawConsole();
if (Key_Dest_Has(kdm_console))
SCR_DrawConsole(false);
scr_drawloading = false;
// scr_drawloading = false;
if (R2D_Flush)
R2D_Flush();
VID_SwapBuffers();

View File

@ -1398,6 +1398,13 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
script = end;
}
else if (!strncmp(script, "!!", 2))
{
Con_DPrintf("Unknown directinve in glsl program %s\n", name);
script += 2;
while (*script == ' ' || *script == '\t')
script++;
}
else if (!strncmp(script, "//", 2))
{
script += 2;

View File

@ -575,7 +575,16 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
gl_config.maxglslversion = 0;
if (gl_config.gles && gl_config.glversion >= 2)
gl_config.maxglslversion = 100;
{
if (gl_config.glversion >= 3.2)
gl_config.maxglslversion = 320;
else if (gl_config.glversion >= 3.1)
gl_config.maxglslversion = 310;
else if (gl_config.glversion >= 3)
gl_config.maxglslversion = 300;
else
gl_config.maxglslversion = 100;
}
else if (gl_config.glversion >= 2)
{
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
@ -1899,16 +1908,28 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int
#endif
{
//known versions:
//<undefined> == gl
//100 == gles2
//110 == gl2.0
//120 == gl2.1
//130 == gl3.0
//140 == gl3.1
//150 [core|compatibility] == gl3.2
//330, 400, 410, 420, 430 [core|compatibility] == gl?.??
//300 ES == gles3
//310 ES == gles3.1
//330, 400, 410, 420, 430 [core|compatibility] == gl?.??
if (gl_config_gles)
{
if (ver <= 110) //gles2 is rougly gl2 so 100(es)==110ish
ver = 100;
else if (ver <= 330) //gles3 is rougly gl3.3 so 300es==330ish
ver = 300;
}
if (gl_config_gles && ver != 100)
Q_snprintfz(verline, sizeof(verline), "#version %u ES\n", ver);
Q_snprintfz(verline, sizeof(verline), "#version %u es\n", ver);
else if (!gl_config_gles && ver >= 150 && !gl_config_nofixedfunc)
//favour compatibility profile, simply because we want ftransform to work properly
//note that versions 130+140 are awkward due to deprecation stuff, both assume compatibility profiles where supported.
@ -2921,7 +2942,12 @@ qboolean GL_Init(rendererstate_t *info, void *(*getglfunction) (char *name))
vid.srgb = info->srgb && srgb;
sh_config.minver = 100;
sh_config.maxver = 100;
if (gl_config.glversion >= 3.1)
sh_config.maxver = 310;
else if (gl_config.glversion >= 3.0)
sh_config.maxver = 300;
else
sh_config.maxver = 100;
sh_config.blobpath = "gles/%s.blob";
sh_config.progpath = "glsl/%s.glsl";
sh_config.shadernamefmt = "%s_gles";

View File

@ -8338,6 +8338,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "lpp_depthnorm",
"!!ver 100 130\n"
"!!permu BUMP\n"
"!!permu SKELETAL\n"
"!!permu FRAMEBLEND\n"

View File

@ -284,7 +284,7 @@ static void SV_EmitDeltaEntIndex(sizebuf_t *msg, unsigned int entnum, qboolean r
void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber)
{
#ifdef PEXT_CSQC
qbyte messagebuffer[1024];
qbyte messagebuffer[MAX_DATAGRAM];
int en;
int currentsequence = client->netchan.outgoing_sequence;
globalvars_t *pr_globals;

View File

@ -61,7 +61,7 @@ cvar_t sv_gameplayfix_spawnbeforethinks = CVARD( "sv_gameplayfix_spawnbeforethin
#endif
cvar_t sv_sound_watersplash = CVAR( "sv_sound_watersplash", "misc/h2ohit1.wav");
cvar_t sv_sound_land = CVAR( "sv_sound_land", "demon/dland2.wav");
cvar_t sv_stepheight = CVARAFD("pm_stepheight", "", "sv_stepheight", CVAR_SERVERINFO, "If empty, the value 18 will be used instead. This is the size of the step you can step up or down.");
cvar_t sv_stepheight = CVARAFD("pm_stepheight", "", "sv_stepheight", CVAR_SERVERINFO, "If empty, the value "STRINGIFY(PM_DEFAULTSTEPHEIGHT)" will be used instead. This is the size of the step you can step up or down.");
cvar_t pm_ktjump = CVARF("pm_ktjump", "", CVAR_SERVERINFO);
cvar_t pm_bunnyspeedcap = CVARFD("pm_bunnyspeedcap", "", CVAR_SERVERINFO, "0 or 1, ish. If the player is traveling faster than this speed while turning, their velocity will be gracefully reduced to match their current maxspeed. You can still rocket-jump to gain high velocity, but turning will reduce your speed back to the max. This can be used to disable bunny hopping.");

View File

@ -1,3 +1,4 @@
!!ver 100 130
!!permu BUMP
!!permu SKELETAL
!!permu FRAMEBLEND

View File

@ -405,7 +405,7 @@ static qboolean VK_CreateSwapChain(void)
swapinfo.oldSwapchain = vk.swapchain;
swapinfo.clipped = vid_isfullscreen?VK_FALSE:VK_TRUE; //allow fragment shaders to be skipped on parts that are obscured by another window. screenshots might get weird, so use proper captures if required/automagic.
swapinfo.presentMode = VK_PRESENT_MODE_FIFO_KHR; //supposed to be guarenteed support.
swapinfo.presentMode = VK_PRESENT_MODE_FIFO_KHR; //support is guarenteed by spec, in theory.
for (i = 0, curpri = 0; i < presentmodes; i++)
{
uint32_t priority = 0;
@ -433,6 +433,9 @@ static qboolean VK_CreateSwapChain(void)
}
}
if (!vk.vsync && swapinfo.presentMode != VK_PRESENT_MODE_IMMEDIATE_KHR)
Con_Printf("Warning: vulkan graphics driver does not fully support disabling vsync.\n");
vk.srgbcapable = false;
swapinfo.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
swapinfo.imageFormat = (vid.srgb||vid_srgb.ival)?VK_FORMAT_B8G8R8A8_SRGB:VK_FORMAT_B8G8R8A8_UNORM;

File diff suppressed because it is too large Load Diff