try to fix sdl inputs.

fix some non-ascii encoding.
generate placeholder 8bit mipmaps for gles2/webgl in case anyone tries using 'vanilla' rendering.
revamping the downloads menu.
fix particles needing a specific blend mode in order to use custom shaders.
added trace_bone_id globals for qc. untested.
try to fix ragdoll crash. failing that, at least prevent it from being a crash.
try to fix d3d11 black lightmaps issue.
add r_norefresh to d3d9+d3d11
skin composing can now use subpics.
vulkan now tries to properly detect supported texture formats, instead of assuming.
vulkan now has a cvar to configure which dynamic buffers should be staged or shared.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5006 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2016-07-21 19:27:59 +00:00
parent 24cd9a1c21
commit 5eb21d1b6e
60 changed files with 864 additions and 423 deletions

View file

@ -2688,7 +2688,7 @@ void CLQ1_AddVisibleBBoxes(void)
for (i = 1; i < w->num_edicts; i++)
{
e = WEDICT_NUM(w->progs, i);
if (e->isfree)
if (ED_ISFREE(e))
continue;
if (r_showbboxes.ival & 4)

View file

@ -52,7 +52,7 @@ usercmd_t independantphysics[MAX_SPLITS];
vec3_t mousemovements[MAX_SPLITS];
/*kinda a hack...*/
int con_splitmodifier;
unsigned int con_splitmodifier;
cvar_t cl_forceseat = CVARAD("in_forceseat", "0", "in_forcesplitclient", "Overrides the device identifiers to control a specific client from any device. This can be used for debugging mods, where you only have one keyboard/mouse.");
extern cvar_t cl_splitscreen;
int CL_TargettedSplit(qboolean nowrap)

View file

@ -67,6 +67,7 @@ void RSpeedShow(void)
RSpNames[RSPEED_SUBMIT] = "submit/finish";
RSpNames[RSPEED_PRESENT] = "present";
RSpNames[RSPEED_ACQUIRE] = "acquire";
memset(RQntNames, 0, sizeof(RQntNames));
RQntNames[RQUANT_MSECS] = "Microseconds";
@ -294,7 +295,8 @@ CENTER PRINTING
typedef struct {
unsigned int flags;
conchar_t string[1024];
conchar_t *string;
size_t stringbytes;
char titleimage[MAX_QPATH];
unsigned int charcount;
float time_start; // for slow victory printing
@ -493,7 +495,20 @@ void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode)
}
}
p->charcount = COM_ParseFunString(CON_WHITEMASK, str, p->string, sizeof(p->string), false) - p->string;
for (;;)
{
p->charcount = COM_ParseFunString(CON_WHITEMASK, str, p->string, p->stringbytes, false) - p->string;
if ((p->charcount+1)*sizeof(*p->string) < p->stringbytes)
break;
else
{
p->stringbytes=p->stringbytes*2+sizeof(*p->string);
Z_Free(p->string);
p->string = Z_Malloc(p->stringbytes);
}
}
p->time_off = scr_centertime.value;
p->time_start = cl.time;
}
@ -514,7 +529,21 @@ void VARGS Stats_Message(char *msg, ...)
p->flags = CPRINT_OBITUARTY;
p->titleimage[0] = 0;
p->charcount = COM_ParseFunString(CON_WHITEMASK, str, p->string, sizeof(p->string), false) - p->string;
for (;;)
{
p->charcount = COM_ParseFunString(CON_WHITEMASK, str, p->string, p->stringbytes, false) - p->string;
if ((p->charcount+1)*sizeof(*p->string) < p->stringbytes)
break;
else
{
p->stringbytes=p->stringbytes*2+sizeof(*p->string);
Z_Free(p->string);
p->string = Z_Malloc(p->stringbytes);
}
}
p->time_off = scr_centertime.value;
p->time_start = cl.time;
}
@ -696,14 +725,17 @@ void R_DrawTextField(int x, int y, int w, int h, const char *text, unsigned int
{
cprint_t p;
vrect_t r;
conchar_t buffer[16384]; //FIXME: make dynamic.
p.string = buffer;
p.stringbytes = sizeof(buffer);
r.x = x;
r.y = y;
r.width = w;
r.height = h;
p.flags = fieldflags;
p.charcount = COM_ParseFunString(defaultmask, text, p.string, sizeof(p.string), false) - p.string;
p.charcount = COM_ParseFunString(defaultmask, text, p.string, p.stringbytes, false) - p.string;
p.time_off = scr_centertime.value;
p.time_start = cl.time;
*p.titleimage = 0;
@ -2963,6 +2995,12 @@ void SCR_DeInit (void)
}
key_customcursor[i].dirty = true;
}
for (i = 0; i < countof(scr_centerprint); i++)
{
Z_Free(scr_centerprint[i].string);
scr_centerprint[i].string = NULL;
scr_centerprint[i].stringbytes = 0;
}
if (scr_initialized)
{
scr_initialized = false;

View file

@ -1360,10 +1360,10 @@ void CSQC_Input_Frame(int lplayernum, usercmd_t *cmd);
void CSQC_WorldLoaded(void);
qboolean CSQC_ParseTempEntity(void);
qboolean CSQC_ConsoleCommand(char *cmd);
qboolean CSQC_KeyPress(int key, int unicode, qboolean down, int devid);
qboolean CSQC_MouseMove(float xdelta, float ydelta, int devid);
qboolean CSQC_MousePosition(float xabs, float yabs, int devid);
qboolean CSQC_JoystickAxis(int axis, float value, int devid);
qboolean CSQC_KeyPress(int key, int unicode, qboolean down, unsigned int devid);
qboolean CSQC_MouseMove(float xdelta, float ydelta, unsigned int devid);
qboolean CSQC_MousePosition(float xabs, float yabs, unsigned int devid);
qboolean CSQC_JoystickAxis(int axis, float value, unsigned int devid);
qboolean CSQC_Accelerometer(float x, float y, float z);
qboolean CSQC_Gyroscope(float x, float y, float z);
int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float vol, float attenuation, float pitchmod, float timeofs, unsigned int flags);

View file

@ -2790,12 +2790,12 @@ void Con_NotifyBox (char *text)
qboolean hadconsole;
// during startup for sound / cd warnings
Con_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n");
Con_Printf("\n\n^Ue01d^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01f\n");
Con_Printf ("%s", text);
Con_Printf ("Press a key.\n");
Con_Printf("\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n");
Con_Printf("^Ue01d^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01f\n");
key_count = -2; // wait for a key down and up
hadconsole = !!Key_Dest_Has(kdm_console);

View file

@ -2961,6 +2961,47 @@ static void Image_MipMap8888 (qbyte *in, int inwidth, int inheight, qbyte *out,
}
}
static qbyte Image_BlendPalette_2(qbyte a, qbyte b)
{
return a;
}
static qbyte Image_BlendPalette_4(qbyte a, qbyte b, qbyte c, qbyte d)
{
return a;
}
//this is expected to be slow, thanks to those two expensive helpers.
static void Image_MipMap8Pal (qbyte *in, int inwidth, int inheight, qbyte *out, int outwidth, int outheight)
{
int i, j;
qbyte *inrow;
int rowwidth = inwidth; //rowwidth is the byte width of the input
inrow = in;
//mips round down, except for when the input is 1. which bugs out.
if (inwidth <= 1 && inheight <= 1)
out[0] = in[0];
else if (inheight <= 1)
{
//single row, don't peek at the next
for (in = inrow, j=0 ; j<outwidth ; j++, out+=1, in+=2)
out[0] = Image_BlendPalette_2(in[0], in[1]);
}
else if (inwidth <= 1)
{
//single colum, peek only at this pixel
for (i=0 ; i<outheight ; i++, inrow+=rowwidth*2)
for (in = inrow, j=0 ; j<outwidth ; j++, out+=1, in+=2)
out[0] = Image_BlendPalette_2(in[0], in[rowwidth]);
}
else
{
for (i=0 ; i<outheight ; i++, inrow+=rowwidth*2)
for (in = inrow, j=0 ; j<outwidth ; j++, out+=1, in+=2)
out[0] = Image_BlendPalette_4(in[0], in[1], in[rowwidth+0], in[rowwidth+1]);
}
}
static void Image_GenerateMips(struct pendingtextureinfo *mips, unsigned int flags)
{
int mip;
@ -2974,6 +3015,25 @@ static void Image_GenerateMips(struct pendingtextureinfo *mips, unsigned int fla
switch(mips->encoding)
{
case PTI_R8:
if (sh_config.can_mipcap)
return; //if we can cap mips, do that. it'll save lots of expensive lookups and uglyness.
for (mip = mips->mipcount; mip < 32; mip++)
{
mips->mip[mip].width = mips->mip[mip-1].width >> 1;
mips->mip[mip].height = mips->mip[mip-1].height >> 1;
if (mips->mip[mip].width < 1 && mips->mip[mip].height < 1)
break;
if (mips->mip[mip].width < 1)
mips->mip[mip].width = 1;
if (mips->mip[mip].height < 1)
mips->mip[mip].height = 1;
mips->mip[mip].datasize = ((mips->mip[mip].width+3)&~3) * mips->mip[mip].height*4;
mips->mip[mip].data = BZ_Malloc(mips->mip[mip].datasize);
mips->mip[mip].needfree = true;
Image_MipMap8Pal(mips->mip[mip-1].data, mips->mip[mip-1].width, mips->mip[mip-1].height, mips->mip[mip].data, mips->mip[mip].width, mips->mip[mip].height);
mips->mipcount = mip+1;
}
return;
case PTI_RGBA8:
case PTI_RGBX8:

View file

@ -127,7 +127,7 @@ struct eventlist_s
IEV_MOUSEDELTA,
IEV_JOYAXIS
} type;
int devid;
unsigned int devid;
union
{
@ -171,7 +171,7 @@ struct mouse_s
M_MOUSE, //using deltas
M_TOUCH //using absolutes
} type;
int qdeviceid; //so we can just use pointers.
unsigned int qdeviceid; //so we can just use pointers.
vec2_t oldpos;
vec2_t downpos;
float moveddist; //how far it has moved while held. this provides us with our emulated mouse1 when they release the press
@ -187,7 +187,7 @@ int touchcursor; //the cursor follows whichever finger was most recently pressed
#define MAXJOYSTICKS 8
struct joy_s
{
int qdeviceid;
unsigned int qdeviceid;
float axis[MAXJOYAXIS];
} joy[MAXJOYSTICKS];
@ -220,11 +220,11 @@ struct remapctx
{
char *type;
char *devicename;
int newdevid;
unsigned int newdevid;
unsigned int found;
unsigned int failed;
};
static void IN_DeviceIDs_DoRemap(void *vctx, const char *type, const char *devicename, int *qdevid)
static void IN_DeviceIDs_DoRemap(void *vctx, const char *type, const char *devicename, unsigned int *qdevid)
{
struct remapctx *ctx = vctx;
@ -238,7 +238,7 @@ static void IN_DeviceIDs_DoRemap(void *vctx, const char *type, const char *devic
ctx->found++;
}
}
void IN_DeviceIDs_Enumerate(void *ctx, const char *type, const char *devicename, int *qdevid)
void IN_DeviceIDs_Enumerate(void *ctx, const char *type, const char *devicename, unsigned int *qdevid)
{
char buf[8192];
devicename = COM_QuotedString(devicename, buf, sizeof(buf), false);
@ -247,7 +247,7 @@ void IN_DeviceIDs_Enumerate(void *ctx, const char *type, const char *devicename,
else if (*qdevid == DEVID_UNSET)
Con_Printf("%s\t%s\t%s\n", type, "Unset", devicename);
else
Con_Printf("%s\t%i\t%s\n", type, *qdevid, devicename);
Con_Printf("%s\t%u\t%s\n", type, *qdevid, devicename);
}
void IN_DeviceIDs_f(void)
@ -259,7 +259,7 @@ void IN_DeviceIDs_f(void)
ctx.failed = false;
ctx.found = 0;
ctx.type = Cmd_Argv(1);
ctx.newdevid = atoi(Cmd_Argv(2));
ctx.newdevid = strtoul(Cmd_Argv(2), NULL, 0);
ctx.devicename = Cmd_Argv(3);
INS_EnumerateDevices(&ctx, IN_DeviceIDs_DoRemap);
@ -333,7 +333,7 @@ void IN_Init(void)
}
//tells the keys.c code whether the cursor is currently active, causing mouse clicks instead of binds.
qboolean IN_MouseDevIsTouch(int devid)
qboolean IN_MouseDevIsTouch(unsigned int devid)
{
if (devid < MAXPOINTERS)
return ptr[devid].type == M_TOUCH;
@ -343,7 +343,7 @@ qboolean IN_MouseDevIsTouch(int devid)
//translates MOUSE1 press events into begin-look-or-strafe events.
//translates to MOUSE2 accordingly
//returns 0 if it ate it completely.
int IN_TranslateMButtonPress(int devid)
int IN_TranslateMButtonPress(unsigned int devid)
{
int ret;
if (!ptr[devid].down)
@ -919,7 +919,7 @@ void IN_Move (float *movements, int pnum, float frametime)
IN_MoveJoystick(&joy[i], movements, pnum, frametime);
}
void IN_JoystickAxisEvent(int devid, int axis, float value)
void IN_JoystickAxisEvent(unsigned int devid, int axis, float value)
{
struct eventlist_s *ev = in_newevent();
if (!ev)
@ -931,7 +931,7 @@ void IN_JoystickAxisEvent(int devid, int axis, float value)
in_finishevent();
}
void IN_KeyEvent(int devid, int down, int keycode, int unicode)
void IN_KeyEvent(unsigned int devid, int down, int keycode, int unicode)
{
struct eventlist_s *ev = in_newevent();
if (!ev)
@ -949,7 +949,7 @@ for multitouch, devid might be the touch identifier, which will persist until re
x is horizontal, y is vertical.
z is height... generally its used as a mousewheel instead, but there are some '3d' mice out there, so its provided in this api.
*/
void IN_MouseMove(int devid, int abs, float x, float y, float z, float size)
void IN_MouseMove(unsigned int devid, int abs, float x, float y, float z, float size)
{
struct eventlist_s *ev = in_newevent();
if (!ev)

View file

@ -213,7 +213,7 @@ void INS_ProcessInputMessage(struct InputEvent *msg, qboolean consumemotion)
void INS_Commands(void)
{
}
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, int *qdevid))
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, unsigned int *qdevid))
{
}
void INS_Move (float *movements, int pnum)

View file

@ -520,7 +520,7 @@ static unsigned int tbl_sdltoquake[] =
0,0,
0, //SDLK_CLEAR = 12,
K_ENTER, //SDLK_RETURN = 13,
0,0,0,0,0,
0,0,0,0,0,
K_PAUSE, //SDLK_PAUSE = 19,
0,0,0,0,0,0,0,
K_ESCAPE, //SDLK_ESCAPE = 27,
@ -913,7 +913,7 @@ void INS_Accumulate(void) //input polling
void INS_Commands (void) //used to Cbuf_AddText joystick button events in windows.
{
}
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, int *qdevid))
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, unsigned int *qdevid))
{
}

View file

@ -2088,7 +2088,7 @@ void INS_JoyMove (float *movements, int pnum)
}
}
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, int *qdevid))
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, unsigned int *qdevid))
{
int idx;

View file

@ -29,8 +29,8 @@ void IN_Shutdown (void);
void IN_Commands (void);
// oportunity for devices to stick commands on the script buffer
qboolean IN_MouseDevIsTouch(int devid); //check if a mouse devid is a touch screen, and thus if we should check the cursor and simulate a ui event or not
int IN_TranslateMButtonPress(int devid); //allow the touchscreen code to swallow mouse1 as a begin-looking event
qboolean IN_MouseDevIsTouch(unsigned int devid); //check if a mouse devid is a touch screen, and thus if we should check the cursor and simulate a ui event or not
int IN_TranslateMButtonPress(unsigned int devid); //allow the touchscreen code to swallow mouse1 as a begin-looking event
void IN_Move (float *movements, int pnum, float frametime);
// add additional movement on top of the keyboard move cmd
@ -46,9 +46,9 @@ void IN_DeactivateMouse(void);
int CL_TargettedSplit(qboolean nowrap);
//specific events for the system-specific input code to call. may be called outside the main thread (so long as you don't call these simultaneously - ie: use a mutex or only one input thread).
void IN_KeyEvent(int devid, int down, int keycode, int unicode); //don't use IN_KeyEvent for mice if you ever use abs mice...
void IN_MouseMove(int devid, int abs, float x, float y, float z, float size);
void IN_JoystickAxisEvent(int devid, int axis, float value);
void IN_KeyEvent(unsigned int devid, int down, int keycode, int unicode); //don't use IN_KeyEvent for mice if you ever use abs mice...
void IN_MouseMove(unsigned int devid, int abs, float x, float y, float z, float size);
void IN_JoystickAxisEvent(unsigned int devid, int axis, float value);
//system-specific functions
void INS_Move (float *movements, int pnum);
@ -58,10 +58,10 @@ void INS_ReInit (void);
void INS_Init (void);
void INS_Shutdown (void);
void INS_Commands (void); //final chance to call IN_MouseMove/IN_KeyEvent each frame
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, int *qdevid));
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, unsigned int *qdevid));
void INS_SetupControllerAudioDevices(qboolean enabled); //creates audio devices for each controller (where controllers have their own audio devices)
#define DEVID_UNSET -1
#define DEVID_UNSET ~0u
extern cvar_t cl_nodelta;
extern cvar_t cl_c2spps;

View file

@ -2305,7 +2305,7 @@ Called by the system between frames for both key up and key down events
Should NOT be called during an interrupt!
===================
*/
void Key_Event (int devid, int key, unsigned int unicode, qboolean down)
void Key_Event (unsigned int devid, int key, unsigned int unicode, qboolean down)
{
int bl, bkey;
char *dc, *uc;

View file

@ -220,7 +220,7 @@ extern unsigned char *chat_buffer;
extern int chat_bufferpos;
extern qboolean chat_team;
void Key_Event (int devid, int key, unsigned int unicode, qboolean down);
void Key_Event (unsigned int devid, int key, unsigned int unicode, qboolean down);
void Key_Init (void);
void IN_WriteButtons(vfsfile_t *f, qboolean all);
void Key_WriteBindings (struct vfsfile_s *f);

View file

@ -444,7 +444,7 @@ static void M_CheckMouseMove(void)
{
if (menu->selecteditem != option)
{
if (!option->common.noselectionsound)
if (!option->common.noselectionsound && vid.activeapp)
{
#ifdef HEXEN2
if (M_GameType() == MGT_HEXEN2)

View file

@ -1026,7 +1026,7 @@ void M_Menu_Demos_f (void)
info->ext[info->numext++] = ".pak";
MC_AddWhiteText(menu, 24, 170, 8, "Choose a Demo", false);
MC_AddWhiteText(menu, 16, 170, 24, "\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37", false);
MC_AddWhiteText(menu, 16, 170, 24, "^Ue01d^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01f", false);
info->list = MC_AddCustom(menu, 0, 32, NULL, 0);
info->list->draw = M_DemoDraw;
@ -1081,7 +1081,7 @@ void M_Menu_MediaFiles_f (void)
#endif
MC_AddWhiteText(menu, 24, 170, 8, "Media List", false);
MC_AddWhiteText(menu, 16, 170, 24, "\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37", false);
MC_AddWhiteText(menu, 16, 170, 24, "^Ue01d^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01f", false);
info->list = MC_AddCustom(menu, 0, 32, NULL, 0);
info->list->draw = M_DemoDraw;

View file

@ -1197,10 +1197,6 @@ void M_Init_Internal (void)
Cmd_AddCommand ("menu_particles", M_Menu_Particles_f);
Cmd_AddCommand ("menu_network", M_Menu_Network_f);
#ifdef WEBCLIENT
Cmd_AddCommand ("menu_download", Menu_DownloadStuff_f);
#endif
#ifdef CL_MASTER
Cmd_AddCommand ("quickconnect", M_QuickConnect_f);
#endif
@ -1253,8 +1249,6 @@ void M_DeInit_Internal (void)
Cmd_RemoveCommand ("menu_textures");
Cmd_RemoveCommand ("menu_particles");
Cmd_RemoveCommand ("menu_download");
Cmd_RemoveCommand ("menu_main"); //I've moved main to last because that way tab gives us main and not quit.
Cmd_RemoveCommand ("quickconnect");
@ -1296,6 +1290,10 @@ void M_Init (void)
//server browser is kinda complex, and has clipboard integration which we need to sandbox a little
#ifdef CL_MASTER
Cmd_AddCommand ("menu_servers", M_Menu_ServerList2_f);
#endif
//downloads menu needs sandboxing, so cannot be provided by qc.
#ifdef WEBCLIENT
Cmd_AddCommand ("menu_download", Menu_DownloadStuff_f);
#endif
//demo menu is allowed to see outside of the quakedir. you can't replicate that in qc's sandbox.
Cmd_AddCommand ("menu_demo", M_Menu_Demos_f);

View file

@ -685,10 +685,24 @@ static void P_LoadTexture(part_type_t *ptype, qboolean warn)
for (i = 0; i < ptype->nummodels; i++)
ptype->models[i].model = NULL;
if (*ptype->texname && ptype->looks.blendmode == BM_BLEND)
if (*ptype->texname)
{
char *bmpostfix;
switch(ptype->looks.blendmode)
{ //we typically need the blendmode as part of the shader name, so that we don't end up with collisions with default shaders and different particle blend modes.
//shader blend modes still override, although I guess this way the shader itself can contain conditionals to use different blend modes... if needed.
default: bmpostfix = "#BLEND"; break;
case BM_BLEND: bmpostfix = ""; break;
case BM_BLENDCOLOUR:bmpostfix = "#BLENDCOLOUR"; break;
case BM_ADDA: bmpostfix = "#ADDA"; break;
case BM_ADDC: bmpostfix = "#ADDC"; break;
case BM_SUBTRACT: bmpostfix = "#SUBTRACT"; break;
case BM_INVMODA: bmpostfix = "#INVMODA"; break;
case BM_INVMODC: bmpostfix = "#INVMODC"; break;
case BM_PREMUL: bmpostfix = "#PREMUL"; break;
}
/*try and load the shader, fail if we would need to generate one*/
ptype->looks.shader = R_RegisterCustom(ptype->texname, SUF_NONE, NULL, NULL);
ptype->looks.shader = R_RegisterCustom(va("%s%s", ptype->texname, bmpostfix), SUF_NONE, NULL, NULL);
}
else
ptype->looks.shader = NULL;

View file

@ -154,13 +154,16 @@ extern sfx_t *cl_sfx_r_exp3;
globalvector(trace_plane_normal, "trace_plane_normal"); /*vector written by traceline*/ \
globalfloat(trace_plane_dist, "trace_plane_dist"); /*float written by traceline*/ \
globalentity(trace_ent, "trace_ent"); /*entity written by traceline*/ \
globalfloat(trace_surfaceflagsf, "trace_surfaceflags"); /*float written by traceline*/ \
globalint(trace_surfaceflagsi, "trace_surfaceflags"); /*int written by traceline*/ \
globalfloat(trace_surfaceflagsf, "trace_surfaceflagsf"); /*float written by traceline*/ \
globalint(trace_surfaceflagsi, "trace_surfaceflagsi"); /*int written by traceline*/ \
globalstring(trace_surfacename, "trace_surfacename"); /*string written by traceline*/ \
globalfloat(trace_endcontents, "trace_endcontents"); /*float written by traceline EXT_CSQC_1*/ \
globalfloat(trace_endcontentsf, "trace_endcontentsf"); /*float written by traceline EXT_CSQC_1*/ \
globalint(trace_endcontentsi, "trace_endcontentsi"); /*int written by traceline EXT_CSQC_1*/ \
globalint(trace_brush_id, "trace_brush_id"); /*int written by traceline*/ \
globalint(trace_brush_faceid, "trace_brush_faceid"); /*int written by traceline*/ \
globalint(trace_surface_id, "trace_surface_id"); /*int written by traceline*/ \
globalint(trace_bone_id, "trace_bone_id"); /*int written by traceline*/ \
globalint(trace_triangle_id, "trace_triangle_id"); /*int written by traceline*/ \
\
globalfloat(clientcommandframe, "clientcommandframe"); /*float the next frame that will be sent*/ \
globalfloat(servercommandframe, "servercommandframe"); /*float the most recent frame received from the server*/ \
@ -288,6 +291,7 @@ static void CSQC_ChangeLocalPlayer(int seat)
static void CSQC_FindGlobals(qboolean nofuncs)
{
static eval_t junk;
static float csphysicsmode = 0;
static float dimension_default = 255;
static vec3_t defaultgravity = {0, 0, -1};
@ -307,6 +311,50 @@ static void CSQC_FindGlobals(qboolean nofuncs)
#undef globalstring
#undef globalfunction
#define ensurefloat(name) if (!csqcg.name) csqcg.name = &junk._float;
#define ensureint(name) if (!csqcg.name) csqcg.name = &junk._int;
#define ensurevector(name) if (!csqcg.name) csqcg.name = junk._vector;
#define ensureentity(name) if (!csqcg.name) csqcg.name = &junk.edict;
if (!csqcg.trace_surfaceflagsf && !csqcg.trace_surfaceflagsi)
{
etype_t etype;
eval_t *v = PR_FindGlobal(csqcprogs, "trace_surfaceflags", 0, &etype);
if (etype == ev_float)
csqcg.trace_surfaceflagsf = &v->_float;
else if (etype == ev_integer)
csqcg.trace_surfaceflagsi = &v->_int;
}
if (!csqcg.trace_endcontentsf && !csqcg.trace_endcontentsi)
{
etype_t etype;
eval_t *v = PR_FindGlobal(csqcprogs, "trace_endcontents", 0, &etype);
if (etype == ev_float)
csqcg.trace_endcontentsf = &v->_float;
else if (etype == ev_integer)
csqcg.trace_endcontentsi = &v->_int;
}
ensurefloat(trace_allsolid);
ensurefloat(trace_startsolid);
ensurefloat(trace_fraction);
ensurefloat(trace_inwater);
ensurefloat(trace_inopen);
ensurevector(trace_endpos);
ensurevector(trace_plane_normal);
ensurefloat(trace_plane_dist);
ensurefloat(trace_surfaceflagsf);
ensureint(trace_surfaceflagsi);
ensurefloat(trace_endcontentsf);
ensureint(trace_endcontentsi);
ensureint(trace_brush_id);
ensureint(trace_brush_faceid);
ensureint(trace_surface_id);
ensureint(trace_bone_id);
ensureint(trace_triangle_id);
ensureentity(trace_ent);
if (csqcg.simtime)
*csqcg.simtime = cl.servertime;
if (csqcg.cltime)
@ -561,7 +609,7 @@ static void QCBUILTIN PF_cs_remove (pubprogfuncs_t *prinst, struct globalvars_s
ed = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0);
if (ed->isfree)
if (ED_ISFREE(ed))
{
csqc_deprecated("Tried removing free entity");
return;
@ -883,7 +931,7 @@ static void QCBUILTIN PF_R_AddEntity(pubprogfuncs_t *prinst, struct globalvars_s
{
csqcedict_t *in = (void*)G_EDICT(prinst, OFS_PARM0);
entity_t ent;
if (in->isfree || in->entnum == 0)
if (ED_ISFREE(in) || in->entnum == 0)
{
csqc_deprecated("Tried drawing a free/removed/world entity\n");
return;
@ -1158,19 +1206,19 @@ static void QCBUILTIN PF_R_AddEntityMask(pubprogfuncs_t *prinst, struct globalva
for (e=1; e < maxe; e++)
{
ent = (void*)EDICT_NUM(prinst, e);
if (ent->isfree)
if (ED_ISFREE(ent))
continue;
if (ent->v->think)
{
WPhys_RunThink (&csqc_world, (wedict_t*)ent);
if (ent->isfree)
if (ED_ISFREE(ent))
continue;
}
if (ent->xv->predraw)
{
*csqcg.self = EDICT_TO_PROG(prinst, (void*)ent);
PR_ExecuteProgram(prinst, ent->xv->predraw);
if (ent->isfree)
if (ED_ISFREE(ent))
continue; //bummer...
}
if ((int)ent->xv->drawmask & mask)
@ -1189,7 +1237,7 @@ static void QCBUILTIN PF_R_AddEntityMask(pubprogfuncs_t *prinst, struct globalva
for (e=1; e < maxe; e++)
{
ent = (void*)EDICT_NUM(prinst, e);
if (ent->isfree)
if (ED_ISFREE(ent))
continue;
if ((int)ent->xv->drawmask & mask)
@ -1199,7 +1247,7 @@ static void QCBUILTIN PF_R_AddEntityMask(pubprogfuncs_t *prinst, struct globalva
*csqcg.self = EDICT_TO_PROG(prinst, (void*)ent);
PR_ExecuteProgram(prinst, ent->xv->predraw);
if (ent->isfree || G_FLOAT(OFS_RETURN))
if (ED_ISFREE(ent) || G_FLOAT(OFS_RETURN))
continue; //bummer...
}
if (CopyCSQCEdictToEntity(ent, &rent))
@ -2225,7 +2273,7 @@ static void QCBUILTIN PF_cs_SetSize (pubprogfuncs_t *prinst, struct globalvars_s
float *min, *max;
e = G_WEDICT(prinst, OFS_PARM0);
if (e->isfree)
if (ED_ISFREE(e))
{
PR_RunWarning(prinst, "%s edict was free\n", "setsize");
return;
@ -2253,20 +2301,17 @@ static void cs_settracevars(pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
VectorCopy (tr->endpos, csqcg.trace_endpos);
VectorCopy (tr->plane.normal, csqcg.trace_plane_normal);
*csqcg.trace_plane_dist = tr->plane.dist;
if (csqcg.trace_surfaceflagsf)
*csqcg.trace_surfaceflagsf = tr->surface?tr->surface->flags:0;
if (csqcg.trace_surfaceflagsi)
*csqcg.trace_surfaceflagsi = tr->surface?tr->surface->flags:0;
*csqcg.trace_surfaceflagsf = tr->surface?tr->surface->flags:0;
*csqcg.trace_surfaceflagsi = tr->surface?tr->surface->flags:0;
if (csqcg.trace_surfacename)
prinst->SetStringField(prinst, NULL, csqcg.trace_surfacename, tr->surface?tr->surface->name:NULL, true);
if (csqcg.trace_endcontents)
*csqcg.trace_endcontents = tr->contents;
if (csqcg.trace_endcontentsi)
*csqcg.trace_endcontentsi = tr->contents;
if (csqcg.trace_brush_id)
*csqcg.trace_brush_id = tr->brush_id;
if (csqcg.trace_brush_faceid)
*csqcg.trace_brush_faceid = tr->brush_face;
*csqcg.trace_endcontentsf = tr->contents;
*csqcg.trace_endcontentsi = tr->contents;
*csqcg.trace_brush_id = tr->brush_id;
*csqcg.trace_brush_faceid = tr->brush_face;
*csqcg.trace_surface_id = tr->surface_id;
*csqcg.trace_bone_id = tr->bone_id;
*csqcg.trace_triangle_id = tr->triangle_id;
if (tr->ent)
*csqcg.trace_ent = EDICT_TO_PROG(csqcprogs, (void*)tr->ent);
else
@ -3693,7 +3738,7 @@ static void QCBUILTIN PF_cs_findchainflags (pubprogfuncs_t *prinst, struct globa
for (i = 1; i < *prinst->parms->sv_num_edicts; i++)
{
ent = (csqcedict_t*)EDICT_NUM(prinst, i);
if (ent->isfree)
if (ED_ISFREE(ent))
continue;
if (!((int)((float *)ent->v)[f] & s))
continue;
@ -3720,7 +3765,7 @@ static void QCBUILTIN PF_cs_findchainfloat (pubprogfuncs_t *prinst, struct globa
for (i = 1; i < *prinst->parms->sv_num_edicts; i++)
{
ent = (csqcedict_t*)EDICT_NUM(prinst, i);
if (ent->isfree)
if (ED_ISFREE(ent))
continue;
if (((float *)ent->v)[f] != s)
continue;
@ -3750,7 +3795,7 @@ static void QCBUILTIN PF_cs_findchain (pubprogfuncs_t *prinst, struct globalvars
for (i = 1; i < *prinst->parms->sv_num_edicts; i++)
{
ent = (csqcedict_t*)EDICT_NUM(prinst, i);
if (ent->isfree)
if (ED_ISFREE(ent))
continue;
t = *(string_t *)&((float*)ent->v)[f];
if (!t)
@ -7226,7 +7271,7 @@ qboolean CSQC_DrawView(void)
return true;
}
qboolean CSQC_KeyPress(int key, int unicode, qboolean down, int devid)
qboolean CSQC_KeyPress(int key, int unicode, qboolean down, unsigned int devid)
{
static qbyte csqckeysdown[K_MAX];
void *pr_globals;
@ -7269,7 +7314,7 @@ qboolean CSQC_KeyPress(int key, int unicode, qboolean down, int devid)
return G_FLOAT(OFS_RETURN);
}
qboolean CSQC_MousePosition(float xabs, float yabs, int devid)
qboolean CSQC_MousePosition(float xabs, float yabs, unsigned int devid)
{
void *pr_globals;
@ -7286,7 +7331,7 @@ qboolean CSQC_MousePosition(float xabs, float yabs, int devid)
return G_FLOAT(OFS_RETURN);
}
qboolean CSQC_MouseMove(float xdelta, float ydelta, int devid)
qboolean CSQC_MouseMove(float xdelta, float ydelta, unsigned int devid)
{
void *pr_globals;
@ -7304,7 +7349,7 @@ qboolean CSQC_MouseMove(float xdelta, float ydelta, int devid)
return G_FLOAT(OFS_RETURN);
}
qboolean CSQC_JoystickAxis(int axis, float value, int devid)
qboolean CSQC_JoystickAxis(int axis, float value, unsigned int devid)
{
void *pr_globals;
if (!csqcprogs || !csqcg.input_event)

View file

@ -671,17 +671,19 @@ void rag_freedoll(doll_t *doll)
BZ_Free(doll);
}
void rag_uninstanciateall(void)
{
int i;
for (i = 0; i < numskelobjectsused; i++)
{
rag_uninstanciate(&skelobjects[i]);
}
}
void rag_flushdolls(qboolean force)
{
doll_t *d, **link;
int i;
if (force)
{
for (i = 0; i < numskelobjectsused; i++)
{
rag_uninstanciate(&skelobjects[i]);
}
}
rag_uninstanciateall();
for (link = &dolllist; *link; )
{
d = *link;
@ -1089,6 +1091,12 @@ static void rag_uninstanciate(skelobject_t *sko)
if (!sko->doll)
return;
if (!sko->world || !sko->world->rbe)
{
sko->numbodies = sko->numjoints = 0;
Con_Printf(CON_ERROR "ERROR: Uninstanciating ragdoll from invalid world\n");
}
for (i = 0; i < sko->numbodies; i++)
{
sko->world->rbe->RagDestroyBody(sko->world, &sko->body[i].odebody);

View file

@ -291,7 +291,7 @@ extern qboolean noclip_anglehack;
extern quakeparms_t host_parms;
extern cvar_t fs_gamename;
extern cvar_t fs_gamemanifest;
extern cvar_t fs_downloads_url;
extern cvar_t com_protocolname;
extern cvar_t com_nogamedirnativecode;
extern cvar_t com_parseutf8;

View file

@ -49,12 +49,14 @@ static const texid_t r_nulltex = NULL;
#if sizeof_index_t == 2
#define GL_INDEX_TYPE GL_UNSIGNED_SHORT
#define D3DFMT_QINDEX D3DFMT_INDEX16
#define DXGI_FORMAT_INDEX_UINT DXGI_FORMAT_R16_UINT
#define VK_INDEX_TYPE VK_INDEX_TYPE_UINT16
typedef unsigned short index_t;
#define MAX_INDICIES 0xffffu
#else
#define GL_INDEX_TYPE GL_UNSIGNED_INT
#define D3DFMT_QINDEX D3DFMT_INDEX32
#define DXGI_FORMAT_INDEX_UINT DXGI_FORMAT_R32_UINT
#define VK_INDEX_TYPE VK_INDEX_TYPE_UINT32
typedef unsigned int index_t;
#define MAX_INDICIES 0x00ffffffu
@ -636,6 +638,7 @@ enum {
RSPEED_SETUP,
RSPEED_SUBMIT,
RSPEED_PRESENT,
RSPEED_ACQUIRE,
RSPEED_MAX
};

View file

@ -424,7 +424,8 @@ cvar_t vid_desktopgamma = CVARFD ("vid_desktopgamma", "0",
cvar_t r_fog_exp2 = CVARD ("r_fog_exp2", "1", "Expresses how fog fades with distance. 0 (matching DarkPlaces's default) is typically more realistic, while 1 (matching FitzQuake and others) is more common.");
#ifdef VKQUAKE
cvar_t vk_submissionthread = CVARD ("vk_submissionthread", "0", "Execute submits+presents on a thread dedicated to executing them. This may be a significant speedup on certain drivers.");
cvar_t vk_stagingbuffers = CVARD ("vk_stagingbuffers", "", "Configures which dynamic buffers are copied into gpu memory for rendering, instead of reading from shared memory. Empty for default settings.\nAccepted chars are u, e, v, 0.");
cvar_t vk_submissionthread = CVARD ("vk_submissionthread", "1", "Execute submits+presents on a thread dedicated to executing them. This may be a significant speedup on certain drivers.");
cvar_t vk_debug = CVARD ("vk_debug", "0", "Register a debug handler to display driver/layer messages. 2 enables the standard validation layers.");
#endif
@ -851,6 +852,7 @@ void Renderer_Init(void)
Cvar_Register (&r_forceprogramify, GLRENDEREROPTIONS);
#ifdef VKQUAKE
Cvar_Register (&vk_stagingbuffers, VKRENDEREROPTIONS);
Cvar_Register (&vk_submissionthread, VKRENDEREROPTIONS);
Cvar_Register (&vk_debug, VKRENDEREROPTIONS);
#endif
@ -1350,7 +1352,7 @@ TRACE(("dbg: R_ApplyRenderer: clearing world\n"));
ent = (wedict_t*)EDICT_NUM(svprogfuncs, i);
if (!ent)
continue;
if (ent->isfree)
if (ED_ISFREE(ent))
continue;
if (ent->area.prev)

View file

@ -88,7 +88,7 @@ void INS_Move(float *movements, int pnum)
void INS_Commands(void)
{
}
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, int *qdevid))
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, unsigned int *qdevid))
{
}
void INS_Init(void)

View file

@ -1908,7 +1908,7 @@ void R_DrawNameTags(void)
for (i = 1; i < w->num_edicts; i++)
{
e = WEDICT_NUM(w->progs, i);
if (e->isfree)
if (ED_ISFREE(e))
continue;
VectorInterpolate(e->v->mins, 0.5, e->v->maxs, org);
VectorAdd(org, e->v->origin, org);

View file

@ -2240,7 +2240,7 @@ void Cmd_ExecuteString (char *text, int level)
#ifndef SERVERONLY //an emergency escape mechansim, to avoid infinatly recursing aliases.
extern qboolean keydown[];
extern int con_splitmodifier;
extern unsigned int con_splitmodifier;
if (keydown[K_SHIFT] && (keydown[K_LCTRL]||keydown[K_RCTRL]) && (keydown[K_LALT]||keydown[K_RALT]))
return;
@ -3125,7 +3125,7 @@ void Cmd_set_f(void)
end--;
while (end >= text)
{
if (*end == ' ')
if (*end == ' ' || *end == '\t' || *end == '\r')
end--;
else
break;

View file

@ -2145,6 +2145,7 @@ qboolean Mod_Trace_Trisoup(vecV_t *posedata, index_t *indexes, int numindexes, v
}
VectorCopy(normal, trace->plane.normal);
trace->plane.dist = planedist;
trace->triangle_id = 1+i/3;
impacted = true;
// if (fabs(normal[0]) != 1 && fabs(normal[1]) != 1 && fabs(normal[2]) != 1)
@ -2243,8 +2244,26 @@ qboolean Mod_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3],
}
trace->truefraction = 1;
if (Mod_Trace_Trisoup(posedata, indexes, mod->numindexes, start_l, end_l, mins, maxs, trace) && axis)
if (Mod_Trace_Trisoup(posedata, indexes, mod->numindexes, start_l, end_l, mins, maxs, trace))
{
trace->surface_id = 1+surfnum;
trace->bone_id = 0;
if (mod->ofs_skel_weight)
{ //fixme: would be better to consider the distance to the vertex too. cartesian coord stuff etc.
unsigned int best = 0, v, w, i;
float bw = 0;
for (i = 0; i < 3; i++)
{
for (v = indexes[(trace->triangle_id-1)*3+i], w = 0; w < 4; w++)
{
if (bw < mod->ofs_skel_weight[v][w])
{
bw = mod->ofs_skel_weight[v][w];
trace->bone_id = 1 + mod->ofs_skel_idx[v][w];
}
}
}
}
if (axis)
{
vec3_t iaxis[3];
@ -2254,27 +2273,27 @@ qboolean Mod_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3],
trace->plane.normal[0] = DotProduct(norm, iaxis[0]);
trace->plane.normal[1] = DotProduct(norm, iaxis[1]);
trace->plane.normal[2] = DotProduct(norm, iaxis[2]);
}
// frac = traceinfo.truefraction;
/*
diststart = DotProduct(traceinfo.start, trace->plane.normal);
distend = DotProduct(traceinfo.end, trace->plane.normal);
if (diststart == distend)
frac = 0;
else
{
frac = (diststart - trace->plane.dist) / (diststart-distend);
if (frac < 0)
// frac = traceinfo.truefraction;
/*
diststart = DotProduct(traceinfo.start, trace->plane.normal);
distend = DotProduct(traceinfo.end, trace->plane.normal);
if (diststart == distend)
frac = 0;
else if (frac > 1)
frac = 1;
}*/
else
{
frac = (diststart - trace->plane.dist) / (diststart-distend);
if (frac < 0)
frac = 0;
else if (frac > 1)
frac = 1;
}*/
/*okay, this is where it hits this plane*/
trace->endpos[0] = start[0] + trace->fraction*(end[0] - start[0]);
trace->endpos[1] = start[1] + trace->fraction*(end[1] - start[1]);
trace->endpos[2] = start[2] + trace->fraction*(end[2] - start[2]);
/*okay, this is where it hits this plane*/
trace->endpos[0] = start[0] + trace->fraction*(end[0] - start[0]);
trace->endpos[1] = start[1] + trace->fraction*(end[1] - start[1]);
trace->endpos[2] = start[2] + trace->fraction*(end[2] - start[2]);
}
}
}

View file

@ -103,7 +103,7 @@ cvar_t gameversion = CVARFD("gameversion","", CVAR_SERVERINFO, "gamecode version
cvar_t gameversion_min = CVARD("gameversion_min","", "gamecode version for server browsers");
cvar_t gameversion_max = CVARD("gameversion_max","", "gamecode version for server browsers");
cvar_t fs_gamename = CVARAFD("com_fullgamename", NULL, "fs_gamename", CVAR_NOSET, "The filesystem is trying to run this game");
cvar_t fs_gamemanifest = CVARFD("fs_gamemanifest", "", CVAR_NOSET, "A small updatable file containing a description of the game, including download mirrors.");
cvar_t fs_downloads_url = CVARFD("fs_downloads_url", NULL, CVAR_NOSET, "The URL of a package updates list.");
cvar_t com_protocolname = CVARAD("com_protocolname", NULL, "com_gamename", "The protocol game name used for dpmaster queries. For compatibility with DP, you can set this to 'DarkPlaces-Quake' in order to be listed in DP's master server, and to list DP servers.");
cvar_t com_parseutf8 = CVARD("com_parseutf8", "1", "Interpret console messages/playernames/etc as UTF-8. Requires special fonts. -1=iso 8859-1. 0=quakeascii(chat uses high chars). 1=utf8, revert to ascii on decode errors. 2=utf8 ignoring errors"); //1 parse. 2 parse, but stop parsing that string if a char was malformed.
cvar_t com_parseezquake = CVARD("com_parseezquake", "0", "Treat chevron chars from configs as a per-character flag. You should use this only for compat with nquake's configs.");
@ -205,7 +205,12 @@ void QDECL Q_strncpyz(char *d, const char *s, int n)
//size is the total size of the buffer
void VARGS Q_vsnprintfz (char *dest, size_t size, const char *fmt, va_list argptr)
{
#ifdef _DEBUG
if ((size_t)vsnprintf (dest, size, fmt, argptr) > size-1)
Sys_Error("Q_vsnprintfz: truncation");
#else
vsnprintf (dest, size, fmt, argptr);
#endif
dest[size-1] = 0;
}
@ -1583,18 +1588,20 @@ char *MSG_ReadStringBuffer (char *out, size_t outsize)
}
char *MSG_ReadString (void)
{
static char string[8192];
static char string[65536];
int l,c;
l = 0;
do
for(;;)
{
c = MSG_ReadChar ();
if (msg_badread || c == 0)
break;
string[l] = c;
l++;
} while (l < sizeof(string)-1);
if (l < sizeof(string)-1)
string[l++] = c;
else
msg_badread = true;
}
string[l] = 0;

View file

@ -601,6 +601,7 @@ typedef struct
char *updatefile; //this is the file that needs to be written to update the manifest.
char *installation; //optional hardcoded commercial name, used for scanning the registry to find existing installs.
char *formalname; //the commercial name of the game. you'll get FULLENGINENAME otherwise.
char *downloadsurl; //optional installable files (menu)
char *protocolname; //the name used for purposes of dpmaster
char *defaultexec; //execed after cvars are reset, to give game-specific defaults.
char *eula; //when running as an installer, the user will be presented with this as a prompt

View file

@ -205,6 +205,7 @@ void FS_Manifest_Free(ftemanifest_t *man)
Z_Free(man->updatefile);
Z_Free(man->installation);
Z_Free(man->formalname);
Z_Free(man->downloadsurl);
Z_Free(man->protocolname);
Z_Free(man->eula);
Z_Free(man->defaultexec);
@ -235,6 +236,8 @@ static ftemanifest_t *FS_Manifest_Clone(ftemanifest_t *oldm)
newm->installation = Z_StrDup(oldm->installation);
if (oldm->formalname)
newm->formalname = Z_StrDup(oldm->formalname);
if (oldm->downloadsurl)
newm->downloadsurl = Z_StrDup(oldm->downloadsurl);
if (oldm->protocolname)
newm->protocolname = Z_StrDup(oldm->protocolname);
if (oldm->eula)
@ -277,6 +280,8 @@ void FS_Manifest_Print(ftemanifest_t *man)
Con_Printf("game %s\n", COM_QuotedString(man->installation, buffer, sizeof(buffer), false));
if (man->formalname)
Con_Printf("name %s\n", COM_QuotedString(man->formalname, buffer, sizeof(buffer), false));
if (man->downloadsurl)
Con_Printf("downloadsurl %s\n", COM_QuotedString(man->downloadsurl, buffer, sizeof(buffer), false));
if (man->protocolname)
Con_Printf("protocolname %s\n", COM_QuotedString(man->protocolname, buffer, sizeof(buffer), false));
if (man->defaultexec)
@ -501,6 +506,11 @@ static qboolean FS_Manifest_ParseTokens(ftemanifest_t *man)
Z_Free(man->eula);
man->eula = Z_StrDup(Cmd_Argv(1));
}
else if (!Q_strcasecmp(cmd, "downloadsurl"))
{
Z_Free(man->downloadsurl);
man->downloadsurl = Z_StrDup(Cmd_Argv(1));
}
else if (!Q_strcasecmp(cmd, "protocolname"))
{
Z_Free(man->protocolname);
@ -1705,6 +1715,26 @@ vfsfile_t *FS_OpenWithFriends(const char *fname, char *sysname, size_t sysnamesi
return NULL;
}
//returns false if the string didn't fit. we're not trying to be clever and reallocate the buffer
qboolean try_snprintf(char *buffer, size_t size, const char *format, ...)
{
size_t ret;
va_list argptr;
va_start (argptr, format);
#ifdef _WIN32
#undef _vsnprintf
ret = _vsnprintf(buffer, size, format, argptr);
#define _vsnprintf unsafe_vsnprintf
#else
ret = vsnprintf (buffer, size, format,argptr);
#endif
va_end (argptr);
if (ret > size-1) //should cope with microsoft's -1s and linuxes total-length return values.
return false;
return true;
}
/*locates and opens a file
modes:
r = read
@ -1747,7 +1777,8 @@ vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative r
case FS_GAMEONLY: //OS access only, no paks
if (com_homepathenabled)
{
snprintf(fullname, sizeof(fullname), "%s%s/%s", com_homepath, gamedirfile, filename);
if (!try_snprintf(fullname, sizeof(fullname), "%s%s/%s", com_homepath, gamedirfile, filename))
return NULL;
if (*mode == 'w')
COM_CreatePath(fullname);
vfs = VFSOS_Open(fullname, mode);
@ -1756,23 +1787,27 @@ vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative r
}
if (*gamedirfile)
{
snprintf(fullname, sizeof(fullname), "%s%s/%s", com_gamepath, gamedirfile, filename);
if (!try_snprintf(fullname, sizeof(fullname), "%s%s/%s", com_gamepath, gamedirfile, filename))
return NULL;
if (*mode == 'w')
COM_CreatePath(fullname);
return VFSOS_Open(fullname, mode);
}
return NULL;
case FS_PUBGAMEONLY:
FS_NativePath(filename, relativeto, fullname, sizeof(fullname));
if (!FS_NativePath(filename, relativeto, fullname, sizeof(fullname)))
return NULL;
if (*mode == 'w')
COM_CreatePath(fullname);
return VFSOS_Open(fullname, mode);
case FS_GAME: //load from paks in preference to system paths. overwriting be damned.
case FS_PUBBASEGAMEONLY: //load from paks in preference to system paths. overwriting be damned.
FS_NativePath(filename, relativeto, fullname, sizeof(fullname));
if (!FS_NativePath(filename, relativeto, fullname, sizeof(fullname)))
return NULL;
break;
case FS_BINARYPATH:
FS_NativePath(filename, relativeto, fullname, sizeof(fullname));
if (!FS_NativePath(filename, relativeto, fullname, sizeof(fullname)))
return NULL;
if (*mode == 'w')
COM_CreatePath(fullname);
return VFSOS_Open(fullname, mode);
@ -1781,22 +1816,26 @@ vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative r
return NULL;
if (com_homepathenabled)
{
snprintf(fullname, sizeof(fullname), "%s%s", com_homepath, filename);
if (!try_snprintf(fullname, sizeof(fullname), "%s%s", com_homepath, filename))
return NULL;
vfs = VFSOS_Open(fullname, mode);
if (vfs)
return vfs;
}
snprintf(fullname, sizeof(fullname), "%s%s", com_gamepath, filename);
if (!try_snprintf(fullname, sizeof(fullname), "%s%s", com_gamepath, filename))
return NULL;
return VFSOS_Open(fullname, mode);
case FS_BASEGAMEONLY: //always bypass packs+pure.
if (com_homepathenabled)
{
snprintf(fullname, sizeof(fullname), "%sfte/%s", com_homepath, filename);
if (!try_snprintf(fullname, sizeof(fullname), "%sfte/%s", com_homepath, filename))
return NULL;
vfs = VFSOS_Open(fullname, mode);
if (vfs)
return vfs;
}
snprintf(fullname, sizeof(fullname), "%sfte/%s", com_gamepath, filename);
if (!try_snprintf(fullname, sizeof(fullname), "%sfte/%s", com_gamepath, filename))
return NULL;
return VFSOS_Open(fullname, mode);
default:
Sys_Error("FS_OpenVFS: Bad relative path (%i)", relativeto);
@ -2855,6 +2894,7 @@ typedef struct {
const char *dir[4];
const char *poshname; //Full name for the game.
const char *downloadsurl;
const char *manifestfile;
} gamemode_info_t;
const gamemode_info_t gamemode_info[] = {
@ -2867,7 +2907,7 @@ const gamemode_info_t gamemode_info[] = {
//for quake, we also allow extracting all files from paks. some people think it loads faster that way or something.
//cmdline switch exename protocol name(dpmaster) identifying file exec dir1 dir2 dir3 dir(fte) full name
{"-quake", "q1", MASTER_PREFIX"Quake", {"id1/pak0.pak", "id1/quake.rc"},QCFG, {"id1", "qw", "*fte"}, "Quake"/*, "id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/},
{"-quake", "q1", MASTER_PREFIX"Quake", {"id1/pak0.pak", "id1/quake.rc"},QCFG, {"id1", "qw", "*fte"}, "Quake", "https://fte.triptohell.info/downloadables.txt" /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/},
//quake's mission packs should not be favoured over the base game nor autodetected
//third part mods also tend to depend upon the mission packs for their huds, even if they don't use any other content.
//and q2 also has a rogue/pak0.pak file that we don't want to find and cause quake2 to look like dissolution of eternity
@ -3795,14 +3835,14 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
return false;
}
#else
#ifdef __linux__
#if defined(__linux__) || defined(__unix__) || defined(__apple__)
#include <sys/stat.h>
#endif
qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *basepath, int basepathlen, qboolean allowprompts)
{
#ifdef __linux__
#if defined(__linux__) || defined(__unix__) || defined(__apple__)
struct stat sb;
if (!strcmp(gamename, "quake"))
if (!strcmp(gamename, "quake"))
{
if (stat("/usr/share/quake/", &sb) == 0)
{
@ -3859,6 +3899,7 @@ void FS_Shutdown(void)
fs_thread_mutex = NULL;
Cvar_SetEngineDefault(&fs_gamename, NULL);
Cvar_SetEngineDefault(&fs_downloads_url, NULL);
Cvar_SetEngineDefault(&com_protocolname, NULL);
}
@ -3930,7 +3971,8 @@ static int FS_IdentifyDefaultGameFromDir(char *basedir)
//3: if we are ftequake3.exe then we always try to run quake3.
//4: identify characteristic files within the working directory (like id1/pak0.pak implies we're running quake)
//5: check where the exe actually is instead of simply where we're being run from.
//6: fallback to prompting. just returns -1 here.
//6: try the homedir, just in case.
//7: fallback to prompting. just returns -1 here.
//if autobasedir is not set, block gamedir changes/prompts.
static int FS_IdentifyDefaultGame(char *newbase, int sizeof_newbase, qboolean fixedbase)
{
@ -3961,6 +4003,12 @@ static int FS_IdentifyDefaultGame(char *newbase, int sizeof_newbase, qboolean fi
if (gamenum != -1)
Q_strncpyz(newbase, host_parms.binarydir, sizeof_newbase);
}
if (gamenum == -1 && *com_homepath && !fixedbase)
{
gamenum = FS_IdentifyDefaultGameFromDir(com_homepath);
if (gamenum != -1)
Q_strncpyz(newbase, com_homepath, sizeof_newbase);
}
return gamenum;
}
@ -4828,6 +4876,11 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
}
}
if (!man->downloadsurl)
{
Cmd_TokenizeString(va("downloadsurl \"%s\"", gamemode_info[i].downloadsurl), false, false);
FS_Manifest_ParseTokens(man);
}
if (!man->protocolname)
{
Cmd_TokenizeString(va("protocolname \"%s\"", gamemode_info[i].protocolname), false, false);
@ -4954,9 +5007,11 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
if (reloadconfigs)
{
Cvar_SetEngineDefault(&fs_gamename, man->formalname?man->formalname:"FTE");
Cvar_SetEngineDefault(&fs_downloads_url, man->downloadsurl?man->downloadsurl:"");
Cvar_SetEngineDefault(&com_protocolname, man->protocolname?man->protocolname:"FTE");
//FIXME: flag this instead and do it after a delay?
Cvar_ForceSet(&fs_gamename, fs_gamename.enginevalue);
Cvar_ForceSet(&fs_downloads_url, fs_downloads_url.enginevalue);
Cvar_ForceSet(&com_protocolname, com_protocolname.enginevalue);
vidrestart = false;
@ -5398,7 +5453,7 @@ void COM_InitFilesystem (void)
Cvar_Register(&cfg_reload_on_gamedir, "Filesystem");
Cvar_Register(&com_fs_cache, "Filesystem");
Cvar_Register(&fs_gamename, "Filesystem");
Cvar_Register(&fs_gamemanifest, "Filesystem");
Cvar_Register(&fs_downloads_url, "Filesystem");
Cvar_Register(&com_protocolname, "Server Info");
Cvar_Register(&fs_game, "Filesystem");
#ifdef Q2SERVER

View file

@ -1205,7 +1205,7 @@ void QCBUILTIN PF_FindFlags (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
for (e++; e < *prinst->parms->sv_num_edicts; e++)
{
ed = WEDICT_NUM(prinst, e);
if (ed->isfree)
if (ED_ISFREE(ed))
continue;
if ((int)((float *)ed->v)[f] & s)
{
@ -1237,7 +1237,7 @@ void QCBUILTIN PF_FindFloat (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
for (e++; e < *prinst->parms->sv_num_edicts; e++)
{
ed = WEDICT_NUM(prinst, e);
if (ed->isfree)
if (ED_ISFREE(ed))
continue;
if (((int *)ed->v)[f] == s)
{
@ -1270,7 +1270,7 @@ void QCBUILTIN PF_FindString (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
for (e++ ; e < *prinst->parms->sv_num_edicts ; e++)
{
ed = WEDICT_NUM(prinst, e);
if (ed->isfree)
if (ED_ISFREE(ed))
continue;
t = ((string_t *)ed->v)[f];
if (!t)
@ -2616,7 +2616,7 @@ void QCBUILTIN PF_WasFreed (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
{
wedict_t *ent;
ent = G_WEDICT(prinst, OFS_PARM0);
G_FLOAT(OFS_RETURN) = ent->isfree;
G_FLOAT(OFS_RETURN) = ED_ISFREE(ent);
}
void QCBUILTIN PF_num_for_edict (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -2666,7 +2666,7 @@ void QCBUILTIN PF_findradius (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
for (i=1 ; i<w->num_edicts ; i++)
{
ent = WEDICT_NUM(prinst, i);
if (ent->isfree)
if (ED_ISFREE(ent))
continue;
if (ent->v->solid == SOLID_NOT && (!((int)ent->v->flags & FL_FINDABLE_NONSOLID)) && !sv_gameplayfix_blowupfallenzombies.value)
continue;
@ -2698,7 +2698,7 @@ void QCBUILTIN PF_nextent (pubprogfuncs_t *prinst, struct globalvars_s *pr_globa
return;
}
ent = WEDICT_NUM(prinst, i);
if (!ent->isfree)
if (!ED_ISFREE(ent))
{
RETURN_EDICT(prinst, ent);
return;
@ -2740,9 +2740,9 @@ void QCBUILTIN PF_copyentity (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
else
out = G_WEDICT(prinst, OFS_PARM1);
if (in->isfree)
if (ED_ISFREE(in))
PR_BIError(prinst, "PF_copyentity: source is free");
if (!out || out->isfree)
if (!out || ED_ISFREE(out))
PR_BIError(prinst, "PF_copyentity: destination is free");
if (out->readonly)
PR_BIError(prinst, "PF_copyentity: destination is read-only");
@ -2760,7 +2760,7 @@ void QCBUILTIN PF_entityprotection (pubprogfuncs_t *prinst, struct globalvars_s
wedict_t *e = G_WEDICT(prinst, OFS_PARM0);
int prot = G_FLOAT(OFS_PARM1);
if (e->isfree)
if (ED_ISFREE(e))
PR_BIError(prinst, "PF_entityprotection: entity is free");
G_FLOAT(OFS_RETURN) = prot;

View file

@ -74,6 +74,9 @@ typedef struct trace_s
float truefraction; //can be negative, also has floating point precision issues, etc.
int brush_id;
int brush_face;
int surface_id;
int triangle_id;
int bone_id;
} trace_t;
typedef struct q2trace_s

View file

@ -2096,7 +2096,7 @@ static void BE_DrawMeshChain_Internal(void)
{
m = shaderstate.meshlist[0];
ID3D11DeviceContext_IASetIndexBuffer(d3ddevctx, shaderstate.batchvbo->indicies.d3d.buff, DXGI_FORMAT_R16_UINT, shaderstate.batchvbo->indicies.d3d.offs);
ID3D11DeviceContext_IASetIndexBuffer(d3ddevctx, shaderstate.batchvbo->indicies.d3d.buff, DXGI_FORMAT_INDEX_UINT, shaderstate.batchvbo->indicies.d3d.offs);
idxfirst = m->vbofirstelement;
vertcount = m->vbofirstvert + m->numvertexes;
@ -2123,7 +2123,7 @@ static void BE_DrawMeshChain_Internal(void)
map += m->numindexes;
}
ID3D11DeviceContext_Unmap(d3ddevctx, (ID3D11Resource*)buf, 0);
ID3D11DeviceContext_IASetIndexBuffer(d3ddevctx, buf, DXGI_FORMAT_R16_UINT, byteofs);
ID3D11DeviceContext_IASetIndexBuffer(d3ddevctx, buf, DXGI_FORMAT_INDEX_UINT, byteofs);
idxfirst = 0;
}
else
@ -2149,7 +2149,7 @@ static void BE_DrawMeshChain_Internal(void)
vertcount += m->numvertexes;
}
ID3D11DeviceContext_Unmap(d3ddevctx, (ID3D11Resource*)buf, 0);
ID3D11DeviceContext_IASetIndexBuffer(d3ddevctx, buf, DXGI_FORMAT_R16_UINT, byteofs);
ID3D11DeviceContext_IASetIndexBuffer(d3ddevctx, buf, DXGI_FORMAT_INDEX_UINT, byteofs);
idxfirst = 0;
}
@ -3517,7 +3517,7 @@ void D3D11BE_RenderShadowBuffer(unsigned int numverts, void *vbuf, unsigned int
shaderstate.lastpasscount = 0;
ID3D11DeviceContext_IASetVertexBuffers(d3ddevctx, 0, 1, vbufs, vstrides, voffsets);
ID3D11DeviceContext_IASetIndexBuffer(d3ddevctx, ibuf, DXGI_FORMAT_R16_UINT, 0);
ID3D11DeviceContext_IASetIndexBuffer(d3ddevctx, ibuf, DXGI_FORMAT_INDEX_UINT, 0);
BE_ApplyUniforms(shaderstate.depthonly->prog, 0);

View file

@ -278,6 +278,7 @@ void D3D11_UploadLightmap(lightmapinfo_t *lm)
mips.mip[0].needfree = false;
mips.mip[0].width = lm->width;
mips.mip[0].height = lm->height;
mips.mip[0].datasize = lm->width*lm->height*4;
if (lightmap_bgra)
mips.encoding = PTI_BGRX8;
else

View file

@ -105,7 +105,8 @@ extern ID3D11Device *pD3DDev11;
#include <d3d11shader.h>
#endif
const GUID IID_ID3D11ShaderReflection = {0x8d536ca1, 0x0cca, 0x4956, {0xa8, 0x37, 0x78, 0x69, 0x63, 0x75, 0x55, 0x84}};
//const GUID IID_ID3D11ShaderReflection = {0x8d536ca1, 0x0cca, 0x4956, {0xa8, 0x37, 0x78, 0x69, 0x63, 0x75, 0x55, 0x84}};
const GUID IID_ID3D11ShaderReflection = {0x0a233719, 0x3960, 0x4578, {0x9d, 0x7c, 0x20, 0x3b, 0x8b, 0x1d, 0x9c, 0xc1}};
#define ID3DBlob_GetBufferPointer(b) b->lpVtbl->GetBufferPointer(b)
#define ID3DBlob_Release(b) b->lpVtbl->Release(b)
#define ID3DBlob_GetBufferSize(b) b->lpVtbl->GetBufferSize(b)
@ -678,6 +679,8 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, unsigned
}
ID3D11ShaderReflection_Release(freflect);
}
else
Con_Printf("%s: D3DReflect failed, unable to get reflection info\n", name);
}
if (vcode)
@ -739,6 +742,8 @@ qboolean D3D11Shader_Init(unsigned int flevel)
sh_config.pCreateProgram = D3D11Shader_CreateProgram;
sh_config.pProgAutoFields = NULL;
sh_config.can_mipcap = true; //at creation time
// sh_config.tex_env_combine = 1;
// sh_config.nv_tex_env_combine4 = 1;
// sh_config.env_add = 1;

View file

@ -485,6 +485,8 @@ void D3D9Shader_Init(void)
sh_config.texfmt[PTI_ARGB1555] = true;
sh_config.texfmt[PTI_ARGB4444] = true;
sh_config.can_mipcap = true; //at creation time, I think.
IDirect3DDevice9_GetDeviceCaps(pD3DDev9, &caps);
if (caps.TextureCaps & D3DPTEXTURECAPS_POW2)

View file

@ -1184,42 +1184,44 @@ static void D3D9_SetupViewPortProjection(void)
static void (D3D9_R_RenderView) (void)
{
Surf_SetupFrame();
//check if we can do underwater warp
if (cls.protocol != CP_QUAKE2) //quake2 tells us directly
if (!r_norefresh.value)
{
if (r_viewcontents & FTECONTENTS_FLUID)
r_refdef.flags |= RDF_UNDERWATER;
else
r_refdef.flags &= ~RDF_UNDERWATER;
}
if (r_refdef.flags & RDF_UNDERWATER)
{
extern cvar_t r_projection;
if (!r_waterwarp.value || r_projection.ival)
r_refdef.flags &= ~RDF_UNDERWATER; //no warp at all
// else if (r_waterwarp.value > 0 && scenepp_waterwarp)
// r_refdef.flags |= RDF_WATERWARP; //try fullscreen warp instead if we can
}
Surf_SetupFrame();
D3D9_SetupViewPortProjection();
//check if we can do underwater warp
if (cls.protocol != CP_QUAKE2) //quake2 tells us directly
{
if (r_viewcontents & FTECONTENTS_FLUID)
r_refdef.flags |= RDF_UNDERWATER;
else
r_refdef.flags &= ~RDF_UNDERWATER;
}
if (r_refdef.flags & RDF_UNDERWATER)
{
extern cvar_t r_projection;
if (!r_waterwarp.value || r_projection.ival)
r_refdef.flags &= ~RDF_UNDERWATER; //no warp at all
// else if (r_waterwarp.value > 0 && scenepp_waterwarp)
// r_refdef.flags |= RDF_WATERWARP; //try fullscreen warp instead if we can
}
// if (r_clear.ival && !(r_refdef.flags & RDF_NOWORLDMODEL))
// d3d9error(IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(255,0,0), 1, 0));
// else
d3d9error(IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1, 0));
D3D9_SetupViewPortProjection();
R_SetFrustum (r_refdef.m_projection, r_refdef.m_view);
RQ_BeginFrame();
if (!(r_refdef.flags & RDF_NOWORLDMODEL))
{
if (cl.worldmodel)
P_DrawParticles ();
// if (r_clear.ival && !(r_refdef.flags & RDF_NOWORLDMODEL))
// d3d9error(IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(255,0,0), 1, 0));
// else
d3d9error(IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1, 0));
R_SetFrustum (r_refdef.m_projection, r_refdef.m_view);
RQ_BeginFrame();
if (!(r_refdef.flags & RDF_NOWORLDMODEL))
{
if (cl.worldmodel)
P_DrawParticles ();
}
Surf_DrawWorld();
RQ_RenderBatchClear();
}
Surf_DrawWorld();
RQ_RenderBatchClear();
D3D9_Set2D ();
}

View file

@ -544,7 +544,7 @@ static LRESULT WINAPI D3D11_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
Cbuf_AddText("\nquit\n", RESTRICT_LOCAL);
}
break;
break;
case WM_ACTIVATE:
fActive = LOWORD(wParam);
@ -557,8 +557,11 @@ static LRESULT WINAPI D3D11_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
if (modestate == MS_FULLSCREEN)
{
IDXGISwapChain_SetFullscreenState(d3dswapchain, vid.activeapp, d3dscreen);
D3D11_DoResize();
if (d3dswapchain)
{
IDXGISwapChain_SetFullscreenState(d3dswapchain, vid.activeapp, d3dscreen);
D3D11_DoResize();
}
}
Cvar_ForceCallback(&v_gamma);
@ -1429,81 +1432,83 @@ static void (D3D11_R_RenderView) (void)
qboolean dofbo = *r_refdef.rt_destcolour[0].texname || *r_refdef.rt_depth.texname;
// texid_t colourrt[1];
if (r_speeds.ival)
time1 = Sys_DoubleTime();
if (dofbo)
D3D11_ApplyRenderTargets(true);
else
ID3D11DeviceContext_ClearDepthStencilView(d3ddevctx, fb_backdepthstencil, D3D11_CLEAR_DEPTH, 1, 0); //is it faster to clear the stencil too?
//check if we can do underwater warp
if (cls.protocol != CP_QUAKE2) //quake2 tells us directly
if (!r_norefresh.value)
{
if (r_viewcontents & FTECONTENTS_FLUID)
r_refdef.flags |= RDF_UNDERWATER;
if (r_speeds.ival)
time1 = Sys_DoubleTime();
if (dofbo)
D3D11_ApplyRenderTargets(true);
else
r_refdef.flags &= ~RDF_UNDERWATER;
}
if (r_refdef.flags & RDF_UNDERWATER)
{
extern cvar_t r_projection;
if (!r_waterwarp.value || r_projection.ival)
r_refdef.flags &= ~RDF_UNDERWATER; //no warp at all
// else if (r_waterwarp.value > 0 && scenepp_waterwarp)
// r_refdef.flags |= RDF_WATERWARP; //try fullscreen warp instead if we can
}
ID3D11DeviceContext_ClearDepthStencilView(d3ddevctx, fb_backdepthstencil, D3D11_CLEAR_DEPTH, 1, 0); //is it faster to clear the stencil too?
D3D11_SetupViewPort();
//unlike gl, we clear colour beforehand, because that seems more sane.
//always clear depth
x = (r_refdef.vrect.x * (int)vid.pixelwidth)/(int)vid.width;
x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * (int)vid.pixelwidth/(int)vid.width;
y = (r_refdef.vrect.y * (int)vid.pixelheight)/(int)vid.height;
y2 = (r_refdef.vrect.y + r_refdef.vrect.height) * (int)vid.pixelheight/(int)vid.height;
r_refdef.pxrect.x = floor(x);
r_refdef.pxrect.y = floor(y);
r_refdef.pxrect.width = (int)ceil(x2) - r_refdef.pxrect.x;
r_refdef.pxrect.height = (int)ceil(y2) - r_refdef.pxrect.y;
Surf_SetupFrame();
//fixme: waterwarp fov
R_SetFrustum (r_refdef.m_projection, r_refdef.m_view);
RQ_BeginFrame();
// if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL))
// {
// if (cl.worldmodel)
// P_DrawParticles ();
// }
if (!(r_refdef.flags & RDF_NOWORLDMODEL))
if (!r_worldentity.model || r_worldentity.model->loadstate != MLS_LOADED || !cl.worldmodel)
//check if we can do underwater warp
if (cls.protocol != CP_QUAKE2) //quake2 tells us directly
{
D3D11_Set2D ();
R2D_ImageColours(0, 0, 0, 1);
R2D_FillBlock(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height);
R2D_ImageColours(1, 1, 1, 1);
if (dofbo)
D3D11_ApplyRenderTargets(false);
return;
if (r_viewcontents & FTECONTENTS_FLUID)
r_refdef.flags |= RDF_UNDERWATER;
else
r_refdef.flags &= ~RDF_UNDERWATER;
}
if (r_refdef.flags & RDF_UNDERWATER)
{
extern cvar_t r_projection;
if (!r_waterwarp.value || r_projection.ival)
r_refdef.flags &= ~RDF_UNDERWATER; //no warp at all
// else if (r_waterwarp.value > 0 && scenepp_waterwarp)
// r_refdef.flags |= RDF_WATERWARP; //try fullscreen warp instead if we can
}
Surf_DrawWorld();
RQ_RenderBatchClear();
D3D11_Set2D ();
D3D11_SetupViewPort();
//unlike gl, we clear colour beforehand, because that seems more sane.
//always clear depth
if (r_speeds.ival)
{
time2 = Sys_DoubleTime();
RQuantAdd(RQUANT_MSECS, (int)((time2-time1)*1000000));
x = (r_refdef.vrect.x * (int)vid.pixelwidth)/(int)vid.width;
x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * (int)vid.pixelwidth/(int)vid.width;
y = (r_refdef.vrect.y * (int)vid.pixelheight)/(int)vid.height;
y2 = (r_refdef.vrect.y + r_refdef.vrect.height) * (int)vid.pixelheight/(int)vid.height;
r_refdef.pxrect.x = floor(x);
r_refdef.pxrect.y = floor(y);
r_refdef.pxrect.width = (int)ceil(x2) - r_refdef.pxrect.x;
r_refdef.pxrect.height = (int)ceil(y2) - r_refdef.pxrect.y;
Surf_SetupFrame();
//fixme: waterwarp fov
R_SetFrustum (r_refdef.m_projection, r_refdef.m_view);
RQ_BeginFrame();
// if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL))
// {
// if (cl.worldmodel)
// P_DrawParticles ();
// }
if (!(r_refdef.flags & RDF_NOWORLDMODEL))
if (!r_worldentity.model || r_worldentity.model->loadstate != MLS_LOADED || !cl.worldmodel)
{
D3D11_Set2D ();
R2D_ImageColours(0, 0, 0, 1);
R2D_FillBlock(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height);
R2D_ImageColours(1, 1, 1, 1);
if (dofbo)
D3D11_ApplyRenderTargets(false);
return;
}
Surf_DrawWorld();
RQ_RenderBatchClear();
if (r_speeds.ival)
{
time2 = Sys_DoubleTime();
RQuantAdd(RQUANT_MSECS, (int)((time2-time1)*1000000));
}
if (dofbo)
D3D11_ApplyRenderTargets(false);
}
if (dofbo)
D3D11_ApplyRenderTargets(false);
D3D11_Set2D ();
}
void D3D11BE_RenderToTextureUpdate2d(qboolean destchanged)

View file

@ -126,6 +126,7 @@ static void Mod_ComposeSkin(char *texture, struct cctx_s *cctx)
float x=0, y=0;
float w, h;
int iw=0, ih=0;
float s1 = 0, t1 = 0, s2 = 1, t2 = 1;
float r=1,g=1,b=1,a=1;
int l;
char *s, tname[MAX_QPATH];
@ -173,6 +174,18 @@ static void Mod_ComposeSkin(char *texture, struct cctx_s *cctx)
s++;
h = strtod(s, &s);
break;
case '$':
s1 = strtod(s+1, &s);
if (*s == ',')
s++;
t1 = strtod(s, &s);
if (*s == ',')
s++;
s2 = strtod(s, &s);
if (*s == ',')
s++;
t2 = strtod(s, &s);
break;
case '?':
r = strtod(s+1, &s);
if (*s == ',')
@ -210,7 +223,7 @@ static void Mod_ComposeSkin(char *texture, struct cctx_s *cctx)
return;
R2D_ImageColours(r,g,b,a);
R2D_Image(x, 512-(y+h), w, h, 0, 1, 1, 0, sourceimg);
R2D_Image(x, cctx->height-(y+h), w, h, s1, t2, s2, t1, sourceimg);
R_UnloadShader(sourceimg); //we're done with it now
}
//create a new skin with explicit name and text. even if its already loaded. this means you can free it safely.

View file

@ -332,7 +332,7 @@ qboolean GL_LoadTextureMips(texid_t tex, struct pendingtextureinfo *mips)
//note that some drivers will just ignore levels that are not valid.
//this means that we can't make this setting dynamic, so we might as well let the drivers know BEFORE we do the uploads, to be kind to those that are buggy..
//this is available in gles3
if (!gl_config.gles || gl_config.glversion >= 3.0)
if (sh_config.can_mipcap)
{
if (targ != GL_TEXTURE_CUBE_MAP_ARB)
{

View file

@ -59,6 +59,7 @@ typedef enum {
#define MAX_GPU_BONES 64 //ATI drivers bug out and start to crash if you put this at 128. FIXME: make dynamic.
#endif
struct doll_s;
void rag_uninstanciateall(void);
void rag_flushdolls(qboolean force);
void rag_freedoll(struct doll_s *doll);
struct doll_s *rag_createdollfromstring(struct model_s *mod, const char *fname, int numbones, const char *file);

View file

@ -2753,9 +2753,13 @@ void GL_Init(void *(*getglfunction) (char *name))
sh_config.blobpath = "gles/%s.blob";
sh_config.progpath = "glsl/%s.glsl";
sh_config.shadernamefmt = "%s_gles";
sh_config.can_mipcap = gl_config.glversion >= 3.0;
}
else
{
sh_config.can_mipcap = gl_config.glversion >= 1.2;
sh_config.texfmt[PTI_RGBX8] = true; //proper support
//these require stuff like GL_UNSIGNED_SHORT_5_5_5_1 etc, which needs gl 1.2+

View file

@ -2108,7 +2108,7 @@ void INS_ReInit(void)
void INS_Shutdown(void)
{
}
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, int *qdevid))
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, unsigned int *qdevid))
{
}

View file

@ -205,7 +205,7 @@ void INS_Shutdown (void)
void INS_Commands (void)
{
}
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, int *qdevid))
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, unsigned int *qdevid))
{
}
void INS_Move (float *movements, int pnum)

View file

@ -703,6 +703,7 @@ typedef struct
qboolean tex_env_combine;
qboolean nv_tex_env_combine4;
qboolean env_add;
qboolean can_mipcap; //
void (*pDeleteProg) (program_t *prog);
qboolean (*pLoadBlob) (program_t *prog, const char *name, unsigned int permu, vfsfile_t *blobfile);

View file

@ -169,7 +169,7 @@ void INS_ReInit(void)
void INS_Shutdown(void)
{
}
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, int *qdevid))
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, unsigned int *qdevid))
{
}

View file

@ -56,7 +56,7 @@ enum ereftype_e
ER_FREE,
ER_OBJECT //custom sized, no vm/engine fields.
};
#define isfree ereftype != ER_ENTITY
#define ED_ISFREE(e) ((e)->ereftype != ER_ENTITY)
//used by progs engine. All nulls is reset.
typedef struct {

View file

@ -752,13 +752,16 @@ void PR_LoadGlabalStruct(qboolean muted)
globalint (true, trace_ent);
globalfloat (false, trace_inopen);
globalfloat (false, trace_inwater);
globalfloat (false, trace_endcontents);
globalfloat (false, trace_endcontentsf);
globalint (false, trace_endcontentsi);
globalfloat (false, trace_surfaceflags);
globalfloat (false, trace_surfaceflagsf);
globalint (false, trace_surfaceflagsi);
globalstring (false, trace_surfacename);
globalint (false, trace_brush_id);
globalint (false, trace_brush_faceid);
globalint (false, trace_surface_id);
globalint (false, trace_bone_id);
globalint (false, trace_triangle_id);
globalfloat (false, cycle_wrapped);
globalint (false, msg_entity);
globalfunc (false, main);
@ -795,15 +798,37 @@ void PR_LoadGlabalStruct(qboolean muted)
#define ensureglobal(name,var) if (!(pr_globals)->name) (pr_globals)->name = &var;
if (!(pr_globals)->trace_surfaceflagsf && !(pr_globals)->trace_surfaceflagsi)
{
etype_t etype;
eval_t *v = PR_FindGlobal(svprogfuncs, "trace_surfaceflags", 0, &etype);
if (etype == ev_float)
(pr_globals)->trace_surfaceflagsf = (float*)v;
else if (etype == ev_integer)
(pr_globals)->trace_surfaceflagsi = (int*)v;
}
if (!(pr_globals)->trace_endcontentsf && !(pr_globals)->trace_endcontentsi)
{
etype_t etype;
eval_t *v = PR_FindGlobal(svprogfuncs, "trace_endcontents", 0, &etype);
if (etype == ev_float)
(pr_globals)->trace_endcontentsf = (float*)v;
else if (etype == ev_integer)
(pr_globals)->trace_endcontentsi = (int*)v;
}
// make sure these entries are always valid pointers
ensureglobal(dimension_send, dimension_send_default);
ensureglobal(dimension_default, dimension_default);
ensureglobal(trace_endcontents, writeonly);
ensureglobal(trace_endcontentsf, writeonly);
ensureglobal(trace_endcontentsi, writeonly_int);
ensureglobal(trace_surfaceflags, writeonly);
ensureglobal(trace_surfaceflagsf, writeonly);
ensureglobal(trace_surfaceflagsi, writeonly_int);
ensureglobal(trace_brush_id, writeonly_int);
ensureglobal(trace_brush_faceid, writeonly_int);
ensureglobal(trace_surface_id, writeonly_int);
ensureglobal(trace_bone_id, writeonly_int);
ensureglobal(trace_triangle_id, writeonly_int);
ensureglobal(input_timelength, input_timelength_default);
ensureglobal(input_impulse, input_impulse_default);
@ -1185,7 +1210,7 @@ void PR_ApplyCompilation_f (void)
for (i=0 ; i<sv.world.num_edicts ; i++)
{
ent = EDICT_NUM(svprogfuncs, i);
if (ent->isfree)
if (ED_ISFREE(ent))
continue;
World_LinkEdict (&sv.world, (wedict_t*)ent, false); // force retouch even for stationary
@ -2355,7 +2380,7 @@ static void QCBUILTIN PF_setsize (pubprogfuncs_t *prinst, struct globalvars_s *p
float *min, *max;
e = G_EDICT(prinst, OFS_PARM0);
if (e->isfree)
if (ED_ISFREE(e))
{
if (progstype != PROG_H2 || developer.ival)
PR_RunWarning(prinst, "%s edict %i was free\n", "setsize", e->entnum);
@ -2398,7 +2423,7 @@ void PF_setmodel_Internal (pubprogfuncs_t *prinst, edict_t *e, const char *m)
PR_RunWarning(prinst, "%s edict %i is read-only\n", "setmodel", e->entnum);
return;
}
if (e->isfree)
if (ED_ISFREE(e))
{
PR_RunWarning(prinst, "%s edict %i was free\n", "setmodel", e->entnum);
return;
@ -3186,14 +3211,18 @@ static void set_trace_globals(pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
pr_global_struct->trace_fraction = trace->fraction;
pr_global_struct->trace_inwater = trace->inwater;
pr_global_struct->trace_inopen = trace->inopen;
pr_global_struct->trace_surfaceflags = trace->surface?trace->surface->flags:0;
pr_global_struct->trace_surfaceflagsf = trace->surface?trace->surface->flags:0;
pr_global_struct->trace_surfaceflagsi = trace->surface?trace->surface->flags:0;
if (pr_global_ptrs->trace_surfacename)
prinst->SetStringField(prinst, NULL, &pr_global_struct->trace_surfacename, trace->surface?trace->surface->name:NULL, true);
pr_global_struct->trace_endcontents = trace->contents;
pr_global_struct->trace_endcontentsf = trace->contents;
pr_global_struct->trace_endcontentsi = trace->contents;
pr_global_struct->trace_brush_id = trace->brush_id;
pr_global_struct->trace_brush_faceid = trace->brush_face;
pr_global_struct->trace_surface_id = trace->surface_id;
pr_global_struct->trace_bone_id = trace->bone_id;
pr_global_struct->trace_triangle_id = trace->triangle_id;
// if (trace.fraction != 1)
// VectorMA (trace->endpos, 4, trace->plane.normal, P_VEC(trace_endpos));
// else
@ -3347,7 +3376,7 @@ int PF_newcheckclient (pubprogfuncs_t *prinst, int check)
if (i == check)
break; // didn't find anything else
if (ent->isfree)
if (ED_ISFREE(ent))
continue;
if (ent->v->health <= 0)
continue;
@ -3405,7 +3434,7 @@ int PF_checkclient_Internal (pubprogfuncs_t *prinst)
// return check if it might be visible
ent = EDICT_NUM(prinst, w->lastcheck);
if (ent->isfree || ent->v->health <= 0)
if (ED_ISFREE(ent) || ent->v->health <= 0)
{
return 0;
}
@ -3747,7 +3776,7 @@ static void QCBUILTIN PF_Remove (pubprogfuncs_t *prinst, struct globalvars_s *pr
ed = G_EDICT(prinst, OFS_PARM0);
if (ed->isfree)
if (ED_ISFREE(ed))
{
ED_CanFree(ed); //fake it
if (developer.value)
@ -5735,12 +5764,12 @@ static qboolean PR_SQLResultAvailable(queryrequest_t *req, int firstrow, int num
// recall self and other references
ent = PROG_TO_EDICT(prinst, req->user.selfent);
if (ent->isfree || ent->xv->uniquespawnid != req->user.selfid)
if (ED_ISFREE(ent) || ent->xv->uniquespawnid != req->user.selfid)
pr_global_struct->self = pr_global_struct->world;
else
pr_global_struct->self = req->user.selfent;
ent = PROG_TO_EDICT(prinst, req->user.otherent);
if (ent->isfree || ent->xv->uniquespawnid != req->user.otherid)
if (ED_ISFREE(ent) || ent->xv->uniquespawnid != req->user.otherid)
pr_global_struct->other = pr_global_struct->world;
else
pr_global_struct->other = req->user.otherent;
@ -5783,9 +5812,9 @@ void QCBUILTIN PF_sqlopenquery (pubprogfuncs_t *prinst, struct globalvars_s *pr_
qreq->user.qccallback = callfunc;
// save self and other references
qreq->user.selfent = PROG_TO_EDICT(prinst, pr_global_struct->self)->isfree?pr_global_struct->world:pr_global_struct->self;
qreq->user.selfent = ED_ISFREE(PROG_TO_EDICT(prinst, pr_global_struct->self))?pr_global_struct->world:pr_global_struct->self;
qreq->user.selfid = PROG_TO_EDICT(prinst, qreq->user.selfent)->xv->uniquespawnid;
qreq->user.otherent = PROG_TO_EDICT(prinst, pr_global_struct->other)->isfree?pr_global_struct->world:pr_global_struct->other;
qreq->user.otherent = ED_ISFREE(PROG_TO_EDICT(prinst, pr_global_struct->other))?pr_global_struct->world:pr_global_struct->other;
qreq->user.otherid = PROG_TO_EDICT(prinst, qreq->user.otherent)->xv->uniquespawnid;
if (querytype & 2)
@ -6640,7 +6669,7 @@ static void QCBUILTIN PF_sv_findchain (pubprogfuncs_t *prinst, struct globalvars
for (i = 1; i < *prinst->parms->sv_num_edicts; i++)
{
ent = EDICT_NUM(prinst, i);
if (ent->isfree)
if (ED_ISFREE(ent))
continue;
t = *(string_t *)&((float*)ent->v)[f];
if (!t)
@ -6673,7 +6702,7 @@ static void QCBUILTIN PF_sv_findchainfloat (pubprogfuncs_t *prinst, struct globa
for (i = 1; i < *prinst->parms->sv_num_edicts; i++)
{
ent = EDICT_NUM(prinst, i);
if (ent->isfree)
if (ED_ISFREE(ent))
continue;
if (((float *)ent->v)[f] != s)
continue;
@ -6703,7 +6732,7 @@ static void QCBUILTIN PF_sv_findchainflags (pubprogfuncs_t *prinst, struct globa
for (i = 1; i < *prinst->parms->sv_num_edicts; i++)
{
ent = EDICT_NUM(prinst, i);
if (ent->isfree)
if (ED_ISFREE(ent))
continue;
if (!((int)((float *)ent->v)[f] & s))
continue;
@ -10113,7 +10142,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"particleeffectquery",PF_Fixme,0, 0, 0, 374, D("string(float efnum, float body)", "Retrieves either the name or the body of the effect with the given number. The effect body is regenerated from internal state, and can be changed before being reapplied via the localcmd builtin.")},
{"adddecal", PF_Fixme, 0, 0, 0, 375, D("void(string shadername, vector origin, vector up, vector side, vector rgb, float alpha)", "Adds a temporary clipped decal shader to the scene, centered at the given point with given orientation. Will be drawn by the next renderscene call, and freed by the next clearscene call.")},
{"setcustomskin", PF_Fixme, 0, 0, 0, 376, D("void(entity e, string skinfilename, optional string skindata)", "Sets an entity's skin overrides. These are custom per-entity surface->shader lookups. The skinfilename/data should be in .skin format:\nsurfacename,shadername - makes the named surface use the named shader\nreplace \"surfacename\" \"shadername\" - same.\nqwskin \"foo\" - use an unmodified quakeworld player skin (including crop+repalette rules)\nq1lower 0xff0000 - specify an override for the entity's lower colour, in this case to red\nq1upper 0x0000ff - specify an override for the entity's lower colour, in this case to blue\ncompose \"surfacename\" \"shader\" \"imagename@x,y:w,h?r,g,b,a\" - compose a skin texture from multiple images.\n The texture is determined to be sufficient to hold the first named image, additional images can be named as extra tokens on the same line.\n Use a + at the end of the line to continue reading image tokens from the next line also, the named shader must use 'map $diffuse' to read the composed texture (compatible with the defaultskin shader).")},
{"setcustomskin", PF_Fixme, 0, 0, 0, 376, D("void(entity e, string skinfilename, optional string skindata)", "Sets an entity's skin overrides. These are custom per-entity surface->shader lookups. The skinfilename/data should be in .skin format:\nsurfacename,shadername - makes the named surface use the named shader\nreplace \"surfacename\" \"shadername\" - same.\nqwskin \"foo\" - use an unmodified quakeworld player skin (including crop+repalette rules)\nq1lower 0xff0000 - specify an override for the entity's lower colour, in this case to red\nq1upper 0x0000ff - specify an override for the entity's lower colour, in this case to blue\ncompose \"surfacename\" \"shader\" \"imagename@x,y:w,h$s,t,s2,t2?r,g,b,a\" - compose a skin texture from multiple images.\n The texture is determined to be sufficient to hold the first named image, additional images can be named as extra tokens on the same line.\n Use a + at the end of the line to continue reading image tokens from the next line also, the named shader must use 'map $diffuse' to read the composed texture (compatible with the defaultskin shader).")},
//END EXT_CSQC
{"memalloc", PF_memalloc, 0, 0, 0, 384, D("__variant*(int size)", "Allocate an arbitary block of memory")},
@ -11042,8 +11071,14 @@ void PR_DumpPlatform_f(void)
{"input_cursor_trace_endpos", "vector", CS/*|QW|NQ*/},
{"input_cursor_trace_entnum", "float", CS/*|QW|NQ*/},
{"trace_endcontents", "int", QW|NQ|CS},
{"trace_surfaceflags", "int", QW|NQ|CS},
// {"trace_surfacename", "string", QW|NQ|CS},
{"trace_brush_id", "int", QW|NQ|CS},
{"trace_brush_faceid", "int", QW|NQ|CS},
{"trace_surface_id", "int", QW|NQ|CS, "1-based. 0 if not known."},
{"trace_bone_id", "int", QW|NQ|CS, "1-based. 0 if not known. typically needs MOVE_HITMODEL."},
{"trace_triangle_id", "int", QW|NQ|CS, "1-based. 0 if not known."},
{"global_gravitydir", "vector", QW|NQ|CS, "The direction gravity should act in if not otherwise specified per entity.", 0,"'0 0 -1'"},
{"serverid", "int", QW|NQ|CS, "The unique id of this server within the server cluster."},

View file

@ -36,9 +36,9 @@
globalentity (true, trace_ent) \
globalfloat (true, trace_inopen) \
globalfloat (true, trace_inwater) \
globalfloat (false, trace_endcontents) \
globalfloat (false, trace_endcontentsf) \
globalint (false, trace_endcontentsi) \
globalfloat (false, trace_surfaceflags) \
globalfloat (false, trace_surfaceflagsf) \
globalint (false, trace_surfaceflagsi) \
globalfloat (false, cycle_wrapped) \
globalentity (false, msg_entity) \

View file

@ -454,7 +454,7 @@ static edict_t *QDECL Q1QVMPF_EntAlloc(pubprogfuncs_t *pf, pbool object, size_t
e = (edict_t*)EDICT_NUM(pf, i);
// the first couple seconds of server time can involve a lot of
// freeing and allocating, so relax the replacement policy
if (!e || (e->isfree && ( e->freetime < 2 || sv.time - e->freetime > 0.5 ) ))
if (!e || (ED_ISFREE(e) && ( e->freetime < 2 || sv.time - e->freetime > 0.5 ) ))
{
Q1QVMED_ClearEdict (e, true);
@ -470,7 +470,7 @@ static edict_t *QDECL Q1QVMPF_EntAlloc(pubprogfuncs_t *pf, pbool object, size_t
e = (edict_t*)EDICT_NUM(pf, i);
// the first couple seconds of server time can involve a lot of
// freeing and allocating, so relax the replacement policy
if (!e || (e->isfree))
if (!e || ED_ISFREE(e))
{
Q1QVMED_ClearEdict (e, true);
@ -669,7 +669,7 @@ static qintptr_t QVM_LightStyle (void *offset, quintptr_t mask, const qintptr_t
static qintptr_t QVM_SetOrigin (void *offset, quintptr_t mask, const qintptr_t *arg)
{
edict_t *e = Q1QVMPF_EdictNum(svprogfuncs, VM_LONG(arg[0]));
if (!e || e->isfree)
if (!e || ED_ISFREE(e))
return false;
e->v->origin[0] = VM_FLOAT(arg[1]);
@ -681,7 +681,7 @@ static qintptr_t QVM_SetOrigin (void *offset, quintptr_t mask, const qintptr_t *
static qintptr_t QVM_SetSize (void *offset, quintptr_t mask, const qintptr_t *arg)
{
edict_t *e = Q1QVMPF_EdictNum(svprogfuncs, arg[0]);
if (!e || e->isfree)
if (!e || ED_ISFREE(e))
return false;
e->v->mins[0] = VM_FLOAT(arg[1]);
@ -793,7 +793,7 @@ static qintptr_t QVM_FindRadius (void *offset, quintptr_t mask, const qintptr_t
for(start++; start < sv.world.num_edicts; start++)
{
ed = EDICT_NUM(svprogfuncs, start);
if (ed->isfree)
if (ED_ISFREE(ed))
continue;
VectorSubtract(ed->v->origin, org, diff);
if (rad > DotProduct(diff, diff))
@ -875,7 +875,7 @@ static qintptr_t QVM_NextEnt (void *offset, quintptr_t mask, const qintptr_t *ar
return 0;
}
ent = EDICT_NUM(svprogfuncs, i);
if (!ent->isfree)
if (!ED_ISFREE(ent))
{
return i;
}
@ -2034,9 +2034,9 @@ qboolean PR_LoadQ1QVM(void)
globalint (true, trace_ent);
globalfloat (true, trace_inopen);
globalfloat (true, trace_inwater);
globalnull (false, trace_endcontents);
globalnull (false, trace_endcontentsf);
globalnull (false, trace_endcontentsi);
globalnull (false, trace_surfaceflags);
globalnull (false, trace_surfaceflagsf);
globalnull (false, trace_surfaceflagsi);
globalnull (false, cycle_wrapped);
globalint (false, msg_entity);
@ -2051,9 +2051,9 @@ qboolean PR_LoadQ1QVM(void)
globalfunc (false, SetNewParms);
globalfunc (false, SetChangeParms);
pr_global_ptrs->trace_surfaceflags = &writable;
pr_global_ptrs->trace_surfaceflagsf = &writable;
pr_global_ptrs->trace_surfaceflagsi = &writable_int;
pr_global_ptrs->trace_endcontents = &writable;
pr_global_ptrs->trace_endcontentsf = &writable;
pr_global_ptrs->trace_endcontentsi = &writable_int;
pr_global_ptrs->dimension_default = &dimensiondefault;
pr_global_ptrs->dimension_send = &dimensionsend;

View file

@ -60,13 +60,16 @@ typedef struct nqglobalvars_s
float *trace_allsolid;
float *trace_startsolid;
float *trace_fraction;
float *trace_surfaceflags;
float *trace_surfaceflagsf;
int *trace_surfaceflagsi;
string_t*trace_surfacename;
float *trace_endcontents;
float *trace_endcontentsf;
int *trace_endcontentsi;
int *trace_brush_id;
int *trace_brush_faceid;
int *trace_surface_id;
int *trace_bone_id;
int *trace_triangle_id;
vec3_t *trace_endpos;
vec3_t *trace_plane_normal;
float *trace_plane_dist;

View file

@ -337,7 +337,7 @@ void SV_Loadgame_Legacy(char *filename, vfsfile_t *f, int version)
if (!ent)
break;
if (ent->isfree)
if (ED_ISFREE(ent))
continue;
World_LinkEdict (&sv.world, (wedict_t*)ent, false);
@ -839,7 +839,7 @@ qboolean SV_LoadLevelCache(const char *savename, const char *level, const char *
for (i=0 ; i<sv.world.num_edicts ; i++)
{
ent = EDICT_NUM(svprogfuncs, i);
if (ent->isfree)
if (ED_ISFREE(ent))
continue;
World_LinkEdict (&sv.world, (wedict_t*)ent, false);
@ -847,7 +847,7 @@ qboolean SV_LoadLevelCache(const char *savename, const char *level, const char *
for (i=0 ; i<sv.world.num_edicts ; i++)
{
ent = EDICT_NUM(svprogfuncs, i);
if (ent->isfree)
if (ED_ISFREE(ent))
continue;
/*hexen2 instead overwrites ents, which can theoretically be unreliable (ents with this flag are not saved in the first place, and thus are effectively reset instead of reloaded).

View file

@ -3532,7 +3532,7 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, pvscamera_t
for ( ; e<limit ; e++)
{
ent = EDICT_NUM(svprogfuncs, e);
if (ent->isfree)
if (ED_ISFREE(ent))
continue;
if (ent->xv->customizeentityforclient)
@ -4001,7 +4001,7 @@ void SV_ProcessSendFlags(client_t *c)
for (e=1 ; e<sv.world.num_edicts && e < c->max_net_ents; e++)
{
ent = EDICT_NUM(svprogfuncs, e);
if (ent->isfree)
if (ED_ISFREE(ent))
continue;
if (ent->xv->SendFlags)
{

View file

@ -237,7 +237,7 @@ void SVQ1_CreateBaseline (void)
memcpy(&svent->baseline, &nullentitystate, sizeof(entity_state_t));
svent->baseline.number = entnum;
if (svent->isfree)
if (ED_ISFREE(svent))
continue;
// create baselines for all player slots,
// and any other edict that has a visible model

View file

@ -192,7 +192,7 @@ qboolean WPhys_RunThink (world_t *w, wedict_t *ent)
ent->v->nextthink = 0;
*w->g.time = thinktime;
w->Event_Think(w, ent);
return !ent->isfree;
return !ED_ISFREE(ent);
}
do
@ -212,7 +212,7 @@ qboolean WPhys_RunThink (world_t *w, wedict_t *ent)
*w->g.time = thinktime;
w->Event_Think(w, ent);
if (ent->isfree)
if (ED_ISFREE(ent))
return false;
if (ent->v->nextthink <= thinktime) //hmm... infinate loop was possible here.. Quite a few non-QW mods do this.
@ -465,7 +465,7 @@ static int WPhys_FlyMove (world_t *w, wedict_t *ent, const vec3_t gravitydir, fl
// run the impact function
//
WPhys_Impact (w, ent, &trace);
if (ent->isfree)
if (ED_ISFREE(ent))
break; // removed by the impact function
@ -698,7 +698,7 @@ static qboolean WPhys_PushAngles (world_t *w, wedict_t *pusher, vec3_t move, vec
for (e = 1; e < w->num_edicts; e++)
{
check = WEDICT_NUM(w->progs, e);
if (check->isfree)
if (ED_ISFREE(check))
continue;
if (check->v->movetype == MOVETYPE_PUSH
@ -891,7 +891,7 @@ static qboolean WPhys_Push (world_t *w, wedict_t *pusher, vec3_t move, vec3_t am
for (e=1 ; e<w->num_edicts ; e++)
{
check = WEDICT_NUM(w->progs, e);
if (check->isfree)
if (ED_ISFREE(check))
continue;
if (check->v->movetype == MOVETYPE_PUSH
|| check->v->movetype == MOVETYPE_NONE
@ -1109,7 +1109,7 @@ VectorCopy (ent->v->angles, oldang);
#endif
PR_ExecuteProgram (svprogfuncs, ent->v->think);
#endif
if (ent->isfree)
if (ED_ISFREE(ent))
return;
VectorSubtract (ent->v->origin, oldorg, move);
VectorSubtract (ent->v->angles, oldang, amove);
@ -1316,7 +1316,7 @@ static void WPhys_Physics_Toss (world_t *w, wedict_t *ent)
{
wedict_t *onent;
onent = PROG_TO_WEDICT(w->progs, ent->v->groundentity);
if (!onent->isfree)
if (!ED_ISFREE(onent))
return; //don't drop if our fround is still valid
}
else
@ -1365,7 +1365,7 @@ static void WPhys_Physics_Toss (world_t *w, wedict_t *ent)
}
if (trace.fraction == 1)
return;
if (ent->isfree)
if (ED_ISFREE(ent))
return;
VectorCopy(trace.endpos, move);
@ -2017,7 +2017,7 @@ void WPhys_MoveChain(world_t *w, wedict_t *ent, wedict_t *movechain, float *init
VectorSubtract(ent->v->angles, initial_angle, moveang);
VectorSubtract(ent->v->origin, initial_origin, moveorg);
for(i=16;i && movechain != w->edicts && !movechain->isfree;i--, movechain = PROG_TO_WEDICT(w->progs, movechain->xv->movechain))
for(i=16;i && movechain != w->edicts && !ED_ISFREE(movechain);i--, movechain = PROG_TO_WEDICT(w->progs, movechain->xv->movechain))
{
if ((int)movechain->v->flags & FL_MOVECHAIN_ANGLE)
VectorAdd(movechain->v->angles, moveang, movechain->v->angles); //FIXME: axial only
@ -2319,7 +2319,7 @@ void World_Physics_Frame(world_t *w)
for (i=0 ; i<w->num_edicts ; i++)
{
ent = (wedict_t*)EDICT_NUM(w->progs, i);
if (ent->isfree)
if (ED_ISFREE(ent))
continue;
WPhys_RunThink (w, ent);
@ -2337,7 +2337,7 @@ void World_Physics_Frame(world_t *w)
for (i=0 ; i<w->num_edicts ; i++)
{
ent = (wedict_t*)EDICT_NUM(w->progs, i);
if (ent->isfree)
if (ED_ISFREE(ent))
continue;
if (retouch)

View file

@ -6309,7 +6309,7 @@ void AddAllEntsToPmove (edict_t *player)
for (e=1 ; e<sv.world.num_edicts ; e++)
{
check = EDICT_NUM(svprogfuncs, e);
if (check->isfree)
if (ED_ISFREE(check))
continue;
if (check->v->owner == pl)
continue;
@ -6993,7 +6993,7 @@ if (sv_player->v->health > 0 && before && !after )
sv.world.Event_Touch(&sv.world, (wedict_t*)ent, (wedict_t*)sv_player);
}
if (sv_player->v->touch && !ent->isfree)
if (sv_player->v->touch && !ED_ISFREE(ent))
sv.world.Event_Touch(&sv.world, (wedict_t*)sv_player, (wedict_t*)ent);
}
}
@ -7095,7 +7095,7 @@ void SV_ReadPrydonCursor(void)
}
// as requested by FrikaC, cursor_trace_ent is reset to world if the
// entity is free at time of receipt
if (!svprogfuncs || EDICT_NUM(svprogfuncs, entnum)->isfree)
if (!svprogfuncs || ED_ISFREE(EDICT_NUM(svprogfuncs, entnum)))
entnum = 0;
if (msg_badread) Con_Printf("SV_ReadPrydonCursor: badread at %s:%i\n", __FILE__, __LINE__);

View file

@ -355,7 +355,7 @@ void World_TouchLinks (world_t *w, wedict_t *ent, areanode_t *node)
touch = nodelinks[ln];
//make sure nothing moved it away
if (touch->isfree)
if (ED_ISFREE(touch))
continue;
if (!touch->v->touch || touch->v->solid != SOLID_TRIGGER)
continue;
@ -373,13 +373,13 @@ void World_TouchLinks (world_t *w, wedict_t *ent, areanode_t *node)
w->Event_Touch(w, touch, ent);
if (ent->isfree)
if (ED_ISFREE(ent))
break;
}
// recurse down both sides
if (node->axis == -1 || ent->isfree)
if (node->axis == -1 || ED_ISFREE(ent))
return;
if (ent->v->absmax[node->axis] > node->dist)
@ -474,7 +474,7 @@ void QDECL World_LinkEdict (world_t *w, wedict_t *ent, qboolean touch_triggers)
if (ent == w->edicts)
return; // don't add the world
if (ent->isfree)
if (ED_ISFREE(ent))
return;
// set the abs box
@ -1538,8 +1538,8 @@ static void World_ClipToEverything (world_t *w, moveclip_t *clip)
{
touch = (wedict_t*)EDICT_NUM(w->progs, e);
if (touch->isfree)
continue;
if (ED_ISFREE(touch))
continue;
if (touch->v->solid == SOLID_NOT && !((int)touch->v->flags & FL_FINDABLE_NONSOLID))
continue;
if (touch->v->solid == SOLID_TRIGGER && !((int)touch->v->flags & FL_FINDABLE_NONSOLID))
@ -2139,7 +2139,7 @@ void World_RBE_Shutdown(world_t *world)
void QDECL World_UnregisterPhysicsEngine(const char *enginename)
{
#ifdef RAGDOLL
// rag_uninstanciateall();
rag_uninstanciateall();
#endif
#if defined(CSQC_DAT) && !defined(SERVERONLY)

View file

@ -36,6 +36,9 @@ extern cvar_t r_portalrecursion;
extern cvar_t r_polygonoffset_shadowmap_offset, r_polygonoffset_shadowmap_factor;
extern cvar_t r_wireframe;
extern cvar_t vk_stagingbuffers;
unsigned int vk_usedynamicstaging;
static void VK_TerminateShadowMap(void);
void VKBE_BeginShadowmapFace(void);
@ -629,6 +632,7 @@ static const char LIGHTPASS_SHADER[] = "\
void VKBE_Init(void)
{
int i;
char *c;
sh_config.pDeleteProg = VKBE_DeleteProg;
@ -713,6 +717,29 @@ void VKBE_Init(void)
}
shaderstate.staticbuf = VKBE_FinishStaging(&lazybuf, &shaderstate.staticbufmem);
}
c = vk_stagingbuffers.string;
if (*c)
{
vk_usedynamicstaging = 0;
while (*c)
{
if (*c == 'u')
vk_usedynamicstaging |= 1u<<DB_UBO;
else if (*c == 'e' || *c == 'i')
vk_usedynamicstaging |= 1u<<DB_EBO;
else if (*c == 'v')
vk_usedynamicstaging |= 1u<<DB_VBO;
else if (*c == '0')
vk_usedynamicstaging |= 0; //for explicly none.
else
Con_Printf("%s: unknown char %c\n", vk_stagingbuffers.string, *c);
c++;
}
}
else
vk_usedynamicstaging = ~0u;
}
static struct descpool *VKBE_CreateDescriptorPool(void)
@ -769,29 +796,37 @@ static struct dynbuffer *VKBE_AllocNewBuffer(struct dynbuffer **link, enum dynbu
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
struct dynbuffer *n = Z_Malloc(sizeof(*n));
bufinf.flags = 0;
bufinf.size = n->size = (1u<<20);
bufinf.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
bufinf.queueFamilyIndexCount = 0;
bufinf.pQueueFamilyIndices = NULL;
#ifdef USE_DYNAMIC_STAGING
bufinf.usage = ufl[type]|VK_BUFFER_USAGE_TRANSFER_DST_BIT;
vkCreateBuffer(vk.device, &bufinf, vkallocationcb, &n->devicebuf);
bufinf.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
vkCreateBuffer(vk.device, &bufinf, vkallocationcb, &n->stagingbuf);
bufinf.flags = 0;
bufinf.size = n->size = (1u<<20);
bufinf.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
bufinf.queueFamilyIndexCount = 0;
bufinf.pQueueFamilyIndices = NULL;
vkGetBufferMemoryRequirements(vk.device, n->devicebuf, &mem_reqs);
n->align = mem_reqs.alignment-1;
memAllocInfo.allocationSize = mem_reqs.size;
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
if (memAllocInfo.memoryTypeIndex == ~0)
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0); //device will still be okay with this usage...
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &n->devicememory));
VkAssert(vkBindBufferMemory(vk.device, n->devicebuf, n->devicememory, 0));
#else
bufinf.usage = ufl[type];
vkCreateBuffer(vk.device, &bufinf, vkallocationcb, &n->stagingbuf);
#endif
if (vk_usedynamicstaging & (1u<<type))
{
bufinf.usage = ufl[type]|VK_BUFFER_USAGE_TRANSFER_DST_BIT;
vkCreateBuffer(vk.device, &bufinf, vkallocationcb, &n->devicebuf);
bufinf.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
vkCreateBuffer(vk.device, &bufinf, vkallocationcb, &n->stagingbuf);
vkGetBufferMemoryRequirements(vk.device, n->devicebuf, &mem_reqs);
n->align = mem_reqs.alignment-1;
memAllocInfo.allocationSize = mem_reqs.size;
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
if (memAllocInfo.memoryTypeIndex == ~0)
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0); //device will still be okay with this usage...
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &n->devicememory));
VkAssert(vkBindBufferMemory(vk.device, n->devicebuf, n->devicememory, 0));
n->renderbuf = n->devicebuf;
}
else
{
bufinf.usage = ufl[type];
vkCreateBuffer(vk.device, &bufinf, vkallocationcb, &n->stagingbuf);
n->renderbuf = n->stagingbuf;
}
vkGetBufferMemoryRequirements(vk.device, n->stagingbuf, &mem_reqs);
n->align = mem_reqs.alignment-1;
@ -827,17 +862,16 @@ static void *fte_restrict VKBE_AllocateBufferSpace(enum dynbuf_e type, size_t da
range.memory = b->stagingmemory;
vkFlushMappedMemoryRanges(vk.device, 1, &range);
#ifdef USE_DYNAMIC_STAGING
if (b->devicebuf != VK_NULL_HANDLE)
{
VkCommandBuffer cb = VK_FencedBegin();
struct vk_fencework *fence = VK_FencedBegin(NULL, 0);
VkBufferCopy bcr = {0};
bcr.srcOffset = 0;
bcr.dstOffset = 0;
bcr.size = b->offset;
vkCmdCopyBuffer(cb, b->stagingbuf, b->devicebuf, 1, &bcr);
VK_FencedSubmit(cb, NULL, 0);
vkCmdCopyBuffer(fence->cbuf, b->stagingbuf, b->devicebuf, 1, &bcr);
VK_FencedSubmit(fence);
}
#endif
if (!b->next)
VKBE_AllocNewBuffer(&b->next, type);
@ -845,11 +879,7 @@ static void *fte_restrict VKBE_AllocateBufferSpace(enum dynbuf_e type, size_t da
b->offset = 0;
}
#ifdef USE_DYNAMIC_STAGING
*buf = b->devicebuf;
#else
*buf = b->stagingbuf;
#endif
*buf = b->renderbuf;
*offset = b->offset;
ret = (qbyte*)b->ptr + b->offset;
@ -895,12 +925,9 @@ void VKBE_InitFramePools(struct vkframe *frame)
//called just before submits
//makes sure that our persistent-mapped memory writes can actually be seen by the hardware.
#ifdef USE_DYNAMIC_STAGING
void VKBE_FlushDynamicBuffers(VkCommandBuffer cb)
#else
void VKBE_FlushDynamicBuffers(void)
#endif
{
struct vk_fencework *fence = NULL;
uint32_t i;
struct dynbuffer *d;
VkMappedMemoryRange range = {VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE};
@ -916,16 +943,20 @@ void VKBE_FlushDynamicBuffers(void)
range.memory = d->stagingmemory;
vkFlushMappedMemoryRanges(vk.device, 1, &range);
#ifdef USE_DYNAMIC_STAGING
if (d->devicebuf != VK_NULL_HANDLE)
{
VkBufferCopy bcr = {0};
bcr.srcOffset = 0;
bcr.dstOffset = 0;
bcr.size = d->offset;
vkCmdCopyBuffer(cb, d->stagingbuf, d->devicebuf, 1, &bcr);
if (!fence)
fence = VK_FencedBegin(NULL, 0);
vkCmdCopyBuffer(fence->cbuf, d->stagingbuf, d->devicebuf, 1, &bcr);
}
#endif
}
if (fence)
VK_FencedSubmit(fence);
}
void VKBE_Set2D(qboolean twodee)
@ -966,10 +997,11 @@ void VKBE_ShutdownFramePools(struct vkframe *frame)
db = frame->dynbufs[i];
vkDestroyBuffer(vk.device, db->stagingbuf, vkallocationcb);
vkFreeMemory(vk.device, db->stagingmemory, vkallocationcb);
#ifdef USE_DYNAMIC_STAGING
vkDestroyBuffer(vk.device, db->devicebuf, vkallocationcb);
vkFreeMemory(vk.device, db->devicememory, vkallocationcb);
#endif
if (db->devicebuf != VK_NULL_HANDLE)
{
vkDestroyBuffer(vk.device, db->devicebuf, vkallocationcb);
vkFreeMemory(vk.device, db->devicememory, vkallocationcb);
}
frame->dynbufs[i] = db->next;
Z_Free(db);
}
@ -2049,8 +2081,17 @@ static void BE_CreatePipeline(program_t *p, unsigned int shaderflags, unsigned i
pipe = Z_Malloc(sizeof(*pipe));
pipe->next = p->pipelines;
p->pipelines = pipe;
if (!p->pipelines)
p->pipelines = pipe;
else
{ //insert at end. if it took us a while to realise that we needed it, chances are its not that common.
//so don't cause the other pipelines to waste cycles for it.
struct pipeline_s *prev;
for (prev = p->pipelines; ; prev = prev->next)
if (!prev->next)
break;
prev->next = pipe;
}
pipe->flags = shaderflags;
pipe->blendbits = blendflags;

View file

@ -5,6 +5,7 @@
#include "shader.h"
#include "renderque.h" //is anything still using this?
extern qboolean vid_isfullscreen;
extern cvar_t vk_submissionthread;
extern cvar_t vk_debug;
extern cvar_t vid_srgb, vid_vsync, vid_triplebuffer, r_stereo_method;
@ -281,7 +282,7 @@ static qboolean VK_CreateSwapChain(void)
swapinfo.queueFamilyIndexCount = 0;
swapinfo.pQueueFamilyIndices = NULL;
swapinfo.oldSwapchain = vk.swapchain;
swapinfo.clipped = 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.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.
for (i = 0, curpri = 0; i < presentmodes; i++)
@ -376,7 +377,7 @@ static qboolean VK_CreateSwapChain(void)
VkAssert(vkCreateFence(vk.device,&fci,vkallocationcb,&vk.acquirefences[i]));
}
/*-1 to hide any weird thread issues*/
while (vk.aquirelast < ACQUIRELIMIT-1 && vk.aquirelast < vk.backbuf_count && vk.aquirelast <= vk.backbuf_count-surfcaps.minImageCount)
while (vk.aquirelast < ACQUIRELIMIT-1 && vk.aquirelast < vk.backbuf_count && vk.aquirelast < 2 && vk.aquirelast <= vk.backbuf_count-surfcaps.minImageCount)
{
VkAssert(vkAcquireNextImageKHR(vk.device, vk.swapchain, UINT64_MAX, VK_NULL_HANDLE, vk.acquirefences[vk.aquirelast%ACQUIRELIMIT], &vk.acquirebufferidx[vk.aquirelast%ACQUIRELIMIT]));
vk.aquirelast++;
@ -593,8 +594,6 @@ vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t lay
format = VK_FORMAT_R5G5B5A1_UNORM_PACK16;
else if (encoding == PTI_ARGB1555)
format = VK_FORMAT_A1R5G5B5_UNORM_PACK16;
else if (encoding == PTI_ARGB1555)
format = VK_FORMAT_A1R5G5B5_UNORM_PACK16;
//float formats
else if (encoding == PTI_RGBA16F)
format = VK_FORMAT_R16G16B16A16_SFLOAT;
@ -893,6 +892,7 @@ qboolean VK_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips)
blocksize = 1;
blockbytes = 2;
break;
default:
return false;
}
@ -1746,7 +1746,7 @@ qboolean VK_SCR_GrabBackBuffer(void)
}
//wait for the queued acquire to actually finish
if (1)//vk.vsync)
if (vk.vsync)
{
//friendly wait
VkAssert(vkWaitForFences(vk.device, 1, &vk.acquirefences[vk.aquirenext%ACQUIRELIMIT], VK_FALSE, UINT64_MAX));
@ -2033,14 +2033,7 @@ qboolean VK_SCR_UpdateScreen (void)
{
RSpeedRemark();
#ifdef USE_DYNAMIC_STAGING
bufs[0] = VK_FencedBegin();
VKBE_FlushDynamicBuffers(bufs[0]);
VK_FencedSubmit(bufs[0], NULL, 0);
#else
VKBE_FlushDynamicBuffers();
#endif
RSpeedEnd(RSPEED_SUBMIT);
}
@ -2255,6 +2248,8 @@ static void VK_Submit_DoWork(void)
Sys_LockMutex(vk.swapchain_mutex);
err = vkQueuePresentKHR(vk.queue_present, &presinfo);
Sys_UnlockMutex(vk.swapchain_mutex);
RSpeedEnd(RSPEED_PRESENT);
RSpeedRemark();
if (err)
{
Con_Printf("ERROR: vkQueuePresentKHR: %x\n", err);
@ -2263,7 +2258,7 @@ static void VK_Submit_DoWork(void)
#ifdef THREADACQUIRE
else
{
err = vkAcquireNextImageKHR(vk.device, vk.swapchain, UINT64_MAX, VK_NULL_HANDLE, vk.acquirefences[vk.aquirelast%ACQUIRELIMIT], &vk.acquirebufferidx[vk.aquirelast%ACQUIRELIMIT]);
err = vkAcquireNextImageKHR(vk.device, vk.swapchain, 0, VK_NULL_HANDLE, vk.acquirefences[vk.aquirelast%ACQUIRELIMIT], &vk.acquirebufferidx[vk.aquirelast%ACQUIRELIMIT]);
if (err)
{
Con_Printf("ERROR: vkAcquireNextImageKHR: %x\n", err);
@ -2272,7 +2267,7 @@ static void VK_Submit_DoWork(void)
vk.aquirelast++;
}
#endif
RSpeedEnd(RSPEED_PRESENT);
RSpeedEnd(RSPEED_ACQUIRE);
}
}
@ -2336,6 +2331,56 @@ void VK_Submit_Work(VkCommandBuffer cmdbuf, VkSemaphore semwait, VkPipelineStage
Sys_UnlockConditional(vk.submitcondition);
}
void VK_CheckTextureFormats(void)
{
struct {
unsigned int pti;
VkFormat vulkan;
unsigned int needextra;
} texfmt[] =
{
{PTI_RGBA8, VK_FORMAT_R8G8B8A8_UNORM},
{PTI_RGBX8, VK_FORMAT_R8G8B8A8_UNORM},
{PTI_BGRA8, VK_FORMAT_B8G8R8A8_UNORM},
{PTI_BGRX8, VK_FORMAT_B8G8R8A8_UNORM},
{PTI_RGB565, VK_FORMAT_R5G6B5_UNORM_PACK16},
{PTI_RGBA4444, VK_FORMAT_R4G4B4A4_UNORM_PACK16},
{PTI_ARGB4444, VK_FORMAT_B4G4R4A4_UNORM_PACK16},
{PTI_RGBA5551, VK_FORMAT_R5G5B5A1_UNORM_PACK16},
{PTI_ARGB1555, VK_FORMAT_A1R5G5B5_UNORM_PACK16},
{PTI_RGBA16F, VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT|VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT},
{PTI_RGBA32F, VK_FORMAT_R32G32B32A32_SFLOAT, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT|VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT},
{PTI_R8, VK_FORMAT_R8_UNORM},
{PTI_RG8, VK_FORMAT_R8G8_UNORM},
{PTI_DEPTH16, VK_FORMAT_D16_UNORM, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT},
{PTI_DEPTH24, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT},
{PTI_DEPTH32, VK_FORMAT_D32_SFLOAT, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT},
{PTI_DEPTH24_8, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT},
{PTI_S3RGB1, VK_FORMAT_BC1_RGB_UNORM_BLOCK},
{PTI_S3RGBA1, VK_FORMAT_BC1_RGBA_UNORM_BLOCK},
{PTI_S3RGBA3, VK_FORMAT_BC2_UNORM_BLOCK},
{PTI_S3RGBA5, VK_FORMAT_BC3_UNORM_BLOCK},
};
unsigned int i;
VkPhysicalDeviceProperties props;
vkGetPhysicalDeviceProperties(vk.gpu, &props);
sh_config.texture_maxsize = props.limits.maxImageDimension2D;
for (i = 0; i < countof(texfmt); i++)
{
unsigned int need = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | texfmt[i].needextra;
VkFormatProperties fmt;
vkGetPhysicalDeviceFormatProperties(vk.gpu, texfmt[i].vulkan, &fmt);
if ((fmt.optimalTilingFeatures & need) == need)
sh_config.texfmt[texfmt[i].pti] = true;
}
}
//initialise the vulkan instance, context, device, etc.
qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*createSurface)(void))
{
@ -2356,6 +2401,7 @@ qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*creat
vk.neednewswapchain = true;
vk.triplebuffer = info->triplebuffer;
vk.vsync = info->wait;
memset(&sh_config, 0, sizeof(sh_config));
//get second set of pointers...
@ -2492,6 +2538,58 @@ qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*creat
}
}
{
char *vendor, *type;
VkPhysicalDeviceProperties props;
vkGetPhysicalDeviceProperties(vk.gpu, &props);
switch(props.vendorID)
{
//explicit vendors
case 0x10001: vendor = "Vivante"; break;
case 0x10002: vendor = "VeriSilicon"; break;
//pci vendor ids
//there's a lot of pci vendors, some even still exist, but not all of them actually have 3d hardware.
//many of these probably won't even be used... Oh well.
//anyway, here's some of the ones that are listed
case 0x1002: vendor = "AMD"; break;
case 0x10DE: vendor = "NVIDIA"; break;
case 0x8086: vendor = "Intel"; break; //cute
case 0x13B5: vendor = "ARM"; break;
case 0x5143: vendor = "Qualcomm"; break;
case 0x1AEE: vendor = "Imagination";break;
case 0x1957: vendor = "Freescale"; break;
case 0x1AE0: vendor = "Google"; break;
case 0x5333: vendor = "S3"; break;
case 0xA200: vendor = "NEC"; break;
case 0x0A5C: vendor = "Broadcom"; break;
case 0x1131: vendor = "NXP"; break;
case 0x1099: vendor = "Samsung"; break;
case 0x10C3: vendor = "Samsung"; break;
case 0x11E2: vendor = "Samsung"; break;
case 0x1249: vendor = "Samsung"; break;
default: vendor = va("VEND_%x", props.vendorID); break;
}
switch(props.deviceType)
{
default:
case VK_PHYSICAL_DEVICE_TYPE_OTHER: type = "(other)"; break;
case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: type = "integrated"; break;
case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: type = "discrete"; break;
case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: type = "virtual"; break;
case VK_PHYSICAL_DEVICE_TYPE_CPU: type = "software"; break;
}
Con_Printf("Vulkan %u.%u.%u: %s %s %s (%u.%u.%u)\n", VK_VERSION_MAJOR(props.apiVersion), VK_VERSION_MINOR(props.apiVersion), VK_VERSION_PATCH(props.apiVersion),
type, vendor, props.deviceName,
VK_VERSION_MAJOR(props.driverVersion), VK_VERSION_MINOR(props.driverVersion), VK_VERSION_PATCH(props.driverVersion)
);
}
//create the platform-specific surface
createSurface();
@ -2591,17 +2689,7 @@ qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*creat
VkAssert(vkCreateCommandPool(vk.device, &cpci, vkallocationcb, &vk.cmdpool));
}
vk.depthformat = VK_FORMAT_D32_SFLOAT;//VK_FORMAT_D32_SFLOAT_S8_UINT;//VK_FORMAT_D24_UNORM_S8_UINT;//VK_FORMAT_D16_UNORM;
#ifndef THREADACQUIRE
{
VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};
VkAssert(vkCreateFence(vk.device,&fci,vkallocationcb,&vk.acquirefence));
}
#endif
memset(&sh_config, 0, sizeof(sh_config));
sh_config.progpath = NULL;//"vulkan";
sh_config.blobpath = "spirv";
sh_config.shadernamefmt = NULL;//".spv";
@ -2611,35 +2699,6 @@ qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*creat
sh_config.minver = -1;
sh_config.maxver = -1;
//depth formats need to support attachments
//other formats might be supported for staging
sh_config.texfmt[PTI_RGBA8] = true;
sh_config.texfmt[PTI_RGBX8] = true;
sh_config.texfmt[PTI_BGRA8] = true;
sh_config.texfmt[PTI_BGRX8] = true;
sh_config.texfmt[PTI_RGB565] = true;
// sh_config.texfmt[PTI_RGBA4444] = true; //FIXME: other formats
// sh_config.texfmt[PTI_ARGB4444] = true; //FIXME: other formats
// sh_config.texfmt[PTI_RGBA5551] = true; //FIXME: other formats
// sh_config.texfmt[PTI_ARGB1555] = true; //FIXME: other formats
sh_config.texfmt[PTI_RGBA16F] = true;
// sh_config.texfmt[PTI_RGBA32F] = true;
sh_config.texfmt[PTI_R8] = true; //FIXME: other formats
sh_config.texfmt[PTI_RG8] = true; //FIXME: other formats
// sh_config.texfmt[PTI_S3RGB1] = true; //FIXME: other formats
// sh_config.texfmt[PTI_S3RGBA1] = true; //FIXME: other formats
// sh_config.texfmt[PTI_S3RGBA3] = true; //FIXME: other formats
// sh_config.texfmt[PTI_S3RGBA5] = true; //FIXME: other formats
sh_config.texfmt[PTI_DEPTH16] = true; //guarenteed, supposedly.
// sh_config.texfmt[PTI_DEPTH24] = true; //FIXME: other formats
// sh_config.texfmt[PTI_DEPTH32] = true; //FIXME: other formats
// sh_config.texfmt[PTI_DEPTH24_8] = true; //FIXME: other formats
sh_config.texfmt[PTI_S3RGB1] = true;
sh_config.texfmt[PTI_S3RGBA1] = true;
sh_config.texfmt[PTI_S3RGBA3] = true;
sh_config.texfmt[PTI_S3RGBA5] = true;
sh_config.texture_maxsize = 4096; //must be at least 4096, FIXME: query this properly
sh_config.texture_non_power_of_two = true; //is this always true?
sh_config.texture_non_power_of_two_pic = true; //probably true...
@ -2648,12 +2707,33 @@ qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*creat
sh_config.nv_tex_env_combine4 = false; //fixme: figure out what this means...
sh_config.env_add = false; //fixme: figure out what this means...
sh_config.can_mipcap = true;
VK_CheckTextureFormats();
sh_config.pDeleteProg = NULL;
sh_config.pLoadBlob = NULL;
sh_config.pCreateProgram = NULL;
sh_config.pValidateProgram = NULL;
sh_config.pProgAutoFields = NULL;
if (sh_config.texfmt[PTI_DEPTH32])
vk.depthformat = VK_FORMAT_D32_SFLOAT;
else if (sh_config.texfmt[PTI_DEPTH24])
vk.depthformat = VK_FORMAT_X8_D24_UNORM_PACK32;
else if (sh_config.texfmt[PTI_DEPTH24_8])
vk.depthformat = VK_FORMAT_D24_UNORM_S8_UINT;
else //16bit depth is guarenteed in vulkan
vk.depthformat = VK_FORMAT_D16_UNORM;
#ifndef THREADACQUIRE
{
VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};
VkAssert(vkCreateFence(vk.device,&fci,vkallocationcb,&vk.acquirefence));
}
#endif
/*
void (*pDeleteProg) (program_t *prog, unsigned int permu);
qboolean (*pLoadBlob) (program_t *prog, const char *name, unsigned int permu, vfsfile_t *blobfile);

View file

@ -18,8 +18,7 @@
#define UINT64_MAX _UI64_MAX
#endif
//#define USE_DYNAMIC_STAGING //seems faster to not bother on nvidia. plus all other vendors seem to have host|device heaps
#define THREADACQUIRE //should be better controlled
#define THREADACQUIRE //should be better behaved, with no extra locks needed.
@ -48,6 +47,7 @@
VKFunc(GetPhysicalDeviceSurfacePresentModesKHR) \
VKFunc(GetPhysicalDeviceSurfaceCapabilitiesKHR) \
VKFunc(GetPhysicalDeviceMemoryProperties) \
VKFunc(GetPhysicalDeviceFormatProperties) \
VKFunc(DestroySurfaceKHR) \
VKFunc(CreateDevice) \
VKFunc(DestroyInstance) \
@ -257,10 +257,9 @@ extern struct vulkaninfo_s
size_t align;
VkBuffer stagingbuf;
VkDeviceMemory stagingmemory;
#ifdef USE_DYNAMIC_STAGING
VkBuffer devicebuf;
VkDeviceMemory devicememory;
#endif
VkBuffer renderbuf; //either staging or device.
void *ptr;
struct dynbuffer *next;
@ -337,11 +336,7 @@ void VK_Shutdown(void);
void VKBE_Init(void);
void VKBE_InitFramePools(struct vkframe *frame);
void VKBE_RestartFrame(void);
#ifdef USE_DYNAMIC_STAGING
void VKBE_FlushDynamicBuffers(VkCommandBuffer buf);
#else
void VKBE_FlushDynamicBuffers(void);
#endif
void VKBE_Set2D(qboolean twodee);
void VKBE_ShutdownFramePools(struct vkframe *frame);
void VKBE_Shutdown(void);

View file

@ -305,7 +305,7 @@ void INS_Accumulate(void)
void INS_Commands (void)
{
}
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, int *qdevid))
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, unsigned int *qdevid))
{
}