vulkan: fixed anisotropy
vulkan: fixed msaa vulkan: fixed some validation errors input: fixed bug with mwheel etc failing to register screenshot_360: default to vid width/height instead of assuming a megascreeny images: reworked Image_ResampleTexture to handle image formats in a more generic way console: toggle command now accepts two args to toggle the cvar between skyrooms: fixed a couple of bugs. x11-egl: should actually work now wayland: fixed up some omissions. still needs more work but should at least be somewhat tolerable now. server: be a little more friendly towards ktx server: added sv_use_dns cvar, to report reverse-dns instead of ip addresses. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5491 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
f75beaff81
commit
e0fe3c8dec
45 changed files with 1966 additions and 684 deletions
|
@ -810,7 +810,7 @@ void CL_GatherButtons (usercmd_t *cmd, int pnum)
|
|||
GATHERBIT(in_button[14-3], 16);
|
||||
GATHERBIT(in_button[15-3], 17);
|
||||
GATHERBIT(in_button[16-3], 18);
|
||||
cmd->buttons = bits;
|
||||
cmd->buttons |= bits;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1331,6 +1331,7 @@ void CLNQ_SendCmd(sizebuf_t *buf)
|
|||
#ifdef CSQC_DAT
|
||||
CSQC_Input_Frame(seat, cmd);
|
||||
#endif
|
||||
memset(&cl_pendingcmd[seat], 0, sizeof(cl_pendingcmd[seat]));
|
||||
}
|
||||
|
||||
//inputs are only sent once we receive an entity.
|
||||
|
|
|
@ -203,19 +203,20 @@ cvar_t cl_dlemptyterminate = CVAR("cl_dlemptyterminate", "1");
|
|||
cvar_t host_mapname = CVARAF("mapname", "",
|
||||
"host_mapname", 0);
|
||||
|
||||
cvar_t ruleset_allow_playercount = CVAR("ruleset_allow_playercount", "1");
|
||||
cvar_t ruleset_allow_frj = CVAR("ruleset_allow_frj", "1");
|
||||
cvar_t ruleset_allow_semicheats = CVAR("ruleset_allow_semicheats", "1");
|
||||
cvar_t ruleset_allow_packet = CVAR("ruleset_allow_packet", "1");
|
||||
cvar_t ruleset_allow_particle_lightning = CVAR("ruleset_allow_particle_lightning", "1");
|
||||
cvar_t ruleset_allow_overlongsounds = CVAR("ruleset_allow_overlong_sounds", "1");
|
||||
cvar_t ruleset_allow_larger_models = CVAR("ruleset_allow_larger_models", "1");
|
||||
cvar_t ruleset_allow_modified_eyes = CVAR("ruleset_allow_modified_eyes", "0");
|
||||
cvar_t ruleset_allow_sensitive_texture_replacements = CVAR("ruleset_allow_sensitive_texture_replacements", "1");
|
||||
cvar_t ruleset_allow_localvolume = CVAR("ruleset_allow_localvolume", "1");
|
||||
cvar_t ruleset_allow_shaders = CVARF("ruleset_allow_shaders", "1", CVAR_SHADERSYSTEM);
|
||||
cvar_t ruleset_allow_watervis = CVARF("ruleset_allow_watervis", "1", CVAR_SHADERSYSTEM);
|
||||
cvar_t ruleset_allow_fbmodels = CVARF("ruleset_allow_fbmodels", "0", CVAR_SHADERSYSTEM);
|
||||
#define RULESETADVICE " You should not normally change this cvar from its permissive default, instead impose limits on yourself only through the 'ruleset' cvar."
|
||||
cvar_t ruleset_allow_playercount = CVARD("ruleset_allow_playercount", "1", "Specifies whether teamplay triggers that count nearby players are allowed in the current ruleset."RULESETADVICE);
|
||||
cvar_t ruleset_allow_frj = CVARD("ruleset_allow_frj", "1", "Specifies whether Forward-Rocket-Jump scripts are allowed in the current ruleset. If 0, limits on yaw speed will be imposed so they cannot be scripted."RULESETADVICE);
|
||||
cvar_t ruleset_allow_semicheats = CVARD("ruleset_allow_semicheats", "1", "If 0, this blocks a range of cvars that are marked as semi-cheats. Such cvars will be locked to their empty/0 value."RULESETADVICE);
|
||||
cvar_t ruleset_allow_packet = CVARD("ruleset_allow_packet", "1", "If 0, network packets sent via the 'packet' command will be blocked. This makes scripting timers a little harder."RULESETADVICE);
|
||||
cvar_t ruleset_allow_particle_lightning = CVARD("ruleset_allow_particle_lightning", "1", "A setting of 0 blocks using the particle system to replace lightning gun trails. This prevents making the trails thinner thus preventing them from obscuring your view of your enemies."RULESETADVICE);
|
||||
cvar_t ruleset_allow_overlongsounds = CVARD("ruleset_allow_overlong_sounds", "1", "A setting of 0 will block the use of extra-long pickup sounds as item respawn timers."RULESETADVICE);
|
||||
cvar_t ruleset_allow_larger_models = CVARD("ruleset_allow_larger_models", "1", "Enforces a maximum bounds limit on models, to prevent the use of additional spikes attached to the model from being used as a kind of wallhack."RULESETADVICE);
|
||||
cvar_t ruleset_allow_modified_eyes = CVARD("ruleset_allow_modified_eyes", "0", "When 0, completely hides progs/eyes.mdl if it is not strictly identical to vanilla quake."RULESETADVICE);
|
||||
cvar_t ruleset_allow_sensitive_texture_replacements = CVARD("ruleset_allow_sensitive_texture_replacements", "1", "Allows the replacement of certain model textures (as well as the models themselves). This prevents adding extra fullbrights to make them blatently obvious."RULESETADVICE);
|
||||
cvar_t ruleset_allow_localvolume = CVARD("ruleset_allow_localvolume", "1", "Allows the use of the snd_playersoundvolume cvar. Muting your own sounds can make it easier to hear where your opponent is."RULESETADVICE);
|
||||
cvar_t ruleset_allow_shaders = CVARFD("ruleset_allow_shaders", "1", CVAR_SHADERSYSTEM, "When 0, this completely disables the use of external shader files, preventing custom shaders from being used for wallhacks."RULESETADVICE);
|
||||
cvar_t ruleset_allow_watervis = CVARFD("ruleset_allow_watervis", "1", CVAR_SHADERSYSTEM, "When 0, this enforces ugly opaque water."RULESETADVICE);
|
||||
cvar_t ruleset_allow_fbmodels = CVARFD("ruleset_allow_fbmodels", "0", CVAR_SHADERSYSTEM, "When 1, allows all models to be displayed fullbright, completely ignoring the lightmaps. This feature exists only for parity with ezquake's defaults."RULESETADVICE);
|
||||
|
||||
extern cvar_t cl_hightrack;
|
||||
extern cvar_t vid_renderer;
|
||||
|
@ -4247,7 +4248,10 @@ void CL_ServerInfo_f(void)
|
|||
if (!sv.state && cls.state && Cmd_Argc() < 2)
|
||||
{
|
||||
if (cl.haveserverinfo)
|
||||
{
|
||||
InfoBuf_Print (&cl.serverinfo, "");
|
||||
Con_Printf("[%u, %s]\n", (unsigned int)cl.serverinfo.totalsize, cls.servername);
|
||||
}
|
||||
else
|
||||
Cmd_ForwardToServer ();
|
||||
}
|
||||
|
|
|
@ -2572,6 +2572,15 @@ static void SCR_ScreenShot_Mega_f(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (strcmp(Cmd_Argv(0), "screenshot_mega"))
|
||||
{ //screenshot_360, screenshot_stereo etc probably don't want to capture mega screenshots
|
||||
//so default to something more realistic instead.
|
||||
if (!fbwidth)
|
||||
fbwidth = vid.pixelwidth;
|
||||
if (!fbheight)
|
||||
fbheight = vid.pixelheight;
|
||||
}
|
||||
|
||||
if (!fbwidth)
|
||||
fbwidth = sh_config.texture2d_maxsize;
|
||||
fbwidth = bound(1, fbwidth, sh_config.texture2d_maxsize);
|
||||
|
|
|
@ -789,7 +789,7 @@ qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, uploadfmt_
|
|||
return NULL;
|
||||
}
|
||||
|
||||
qboolean WriteTGA(char *filename, enum fs_relative fsroot, const qbyte *fte_restrict rgb_buffer, int bytestride, int width, int height, enum uploadfmt fmt)
|
||||
qboolean WriteTGA(char *filename, enum fs_relative fsroot, const qbyte *fte_restrict rgb_buffer, qintptr_t bytestride, int width, int height, enum uploadfmt fmt)
|
||||
{
|
||||
qboolean success = false;
|
||||
size_t c, i;
|
||||
|
@ -844,20 +844,20 @@ qboolean WriteTGA(char *filename, enum fs_relative fsroot, const qbyte *fte_rest
|
|||
if (ipx == opx && !rgb)
|
||||
{ //can just directly write it
|
||||
//bgr24, bgra24
|
||||
c = width*height*opx;
|
||||
c = (size_t)width*height*opx;
|
||||
|
||||
VFS_WRITE(vfs, header, sizeof(header));
|
||||
VFS_WRITE(vfs, rgb_buffer, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
qbyte *fte_restrict rgb_out = malloc(width*opx*height);
|
||||
qbyte *fte_restrict rgb_out = malloc((size_t)width*opx*height);
|
||||
|
||||
//no need to swap alpha, and if we're just swapping alpha will be fine in-place.
|
||||
if (rgb)
|
||||
{ //rgb24, rgbx32, rgba32
|
||||
// compact, and swap
|
||||
c = width*height;
|
||||
c = (size_t)width*height;
|
||||
for (i=0 ; i<c ; i++)
|
||||
{
|
||||
rgb_out[i*opx+2] = rgb_buffer[i*ipx+0];
|
||||
|
@ -868,7 +868,7 @@ qboolean WriteTGA(char *filename, enum fs_relative fsroot, const qbyte *fte_rest
|
|||
else
|
||||
{ //(bgr24), bgrx32, (bgra32)
|
||||
// compact
|
||||
c = width*height;
|
||||
c = (size_t)width*height;
|
||||
for (i=0 ; i<c ; i++)
|
||||
{
|
||||
rgb_out[i*opx+0] = rgb_buffer[i*ipx+0];
|
||||
|
@ -1255,7 +1255,7 @@ error:
|
|||
|
||||
|
||||
#ifndef NPFTE
|
||||
static int Image_WritePNG (char *filename, enum fs_relative fsroot, int compression, void **buffers, int numbuffers, int bufferstride, int width, int height, enum uploadfmt fmt, qboolean writemetadata)
|
||||
static int Image_WritePNG (char *filename, enum fs_relative fsroot, int compression, void **buffers, int numbuffers, qintptr_t bufferstride, int width, int height, enum uploadfmt fmt, qboolean writemetadata)
|
||||
{
|
||||
char name[MAX_OSPATH];
|
||||
int i;
|
||||
|
@ -1924,7 +1924,7 @@ METHODDEF(void) jpeg_error_exit (j_common_ptr cinfo)
|
|||
{
|
||||
longjmp(((jpeg_error_mgr_wrapper *) cinfo->err)->setjmp_buffer, 1);
|
||||
}
|
||||
static qboolean screenshotJPEG(char *filename, enum fs_relative fsroot, int compression, qbyte *screendata, int stride, int screenwidth, int screenheight, enum uploadfmt fmt, unsigned int writemeta)
|
||||
static qboolean screenshotJPEG(char *filename, enum fs_relative fsroot, int compression, qbyte *screendata, qintptr_t stride, int screenwidth, int screenheight, enum uploadfmt fmt, unsigned int writemeta)
|
||||
{
|
||||
qbyte *buffer;
|
||||
vfsfile_t *outfile;
|
||||
|
@ -2550,7 +2550,7 @@ static qbyte *ReadBMPFile(qbyte *buf, int length, int *width, int *height)
|
|||
return ReadRawBMPFile(buf + 14, length-14, width, height, OffsetofBMPBits - 14);
|
||||
}
|
||||
|
||||
qboolean WriteBMPFile(char *filename, enum fs_relative fsroot, qbyte *in, int instride, int width, int height, uploadfmt_t fmt)
|
||||
qboolean WriteBMPFile(char *filename, enum fs_relative fsroot, qbyte *in, qintptr_t instride, int width, int height, uploadfmt_t fmt)
|
||||
{
|
||||
int y;
|
||||
bmpheader_t h;
|
||||
|
@ -5407,18 +5407,12 @@ static void Image_Resample32Lerp(const void *indata, int inwidth, int inheight,
|
|||
GL_ResampleTexture
|
||||
================
|
||||
*/
|
||||
void Image_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight)
|
||||
static void Image_ResampleTexture32Nearest (const unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight)
|
||||
{
|
||||
int i, j;
|
||||
unsigned *inrow;
|
||||
const unsigned *inrow;
|
||||
unsigned frac, fracstep;
|
||||
|
||||
if (gl_lerpimages.ival)
|
||||
{
|
||||
Image_Resample32Lerp(in, inwidth, inheight, out, outwidth, outheight);
|
||||
return;
|
||||
}
|
||||
|
||||
fracstep = inwidth*0x10000/outwidth;
|
||||
for (i=0 ; i<outheight ; i++, out += outwidth)
|
||||
{
|
||||
|
@ -5446,18 +5440,12 @@ void Image_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *o
|
|||
}
|
||||
}
|
||||
|
||||
void Image_ResampleTexture8 (unsigned char *in, int inwidth, int inheight, unsigned char *out, int outwidth, int outheight)
|
||||
static void Image_ResampleTexture8Nearest (const unsigned char *in, int inwidth, int inheight, unsigned char *out, int outwidth, int outheight)
|
||||
{
|
||||
int i, j;
|
||||
unsigned char *inrow;
|
||||
const unsigned char *inrow;
|
||||
unsigned frac, fracstep;
|
||||
|
||||
/*if (gl_lerpimages.ival)
|
||||
{
|
||||
Image_Resample32Lerp(in, inwidth, inheight, out, outwidth, outheight);
|
||||
return;
|
||||
}*/
|
||||
|
||||
fracstep = inwidth*0x10000/outwidth;
|
||||
for (i=0 ; i<outheight ; i++, out += outwidth)
|
||||
{
|
||||
|
@ -5484,18 +5472,12 @@ void Image_ResampleTexture8 (unsigned char *in, int inwidth, int inheight, unsig
|
|||
}
|
||||
}
|
||||
}
|
||||
void Image_ResampleTexture16 (unsigned short *in, int inwidth, int inheight, unsigned short *out, int outwidth, int outheight)
|
||||
static void Image_ResampleTexture16Nearest (const unsigned short *in, int inwidth, int inheight, unsigned short *out, int outwidth, int outheight)
|
||||
{
|
||||
int i, j;
|
||||
unsigned short *inrow;
|
||||
const unsigned short *inrow;
|
||||
unsigned frac, fracstep;
|
||||
|
||||
/*if (gl_lerpimages.ival)
|
||||
{
|
||||
Image_Resample32Lerp(in, inwidth, inheight, out, outwidth, outheight);
|
||||
return;
|
||||
}*/
|
||||
|
||||
fracstep = inwidth*0x10000/outwidth;
|
||||
for (i=0 ; i<outheight ; i++, out += outwidth)
|
||||
{
|
||||
|
@ -5523,6 +5505,72 @@ void Image_ResampleTexture16 (unsigned short *in, int inwidth, int inheight, uns
|
|||
}
|
||||
}
|
||||
|
||||
//returns out on success. if out is null then returns a new BZ_Malloced buffer
|
||||
void *Image_ResampleTexture (uploadfmt_t format, const void *in, int inwidth, int inheight, void *out, int outwidth, int outheight)
|
||||
{
|
||||
switch(format)
|
||||
{
|
||||
case PTI_INVALID:
|
||||
default:
|
||||
return NULL;
|
||||
//we don't care about byte order etc, just channels+sizes.
|
||||
case PTI_LLLX8:
|
||||
case PTI_LLLA8:
|
||||
case PTI_RGBA8:
|
||||
case PTI_RGBX8:
|
||||
case PTI_BGRA8:
|
||||
case PTI_BGRX8:
|
||||
case PTI_RGBA8_SRGB:
|
||||
case PTI_RGBX8_SRGB:
|
||||
case PTI_BGRA8_SRGB:
|
||||
case PTI_BGRX8_SRGB:
|
||||
if (!out)
|
||||
out = BZ_Malloc(((outwidth+3)&~3)*outheight*4);
|
||||
if (gl_lerpimages.ival)
|
||||
Image_Resample32Lerp(in, inwidth, inheight, out, outwidth, outheight); //FIXME: should be sRGB-aware, but probably not a common path on hardware that can actually do srgb.
|
||||
else
|
||||
Image_ResampleTexture32Nearest(in, inwidth, inheight, out, outwidth, outheight);
|
||||
return out;
|
||||
case PTI_R32F:
|
||||
case PTI_A2BGR10:
|
||||
case PTI_E5BGR9:
|
||||
if (!out)
|
||||
out = BZ_Malloc(((outwidth+3)&~3)*outheight*4);
|
||||
Image_ResampleTexture32Nearest(in, inwidth, inheight, out, outwidth, outheight);
|
||||
return out;
|
||||
case PTI_P8:
|
||||
case PTI_L8:
|
||||
case PTI_R8:
|
||||
case PTI_L8_SRGB:
|
||||
case PTI_R8_SNORM:
|
||||
if (!out)
|
||||
out = BZ_Malloc((outwidth+3)*outheight);
|
||||
Image_ResampleTexture8Nearest(in, inwidth, inheight, out, outwidth, outheight);
|
||||
return out;
|
||||
case PTI_RG8:
|
||||
case PTI_RG8_SNORM:
|
||||
case PTI_L8A8:
|
||||
case PTI_L8A8_SRGB:
|
||||
case PTI_R16:
|
||||
case PTI_R16F:
|
||||
case PTI_RGB565:
|
||||
case PTI_RGBA4444:
|
||||
case PTI_ARGB4444:
|
||||
case PTI_RGBA5551:
|
||||
case PTI_ARGB1555:
|
||||
if (!out)
|
||||
out = BZ_Malloc((outwidth+3)*outheight*2);
|
||||
Image_ResampleTexture16Nearest(in, inwidth, inheight, out, outwidth, outheight);
|
||||
return out;
|
||||
case PTI_RGB8:
|
||||
case PTI_BGR8:
|
||||
case PTI_RGBA16:
|
||||
case PTI_RGBA16F:
|
||||
case PTI_RGBA32F:
|
||||
return NULL; //fixmes
|
||||
}
|
||||
}
|
||||
|
||||
//ripped from tenebrae
|
||||
static unsigned int * Image_GenerateNormalMap(qbyte *pixels, unsigned int *nmap, int w, int h, float scale, float offsetscale)
|
||||
{
|
||||
|
@ -7700,48 +7748,19 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag
|
|||
mips->mip[0].data = rgbadata;
|
||||
else
|
||||
{
|
||||
switch(mips->encoding)
|
||||
mips->mip[0].data = Image_ResampleTexture(mips->encoding, rgbadata, imgwidth, imgheight, NULL, mips->mip[0].width, mips->mip[0].height);
|
||||
if (mips->mip[0].data)
|
||||
{
|
||||
case PTI_LLLX8:
|
||||
case PTI_RGBA8:
|
||||
case PTI_RGBX8:
|
||||
case PTI_BGRA8:
|
||||
case PTI_BGRX8:
|
||||
case PTI_RGBA8_SRGB:
|
||||
case PTI_RGBX8_SRGB:
|
||||
case PTI_BGRA8_SRGB:
|
||||
case PTI_BGRX8_SRGB:
|
||||
mips->mip[0].data = BZ_Malloc(((mips->mip[0].width+3)&~3)*mips->mip[0].height*4);
|
||||
//FIXME: should be sRGB-aware, but probably not a common path on hardware that can actually do srgb.
|
||||
Image_ResampleTexture(rgbadata, imgwidth, imgheight, mips->mip[0].data, mips->mip[0].width, mips->mip[0].height);
|
||||
if (freedata)
|
||||
BZ_Free(rgbadata);
|
||||
freedata = true;
|
||||
break;
|
||||
case PTI_L8:
|
||||
case PTI_L8_SRGB:
|
||||
mips->mip[0].data = BZ_Malloc(mips->mip[0].width*mips->mip[0].height);
|
||||
//FIXME: should be sRGB-aware, but probably not a common path on hardware that can actually do srgb.
|
||||
Image_ResampleTexture8((void*)rgbadata, imgwidth, imgheight, mips->mip[0].data, mips->mip[0].width, mips->mip[0].height);
|
||||
if (freedata)
|
||||
BZ_Free(rgbadata);
|
||||
freedata = true;
|
||||
break;
|
||||
case PTI_L8A8:
|
||||
case PTI_L8A8_SRGB:
|
||||
mips->mip[0].data = BZ_Malloc(mips->mip[0].width*mips->mip[0].height*2);
|
||||
//FIXME: should be sRGB-aware, but probably not a common path on hardware that can actually do srgb.
|
||||
Image_ResampleTexture16((void*)rgbadata, imgwidth, imgheight, mips->mip[0].data, mips->mip[0].width, mips->mip[0].height);
|
||||
if (freedata)
|
||||
BZ_Free(rgbadata);
|
||||
freedata = true;
|
||||
break;
|
||||
default: //scaling not supported...
|
||||
}
|
||||
else
|
||||
{ //rescaling unsupported
|
||||
mips->mip[0].data = rgbadata;
|
||||
mips->mip[0].width = imgwidth;
|
||||
mips->mip[0].height = imgheight;
|
||||
mips->mip[0].depth = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9419,7 +9438,7 @@ int MipColor(int r, int g, int b)
|
|||
return best;
|
||||
}
|
||||
|
||||
qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void **buffer, int numbuffers, int bytestride, int width, int height, enum uploadfmt fmt, qboolean writemeta)
|
||||
qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void **buffer, int numbuffers, qintptr_t bytestride, int width, int height, enum uploadfmt fmt, qboolean writemeta)
|
||||
{
|
||||
char ext[8];
|
||||
void *nbuffers[2];
|
||||
|
@ -9443,7 +9462,7 @@ qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void **buffer,
|
|||
|
||||
COM_FileExtension(filename, ext, sizeof(ext));
|
||||
|
||||
#ifdef AVAIL_PNGLIB
|
||||
#ifdef AVAIL_PNGLIB
|
||||
if (!Q_strcasecmp(ext, "png") || !Q_strcasecmp(ext, "pns"))
|
||||
{
|
||||
//png can do bgr+rgb
|
||||
|
@ -9473,9 +9492,9 @@ qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void **buffer,
|
|||
int y, x, s;
|
||||
qbyte *src, *dest;
|
||||
qbyte *srcbuf = buffer[0], *dstbuf;
|
||||
if (fmt == TF_RGB24 || fmt == TF_RGBA32 || fmt == TF_RGBX32)
|
||||
if (fmt == TF_RGB24 || fmt == TF_RGBA32 || fmt == TF_RGBX32 || fmt == PTI_LLLA8 || fmt == PTI_LLLX8)
|
||||
{
|
||||
dstbuf = malloc(width*height);
|
||||
dstbuf = malloc((intptr_t)width*height);
|
||||
s = (fmt == TF_RGB24)?3:4;
|
||||
// convert in-place to eight bit
|
||||
for (y = 0; y < height; y++)
|
||||
|
@ -9491,7 +9510,7 @@ qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void **buffer,
|
|||
}
|
||||
else if (fmt == TF_BGR24 || fmt == TF_BGRA32 || fmt == TF_BGRX32)
|
||||
{
|
||||
dstbuf = malloc(width*height);
|
||||
dstbuf = malloc((intptr_t)width*height);
|
||||
s = (fmt == TF_BGR24)?3:4;
|
||||
// convert in-place to eight bit
|
||||
for (y = 0; y < height; y++)
|
||||
|
|
|
@ -1099,6 +1099,23 @@ void FPS_Preset_f (void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!stricmp("qw", arg))
|
||||
{ //enable qwisms
|
||||
Cbuf_InsertText(
|
||||
"set sv_nqplayerphysics 0\n"
|
||||
"set sv_gameplayfix_multiplethinks 1\n"
|
||||
, RESTRICT_LOCAL, false);
|
||||
return;
|
||||
}
|
||||
if (!stricmp("nq", arg))
|
||||
{ //disable qwisms, for better mod compat
|
||||
Cbuf_InsertText(
|
||||
"set sv_nqplayerphysics 1\n"
|
||||
"set sv_gameplayfix_multiplethinks 0\n"
|
||||
, RESTRICT_LOCAL, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!stricmp("dp", arg))
|
||||
{
|
||||
#ifdef HAVE_SERVER
|
||||
|
@ -1106,6 +1123,7 @@ void FPS_Preset_f (void)
|
|||
Cbuf_InsertText("echo Be sure to restart your server\n", RESTRICT_LOCAL, false);
|
||||
#endif
|
||||
Cbuf_InsertText(
|
||||
"fps_preset nq\n"
|
||||
//these are for smc+derived mods
|
||||
"sv_listen_dp 1\n" //awkward, but forces the server to load the effectinfo.txt in advance.
|
||||
"sv_bigcoords 1\n" //for viewmodel lep precision (would be better to use csqc)
|
||||
|
@ -1135,6 +1153,7 @@ void FPS_Preset_f (void)
|
|||
if (!stricmp("tenebrae", arg))
|
||||
{ //for the luls. combine with the tenebrae mod for maximum effect.
|
||||
Cbuf_InsertText(
|
||||
"fps_preset nq\n"
|
||||
"set r_shadow_realtime_world 1\n"
|
||||
"set r_shadow_realtime_dlight 1\n"
|
||||
"set r_shadow_bumpscale_basetexture 4\n"
|
||||
|
|
|
@ -182,6 +182,8 @@ int MP_TranslateFTEtoQCCodes(int code)
|
|||
case K_SEARCH: return -code;
|
||||
|
||||
default:
|
||||
if (code == -1) //mod bug
|
||||
return code;
|
||||
if (code < 0) //negative values are 'qc-native' keys, for stuff that the api lacks.
|
||||
return -code;
|
||||
if (code >= 0 && code < 128) //ascii codes identical
|
||||
|
@ -344,7 +346,9 @@ int MP_TranslateQCtoFTECodes(int code)
|
|||
case 841: return K_JOY_DOWN;
|
||||
case 842: return K_JOY_LEFT;
|
||||
case 843: return K_JOY_RIGHT;
|
||||
default:
|
||||
default:
|
||||
if (code == -1) //mod bug
|
||||
return -1;
|
||||
if (code < 0) //negative values are 'fte-native' keys, for stuff that the api lacks.
|
||||
return -code;
|
||||
if (code >= 0 && code < 128)
|
||||
|
|
|
@ -843,9 +843,14 @@ void QCBUILTIN PF_CL_drawcharacter (pubprogfuncs_t *prinst, struct globalvars_s
|
|||
}
|
||||
|
||||
//no control chars. use quake ones if so
|
||||
if (!(flag & 4))
|
||||
if (chara < 32 && chara != '\t')
|
||||
chara |= 0xe000;
|
||||
if (!(flag & 4) && !com_parseutf8.ival)
|
||||
{
|
||||
//ugly quake chars...
|
||||
if (chara >= 32 && chara < 128)
|
||||
; //ascii-comptaible range
|
||||
else
|
||||
chara |= 0xe000; //use quake glyphs (including for red text, unfortunately)
|
||||
}
|
||||
|
||||
r2d_be_flags = PF_SelectDPDrawFlag(prinst, flag);
|
||||
PR_CL_BeginString(prinst, pos[0], pos[1], size[0], size[1], &x, &y);
|
||||
|
|
|
@ -3726,9 +3726,9 @@ int Surf_NewLightmaps(int count, int width, int height, uploadfmt_t fmt, qboolea
|
|||
if (pixw != 1 || pixh != 1)
|
||||
return -1; //compressed formats are unsupported
|
||||
dfmt = PTI_BGRX8;
|
||||
if (!sh_config.texfmt[dfmt])
|
||||
if (!sh_config.texfmt[dfmt])
|
||||
dfmt = PTI_RGBX8;
|
||||
if (!sh_config.texfmt[dfmt])
|
||||
if (!sh_config.texfmt[dfmt])
|
||||
dfmt = PTI_RGB8;
|
||||
Image_BlockSizeForEncoding(dfmt, &dpixbytes, &dpixw, &dpixh);
|
||||
|
||||
|
|
|
@ -597,8 +597,7 @@ qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, uploadfmt_
|
|||
qbyte *ReadJPEGFile(qbyte *infile, int length, int *width, int *height);
|
||||
qbyte *ReadPNGFile(const char *fname, qbyte *buf, int length, int *width, int *height, uploadfmt_t *format);
|
||||
qbyte *ReadPCXPalette(qbyte *buf, int len, qbyte *out);
|
||||
void Image_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight);
|
||||
void Image_ResampleTexture8 (unsigned char *in, int inwidth, int inheight, unsigned char *out, int outwidth, int outheight);
|
||||
void *Image_ResampleTexture (uploadfmt_t format, const void *in, int inwidth, int inheight, void *out, int outwidth, int outheight);
|
||||
|
||||
void BoostGamma(qbyte *rgba, int width, int height, uploadfmt_t fmt);
|
||||
void SaturateR8G8B8(qbyte *data, int size, float sat);
|
||||
|
|
|
@ -231,7 +231,7 @@ typedef enum uploadfmt
|
|||
#define PTI_EMULATED TF_INVALID:case TF_BGR24_FLIP:case TF_MIP4_P8:case TF_MIP4_SOLID8:case TF_MIP4_8PAL24:case TF_MIP4_8PAL24_T255:case TF_SOLID8:case TF_TRANS8:case TF_TRANS8_FULLBRIGHT:case TF_HEIGHT8:case TF_HEIGHT8PAL:case TF_H2_T7G1:case TF_H2_TRANS8_0:case TF_H2_T4A4:case TF_8PAL24:case TF_8PAL32:case PTI_LLLX8:case PTI_LLLA8
|
||||
} uploadfmt_t;
|
||||
|
||||
qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void **buffer, int numbuffers, int bytestride, int width, int height, enum uploadfmt fmt, qboolean writemeta);
|
||||
qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void **buffer, int numbuffers, qintptr_t bytestride, int width, int height, enum uploadfmt fmt, qboolean writemeta);
|
||||
|
||||
void SCR_DrawTwoDimensional(int uimenu, qboolean nohud);
|
||||
|
||||
|
@ -258,6 +258,7 @@ void Font_BeginScaledString(struct font_s *font, float vx, float vy, float szx,
|
|||
void Font_Transform(float vx, float vy, int *px, int *py);
|
||||
int Font_CharHeight(void);
|
||||
float Font_CharVHeight(struct font_s *font);
|
||||
int Font_CharPHeight(struct font_s *font);
|
||||
float Font_CharScaleHeight(void);
|
||||
int Font_CharWidth(unsigned int charflags, unsigned int codepoint);
|
||||
float Font_CharScaleWidth(unsigned int charflags, unsigned int codepoint);
|
||||
|
|
|
@ -65,8 +65,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
#undef malloc
|
||||
|
||||
int noconinput = 0;
|
||||
int nostdout = 0;
|
||||
static int noconinput = 0;
|
||||
static int nostdout = 0;
|
||||
|
||||
int isPlugin;
|
||||
int sys_parentleft;
|
||||
|
@ -78,8 +78,6 @@ qboolean sys_gracefulexit;
|
|||
|
||||
qboolean X11_GetDesktopParameters(int *width, int *height, int *bpp, int *refreshrate);
|
||||
|
||||
char *basedir = "./";
|
||||
|
||||
qboolean Sys_InitTerminal (void) //we either have one or we don't.
|
||||
{
|
||||
return true;
|
||||
|
@ -311,9 +309,10 @@ static void Sys_Register_File_Associations_f(void)
|
|||
|
||||
//we need to create some .desktop file first, so stuff knows how to start us up.
|
||||
{
|
||||
char iconsyspath[MAX_OSPATH];
|
||||
char *exe = realpath(host_parms.argv[0], NULL);
|
||||
char *basedir = realpath(com_gamepath, NULL);
|
||||
char *iconname = fs_manifest->installation;
|
||||
const char *iconname = fs_manifest->installation;
|
||||
const char *desktopfile =
|
||||
"[Desktop Entry]\n"
|
||||
"Type=Application\n"
|
||||
|
@ -329,6 +328,10 @@ static void Sys_Register_File_Associations_f(void)
|
|||
;
|
||||
if (!strcmp(iconname, "afterquake") || !strcmp(iconname, "nq")) //hacks so that we don't need to create icons.
|
||||
iconname = "quake";
|
||||
|
||||
if (FS_NativePath("icon.png", FS_GAME, iconsyspath, sizeof(iconsyspath)))
|
||||
iconname = iconsyspath;
|
||||
|
||||
desktopfile = va(desktopfile,
|
||||
fs_manifest->formalname?fs_manifest->formalname:fs_manifest->installation,
|
||||
exe, basedir, iconname);
|
||||
|
|
|
@ -3625,7 +3625,6 @@ static void Sys_MakeInstaller(const char *name)
|
|||
for (i = 0; i < sizeof(icosizes)/sizeof(icosizes[0]); i++)
|
||||
{
|
||||
unsigned int x,y;
|
||||
unsigned int pixels;
|
||||
if (icosizes[i].width > imgwidth || icosizes[i].height > imgheight)
|
||||
continue; //ignore icons if they're bigger than the original icon.
|
||||
|
||||
|
@ -3642,8 +3641,6 @@ static void Sys_MakeInstaller(const char *name)
|
|||
qbyte *in, *inrow;
|
||||
unsigned int outidx;
|
||||
|
||||
pixels = icosizes[i].width * icosizes[i].height;
|
||||
|
||||
bi = data = Z_Malloc(sizeof(*bi) + icosizes[i].width * icosizes[i].height * 5 + icosizes[i].height*4);
|
||||
memset(bi,0, sizeof(BITMAPINFOHEADER));
|
||||
bi->bV4Size = sizeof(BITMAPINFOHEADER);
|
||||
|
@ -3660,8 +3657,7 @@ static void Sys_MakeInstaller(const char *name)
|
|||
outmask = (qbyte*)data + datalen;
|
||||
datalen += ((icosizes[i].width+31)&~31)/8 * icosizes[i].height;
|
||||
|
||||
in = malloc(pixels*4);
|
||||
Image_ResampleTexture((unsigned int*)rgbadata, imgwidth, imgheight, (unsigned int*)in, icosizes[i].width, icosizes[i].height);
|
||||
in = Image_ResampleTexture(format, rgbadata, imgwidth, imgheight, NULL, icosizes[i].width, icosizes[i].height);
|
||||
|
||||
inrow = in;
|
||||
outidx = 0;
|
||||
|
@ -4267,8 +4263,7 @@ void *WIN_CreateCursor(const qbyte *imagedata, int width, int height, uploadfmt_
|
|||
nh = height * scale;
|
||||
if (nw <= 0 || nh <= 0 || nw > 128 || nh > 128) //don't go crazy.
|
||||
return NULL;
|
||||
nd = BZ_Malloc(nw*nh*4);
|
||||
Image_ResampleTexture((unsigned int*)imagedata, width, height, (unsigned int*)nd, nw, nh);
|
||||
nd = Image_ResampleTexture(format, imagedata, width, height, NULL, nw, nh);
|
||||
width = nw;
|
||||
height = nh;
|
||||
imagedata = scaled = nd;
|
||||
|
|
|
@ -30,7 +30,7 @@ cvar_t allow_f_fakeshaft = CVAR("allow_f_fakeshaft", "1");
|
|||
cvar_t allow_f_system = CVAR("allow_f_system", "0");
|
||||
cvar_t allow_f_cmdline = CVAR("allow_f_cmdline", "0");
|
||||
cvar_t auth_validateclients = CVAR("auth_validateclients", "1");
|
||||
cvar_t ruleset = CVARC("ruleset", "none", rulesetcallback);
|
||||
cvar_t ruleset = CVARCD("ruleset", "none", rulesetcallback, "Known rulesets are:\nnone: no explicit rules, all 'minor cheats' are allowed.\nstrict: equivelent to the smackdown ruleset. Note that this will block certain graphical enhancements too.");
|
||||
|
||||
|
||||
#define SECURITY_INIT_BAD_CHECKSUM 1
|
||||
|
@ -369,7 +369,7 @@ typedef struct {
|
|||
qboolean flagged;
|
||||
} ruleset_t;
|
||||
|
||||
rulesetrule_t rulesetrules_strict[] = {
|
||||
static rulesetrule_t rulesetrules_strict[] = {
|
||||
{"ruleset_allow_shaders", "0"}, /*users can potentially create all sorts of wallhacks or spiked models with this*/
|
||||
{"ruleset_allow_watervis", "0"}, /*oh noes! users might be able to see underwater if they're already in said water. oh wait. what? why do we care, dude*/
|
||||
{"r_vertexlight", "0"},
|
||||
|
@ -395,7 +395,7 @@ rulesetrule_t rulesetrules_strict[] = {
|
|||
{NULL}
|
||||
};
|
||||
|
||||
rulesetrule_t rulesetrules_nqr[] = {
|
||||
static rulesetrule_t rulesetrules_nqr[] = {
|
||||
{"ruleset_allow_larger_models", "0"},
|
||||
{"ruleset_allow_watervis", "0"}, /*block seeing through turbs, as well as all our cool graphics stuff. apparently we're not allowed.*/
|
||||
{"ruleset_allow_overlong_sounds", "0"},
|
||||
|
@ -438,7 +438,7 @@ void Validation_DelatchRulesets(void)
|
|||
Con_DPrintf("Ruleset deactivated\n");
|
||||
}
|
||||
|
||||
qboolean Validation_GetCurrentRulesetName(char *rsnames, int resultbuflen, qboolean enforcechosenrulesets)
|
||||
static qboolean Validation_GetCurrentRulesetName(char *rsnames, int resultbuflen, qboolean enforcechosenrulesets)
|
||||
{ //this code is more complex than it needs to be
|
||||
//this allows for the ruleset code to print a ruleset name that is applied via the cvars, but not directly named by the user
|
||||
cvar_t *var;
|
||||
|
@ -501,7 +501,7 @@ qboolean Validation_GetCurrentRulesetName(char *rsnames, int resultbuflen, qbool
|
|||
return false;
|
||||
}
|
||||
|
||||
void Validation_OldRuleset(void)
|
||||
static void Validation_OldRuleset(void)
|
||||
{
|
||||
char rsnames[1024];
|
||||
|
||||
|
@ -511,7 +511,7 @@ void Validation_OldRuleset(void)
|
|||
Cbuf_AddText("say No specific ruleset\n", RESTRICT_LOCAL);
|
||||
}
|
||||
|
||||
void Validation_AllChecks(void)
|
||||
static void Validation_AllChecks(void)
|
||||
{
|
||||
char servername[22];
|
||||
char playername[16];
|
||||
|
|
|
@ -3616,10 +3616,22 @@ static void Cmd_toggle_f(void)
|
|||
if (!v)
|
||||
return;
|
||||
|
||||
if (v->value)
|
||||
Cvar_Set(v, "0");
|
||||
if (Cmd_Argc() >= 3)
|
||||
{
|
||||
const char *newval = Cmd_Argv(2);
|
||||
const char *defval = (Cmd_Argc()>3)?Cmd_Argv(3):v->defaultstr;
|
||||
if (!strcmp(newval, v->string))
|
||||
Cvar_Set(v, defval);
|
||||
else
|
||||
Cvar_Set(v, newval);
|
||||
}
|
||||
else
|
||||
Cvar_Set(v, "1");
|
||||
{
|
||||
if (v->value)
|
||||
Cvar_Set(v, "0");
|
||||
else
|
||||
Cvar_Set(v, "1");
|
||||
}
|
||||
}
|
||||
|
||||
static void Cmd_Set_c(int argn, const char *partial, struct xcommandargcompletioncb_s *ctx)
|
||||
|
@ -4220,7 +4232,7 @@ void Cmd_Init (void)
|
|||
// Cmd_AddCommand ("msg_trigger", Cmd_Msg_Trigger_f);
|
||||
// Cmd_AddCommand ("filter", Cmd_Msg_Filter_f);
|
||||
|
||||
Cmd_AddCommand ("toggle", Cmd_toggle_f);
|
||||
Cmd_AddCommandAD ("toggle", Cmd_toggle_f, Cmd_Set_c, "Toggles a cvar between two values\ntoggle CVARNAME [newval [altval]]");
|
||||
Cmd_AddCommandAD ("set", Cmd_set_f, Cmd_Set_c, "Changes the current value of the named cvar, creating it if it doesn't yet exist.");
|
||||
Cmd_AddCommandAD ("setfl", Cmd_set_f, Cmd_Set_c, "Changes the current value of the named cvar, creating it if it doesn't yet exist. The third arg allows setting cvar flags and should be u, s, or a. This command should normally be used only inside default.cfg.");
|
||||
Cmd_AddCommandAD ("set_calc", Cmd_set_f, Cmd_Set_c, "Sets the named cvar to the result of a (complex) expression.");
|
||||
|
|
|
@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
qboolean sys_nounload;
|
||||
#ifndef HAVE_CLIENT
|
||||
double host_frametime;
|
||||
double realtime; // without any filtering or bounding
|
||||
|
@ -5824,6 +5825,9 @@ void COM_Init (void)
|
|||
LittleFloat = FloatSwap;
|
||||
}
|
||||
|
||||
//random should be random from the start...
|
||||
srand(time(0));
|
||||
|
||||
#ifdef MULTITHREAD
|
||||
Sys_ThreadsInit();
|
||||
#endif
|
||||
|
|
|
@ -5800,15 +5800,17 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
|
|||
|
||||
if (allowreloadconfigs)
|
||||
{
|
||||
for (i = 0; i < countof(conffile); i++)
|
||||
{
|
||||
FS_FLocateFile(conffile[i], FSLF_IFFOUND|FSLF_IGNOREPURE, &loc);
|
||||
if (confpath[i] != (loc.search?loc.search->handle:NULL))
|
||||
if (!reloadconfigs)
|
||||
for (i = 0; i < countof(conffile); i++)
|
||||
{
|
||||
reloadconfigs = true;
|
||||
Con_DPrintf("Reloading configs because %s has changed\n", conffile[i]);
|
||||
FS_FLocateFile(conffile[i], FSLF_IFFOUND|FSLF_IGNOREPURE, &loc);
|
||||
if (confpath[i] != (loc.search?loc.search->handle:NULL))
|
||||
{
|
||||
reloadconfigs = true;
|
||||
Con_DPrintf("Reloading configs because %s has changed\n", conffile[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (reloadconfigs)
|
||||
{
|
||||
|
|
|
@ -12,10 +12,10 @@ cvar_t log_enable[LOG_TYPES] = { CVARF("log_enable", "0", CVAR_NOTFROMSERVER),
|
|||
CVARF("log_enable_players", "0", CVAR_NOTFROMSERVER),
|
||||
CVARF("log_enable_rcon", "1", CVAR_NOTFROMSERVER)
|
||||
};
|
||||
cvar_t log_name[LOG_TYPES] = { CVARFC("log_name", "", CVAR_NOTFROMSERVER, Log_Name_Callback),
|
||||
cvar_t log_name[LOG_TYPES] = { CVARFC("log_name", "qconsole", CVAR_NOTFROMSERVER, Log_Name_Callback),
|
||||
CVARFC("log_name_players", "players", CVAR_NOTFROMSERVER, Log_Name_Callback),
|
||||
CVARFC("log_name_rcon", "rcon", CVAR_NOTFROMSERVER, Log_Name_Callback)};
|
||||
cvar_t log_dir_var = CVARFC("log_dir", "", CVAR_NOTFROMSERVER, Log_Dir_Callback);
|
||||
cvar_t log_dir_var = CVARAFC("log_dir", "", "sv_logdir", CVAR_NOTFROMSERVER, Log_Dir_Callback);
|
||||
cvar_t log_readable = CVARFD("log_readable", "7", CVAR_NOTFROMSERVER, "Bitfield describing what to convert/strip. If 0, exact byte representation will be used.\n&1: Dequakify text.\n&2: Strip special markup.\n&4: Strip ansi control codes.");
|
||||
cvar_t log_developer = CVARFD("log_developer", "0", CVAR_NOTFROMSERVER, "Enables logging of console prints when set to 1. Otherwise unimportant messages will not fill up your log files.");
|
||||
cvar_t log_rotate_files = CVARF("log_rotate_files", "0", CVAR_NOTFROMSERVER);
|
||||
|
@ -47,7 +47,7 @@ static void QDECL Log_Dir_Callback (struct cvar_s *var, char *oldvalue)
|
|||
{
|
||||
Con_Printf(CON_NOTICE "%s forced to default due to invalid characters.\n", var->name);
|
||||
// recursion is avoided by assuming the default value is sane
|
||||
Cvar_ForceSet(var, var->defaultstr);
|
||||
Cvar_ForceSet(var, var->enginevalue);
|
||||
}
|
||||
|
||||
if (!strncmp(var->string, "./", 2)||!strncmp(var->string, ".\\", 2))
|
||||
|
@ -72,7 +72,7 @@ static void QDECL Log_Name_Callback (struct cvar_s *var, char *oldvalue)
|
|||
{
|
||||
Con_Printf(CON_NOTICE "%s forced to default due to invalid characters.\n", var->name);
|
||||
// recursion is avoided by assuming the default value is sane
|
||||
Cvar_ForceSet(var, var->defaultstr);
|
||||
Cvar_ForceSet(var, var->enginevalue);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,27 +89,13 @@ void Log_String (logtype_t lognum, const char *s)
|
|||
conchar_t cline[2048], *c;
|
||||
unsigned int u, flags;
|
||||
|
||||
f = NULL;
|
||||
switch(lognum)
|
||||
{
|
||||
case LOG_CONSOLE:
|
||||
f = "qconsole";
|
||||
break;
|
||||
case LOG_PLAYER:
|
||||
f = "players";
|
||||
break;
|
||||
case LOG_RCON:
|
||||
f = "rcon";
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (!log_enable[lognum].value)
|
||||
return;
|
||||
|
||||
if (log_name[lognum].string[0])
|
||||
f = log_name[lognum].string;
|
||||
else
|
||||
f = log_name[lognum].enginevalue;
|
||||
|
||||
if (!f)
|
||||
return;
|
||||
|
@ -268,24 +254,39 @@ void SV_LogPlayer(client_t *cl, char *msg)
|
|||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_LEGACY
|
||||
static struct {
|
||||
const char *commandname;
|
||||
const char *desc;
|
||||
} legacylog[] =
|
||||
{
|
||||
{"logfile", ""},
|
||||
{"logplayers", " players"},
|
||||
{"logrcon", " frags"},
|
||||
};
|
||||
|
||||
void Log_Logfile_f (void)
|
||||
{
|
||||
if (log_enable[LOG_CONSOLE].value)
|
||||
size_t logtype;
|
||||
const char *cmd = Cmd_Argv(0);
|
||||
for (logtype = 0; logtype < countof(legacylog); logtype++)
|
||||
if (!Q_strcasecmp(legacylog[logtype].commandname, cmd))
|
||||
break;
|
||||
|
||||
if (log_enable[logtype].value)
|
||||
{
|
||||
Cvar_SetValue(&log_enable[LOG_CONSOLE], 0);
|
||||
Con_Printf("Logging disabled.\n");
|
||||
Cvar_SetValue(&log_enable[logtype], 0);
|
||||
Con_Printf("Logging%s disabled.\n", legacylog[logtype].desc);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *f;
|
||||
const char *f;
|
||||
char syspath[MAX_OSPATH];
|
||||
|
||||
f = "qconsole";
|
||||
if (log_name[LOG_CONSOLE].string[0])
|
||||
f = log_name[LOG_CONSOLE].string;
|
||||
if (log_name[logtype].string[0])
|
||||
f = log_name[logtype].string;
|
||||
else
|
||||
f = log_name[logtype].enginevalue;
|
||||
|
||||
if (*log_dir)
|
||||
f = va("%s/%s.log", log_dir, f);
|
||||
|
@ -293,10 +294,10 @@ void Log_Logfile_f (void)
|
|||
f = va("%s.log", f);
|
||||
|
||||
if (FS_NativePath(f, log_root, syspath, sizeof(syspath)))
|
||||
Con_Printf("%s", va("Logging to %s\n", syspath));
|
||||
Con_Printf("%s", va("Logging%s to %s\n", legacylog[logtype].desc, syspath));
|
||||
else
|
||||
Con_Printf("%s", va("Logging to %s\n", f));
|
||||
Cvar_SetValue(&log_enable[LOG_CONSOLE], 1);
|
||||
Con_Printf("%s", va("Logging%s to %s\n", legacylog[logtype].desc, f));
|
||||
Cvar_SetValue(&log_enable[logtype], 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -338,6 +339,7 @@ void SV_Fraglogfile_f (void)
|
|||
Con_TPrintf ("Logging frags to %s.\n", name);
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
#ifdef IPLOG
|
||||
/*for fuck sake, why can people still not write simple files. proquake is writing binary files as text ones. this function is to try to deal with that fuckup*/
|
||||
|
@ -626,7 +628,7 @@ static void IPLog_Merge_f(void)
|
|||
{
|
||||
const char *fname = Cmd_Argv(1);
|
||||
if (!IPLog_Merge_File(fname))
|
||||
Con_Printf("unable to read %s\n", fname);
|
||||
Con_Printf("unable to read iplog \"%s\" for merging\n", fname);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -975,9 +977,16 @@ void Log_Init(void)
|
|||
// register cvars
|
||||
for (i = 0; i < LOG_TYPES; i++)
|
||||
{
|
||||
#ifdef CLIENTONLY
|
||||
if (i != LOG_CONSOLE)
|
||||
continue;
|
||||
#endif
|
||||
Cvar_Register (&log_enable[i], CONLOGGROUP);
|
||||
Cvar_Register (&log_name[i], CONLOGGROUP);
|
||||
log_newline[i] = true;
|
||||
#ifdef HAVE_LEGACY
|
||||
Cmd_AddCommand(legacylog[i].commandname, IPLog_Merge_f);
|
||||
#endif
|
||||
}
|
||||
Cvar_Register (&log_dir_var, CONLOGGROUP);
|
||||
Cvar_Register (&log_readable, CONLOGGROUP);
|
||||
|
@ -987,8 +996,6 @@ void Log_Init(void)
|
|||
Cvar_Register (&log_dosformat, CONLOGGROUP);
|
||||
Cvar_Register (&log_timestamps, CONLOGGROUP);
|
||||
|
||||
Cmd_AddCommand("logfile", Log_Logfile_f);
|
||||
|
||||
#ifdef IPLOG
|
||||
Cmd_AddCommandD("identify", IPLog_Identify_f, "Looks up a player's ip to see if they're using a different name");
|
||||
Cmd_AddCommand("ipmerge", IPLog_Merge_f);
|
||||
|
|
|
@ -586,7 +586,6 @@ qboolean NET_AddressSmellsFunny(netadr_t *a)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
static void NET_AdrToStringDoResolve(void *ctx, void *data, size_t a, size_t b)
|
||||
{
|
||||
netadr_t *n = data;
|
||||
|
@ -615,7 +614,6 @@ void NET_AdrToStringResolve (netadr_t *adr, void (*resolved)(void *ctx, void *da
|
|||
*(void**)(n+1) = resolved;
|
||||
COM_AddWork(WG_LOADER, NET_AdrToStringDoResolve, ctx, n, a, b);
|
||||
}
|
||||
*/
|
||||
|
||||
char *NET_AdrToString (char *s, int len, netadr_t *a)
|
||||
{
|
||||
|
|
|
@ -555,7 +555,7 @@ void QCBUILTIN PF_ExecuteCommand (pubprogfuncs_t *prinst, struct globalvars_s *
|
|||
void QCBUILTIN PF_setspawnparms (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
void QCBUILTIN PF_precache_vwep_model(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
int PF_checkclient_Internal (pubprogfuncs_t *prinst);
|
||||
int PF_precache_sound_Internal (pubprogfuncs_t *prinst, const char *s);
|
||||
int PF_precache_sound_Internal (pubprogfuncs_t *prinst, const char *s, qboolean queryonly);
|
||||
int PF_precache_model_Internal (pubprogfuncs_t *prinst, const char *s, qboolean queryonly);
|
||||
void PF_setmodel_Internal (pubprogfuncs_t *prinst, edict_t *e, const char *m);
|
||||
char *PF_infokey_Internal (int entnum, const char *value);
|
||||
|
|
|
@ -1361,6 +1361,7 @@ typedef struct q1usercmd_s
|
|||
#define RDF_RENDERSCALE (1u<<21)
|
||||
#define RDF_SCENEGAMMA (1u<<22)
|
||||
#define RDF_DISABLEPARTICLES (1u<<23) //mostly for skyrooms
|
||||
#define RDF_SKIPSKY (1u<<24) //we have a skyroom, skip drawing sky chains for this scene.
|
||||
|
||||
#define RDF_ALLPOSTPROC (RDF_BLOOM|RDF_FISHEYE|RDF_WATERWARP|RDF_CUSTOMPOSTPROC|RDF_ANTIALIAS|RDF_SCENEGAMMA) //these flags require rendering to an fbo for the various different post-processing shaders.
|
||||
|
||||
|
|
|
@ -105,21 +105,8 @@ qboolean QVM_LoadDLL(vm_t *vm, const char *name, qboolean binroot, void **vmMain
|
|||
|
||||
if (binroot)
|
||||
{
|
||||
//load eg: basedir/module_gamedir_arch.ext
|
||||
Con_DPrintf("Attempting to load native library: %s\n", name);
|
||||
#ifdef ANDROID
|
||||
if (!hVM && FS_NativePath(dllname_anycpu, FS_BINARYPATH, fname, sizeof(fname)))
|
||||
hVM = Sys_LoadLibrary(fname, funcs);
|
||||
#else
|
||||
if (!hVM && FS_NativePath(dllname_archpri, FS_BINARYPATH, fname, sizeof(fname)))
|
||||
hVM = Sys_LoadLibrary(fname, funcs);
|
||||
if (!hVM && FS_NativePath(dllname_anycpu, FS_BINARYPATH, fname, sizeof(fname)))
|
||||
hVM = Sys_LoadLibrary(fname, funcs);
|
||||
|
||||
if (!hVM && FS_NativePath(dllname_archpri, FS_ROOT, fname, sizeof(fname)))
|
||||
hVM = Sys_LoadLibrary(fname, funcs);
|
||||
if (!hVM && FS_NativePath(dllname_anycpu, FS_ROOT, fname, sizeof(fname)))
|
||||
hVM = Sys_LoadLibrary(fname, funcs);
|
||||
#endif
|
||||
|
||||
// run through the search paths
|
||||
iterator = NULL;
|
||||
|
@ -151,9 +138,25 @@ qboolean QVM_LoadDLL(vm_t *vm, const char *name, qboolean binroot, void **vmMain
|
|||
hVM = Sys_LoadLibrary(fname, funcs);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
if (!hVM && FS_NativePath(dllname_anycpu, FS_BINARYPATH, fname, sizeof(fname)))
|
||||
hVM = Sys_LoadLibrary(fname, funcs);
|
||||
#else
|
||||
if (!hVM && FS_NativePath(dllname_archpri, FS_BINARYPATH, fname, sizeof(fname)))
|
||||
hVM = Sys_LoadLibrary(fname, funcs);
|
||||
if (!hVM && FS_NativePath(dllname_anycpu, FS_BINARYPATH, fname, sizeof(fname)))
|
||||
hVM = Sys_LoadLibrary(fname, funcs);
|
||||
|
||||
if (!hVM && FS_NativePath(dllname_archpri, FS_ROOT, fname, sizeof(fname)))
|
||||
hVM = Sys_LoadLibrary(fname, funcs);
|
||||
if (!hVM && FS_NativePath(dllname_anycpu, FS_ROOT, fname, sizeof(fname)))
|
||||
hVM = Sys_LoadLibrary(fname, funcs);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
//load eg: basedir/gamedir/module_arch.ext
|
||||
Con_DPrintf("Attempting to load (unsafe) native library: %s\n", name);
|
||||
|
||||
// run through the search paths
|
||||
|
|
|
@ -58,6 +58,7 @@ typedef struct {
|
|||
char *name;
|
||||
} dllfunction_t;
|
||||
typedef void dllhandle_t; //typically used as void*
|
||||
extern qboolean sys_nounload; //blocks Sys_CloseLibrary. set before stack trace fatal shutdowns.
|
||||
dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs);
|
||||
void Sys_CloseLibrary(dllhandle_t *lib);
|
||||
void *Sys_GetAddressForName(dllhandle_t *module, const char *exportname);
|
||||
|
|
|
@ -1696,7 +1696,7 @@ void GLBE_Init(void)
|
|||
|
||||
//end tables
|
||||
|
||||
#define MAX_ARRAY_VERTS 65535
|
||||
#define MAX_ARRAY_VERTS 65536
|
||||
static vecV_t vertexarray[MAX_ARRAY_VERTS];
|
||||
#if 1//ndef GLSLONLY
|
||||
static avec4_t coloursarray[MAX_ARRAY_VERTS];
|
||||
|
@ -5220,7 +5220,7 @@ static qboolean GLBE_GenerateBatchTextures(batch_t *batch, shader_t *bs)
|
|||
int oldfbo;
|
||||
float oldil;
|
||||
int oldbem;
|
||||
if (r_refdef.recurse == r_portalrecursion.ival || r_refdef.recurse == R_MAX_RECURSE)
|
||||
if (r_refdef.recurse >= r_portalrecursion.ival || r_refdef.recurse == R_MAX_RECURSE)
|
||||
return false;
|
||||
//these flags require rendering some view as an fbo
|
||||
//(BEM_DEPTHDARK is used when lightmap scale is 0, but still shows any emissive stuff)
|
||||
|
@ -6211,6 +6211,8 @@ void GLBE_DrawLightPrePass(void)
|
|||
qglClearColor (1,0,0,1);
|
||||
}
|
||||
|
||||
qboolean R_DrawSkyroom(shader_t *skyshader);
|
||||
|
||||
void GLBE_DrawWorld (batch_t **worldbatches)
|
||||
{
|
||||
#ifdef RTLIGHTS
|
||||
|
@ -6268,6 +6270,21 @@ void GLBE_DrawWorld (batch_t **worldbatches)
|
|||
BE_UpdateLightmaps();
|
||||
if (worldbatches)
|
||||
{
|
||||
if (worldbatches[SHADER_SORT_SKY] && r_refdef.skyroom_enabled)
|
||||
{
|
||||
batch_t *b;
|
||||
for (b = worldbatches[SHADER_SORT_SKY]; b; b = b->next)
|
||||
if (R_DrawSkyroom(b->shader))
|
||||
{
|
||||
GL_CullFace(0);//make sure flipcull reversion takes effect
|
||||
currententity = NULL;
|
||||
GLBE_SelectEntity(&r_worldentity);
|
||||
GL_ForceDepthWritable();
|
||||
qglClear(GL_DEPTH_BUFFER_BIT);
|
||||
r_refdef.flags |= RDF_SKIPSKY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (gl_overbright.modified)
|
||||
{
|
||||
int i;
|
||||
|
|
|
@ -1130,13 +1130,13 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx)
|
|||
else if (bm->pixel_mode == FT_PIXEL_MODE_BGRA)
|
||||
{
|
||||
unsigned int *out = alloca(nw*nh*sizeof(*out));
|
||||
Image_ResampleTexture((void*)bm->buffer, bm->width, bm->rows, out, nw, nh);
|
||||
Image_ResampleTexture(PTI_BGRA8, (void*)bm->buffer, bm->width, bm->rows, out, nw, nh);
|
||||
c = Font_LoadGlyphData(f, charidx, bm->pixel_mode, out, nw, nh, nw*sizeof(*out));
|
||||
}
|
||||
else if (bm->pixel_mode == FT_PIXEL_MODE_GRAY)
|
||||
{
|
||||
unsigned char *out = alloca(nw*nh*sizeof(*out));
|
||||
Image_ResampleTexture8((void*)bm->buffer, bm->width, bm->rows, out, nw, nh);
|
||||
Image_ResampleTexture(PTI_L8, (void*)bm->buffer, bm->width, bm->rows, out, nw, nh);
|
||||
c = Font_LoadGlyphData(f, charidx, bm->pixel_mode, out, nw, nh, nw*sizeof(*out));
|
||||
}
|
||||
else
|
||||
|
@ -1204,7 +1204,7 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx)
|
|||
int ngh = f->charheight;
|
||||
qbyte *out2 = alloca(ngw*ngh*4);
|
||||
if (ngw&&ngh)
|
||||
Image_ResampleTexture((unsigned int *)out, gw, gh, (unsigned int *)out2, ngw, ngh);
|
||||
Image_ResampleTexture(PTI_RGBA8, out, gw, gh, out2, ngw, ngh);
|
||||
c = Font_LoadGlyphData(f, charidx, FT_PIXEL_MODE_RGBA, out2, ngw, ngh, ngw*4);
|
||||
gw = ngw;
|
||||
}
|
||||
|
@ -1263,7 +1263,7 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx)
|
|||
for (y = 0; y < gh; y++)
|
||||
for (x = 0; x < gw; x++)
|
||||
out1[x+y*gw] = out[x+y*gs];
|
||||
Image_ResampleTexture((unsigned int *)out1, gw, gh, (unsigned int *)out2, ngw, ngh);
|
||||
Image_ResampleTexture(PTI_RGBA8, out1, gw, gh, out2, ngw, ngh);
|
||||
}
|
||||
c = Font_LoadGlyphData(f, charidx, FT_PIXEL_MODE_RGBA, out2, ngw, ngh, ngw*4);
|
||||
gw = ngw;
|
||||
|
@ -2404,6 +2404,10 @@ int Font_CharHeight(void)
|
|||
{
|
||||
return curfont->charheight;
|
||||
}
|
||||
int Font_CharPHeight(struct font_s *font)
|
||||
{
|
||||
return font->charheight;
|
||||
}
|
||||
float Font_CharVHeight(struct font_s *font)
|
||||
{
|
||||
return ((float)font->charheight * vid.height)/vid.rotpixelheight;
|
||||
|
|
|
@ -68,6 +68,11 @@ qboolean GLSCR_UpdateScreen (void)
|
|||
|
||||
vid.numpages = 2 + vid_triplebuffer.value;
|
||||
|
||||
if (!scr_initialized || !con_initialized)
|
||||
{
|
||||
return false; // not initialized yet
|
||||
}
|
||||
|
||||
R2D_Font_Changed();
|
||||
|
||||
if (vid_srgb.modified)
|
||||
|
@ -95,11 +100,6 @@ qboolean GLSCR_UpdateScreen (void)
|
|||
}
|
||||
}
|
||||
|
||||
if (!scr_initialized || !con_initialized)
|
||||
{
|
||||
return false; // not initialized yet
|
||||
}
|
||||
|
||||
if (scr_disabled_for_loading)
|
||||
{
|
||||
extern float scr_disabled_time;
|
||||
|
@ -138,19 +138,16 @@ qboolean GLSCR_UpdateScreen (void)
|
|||
{
|
||||
Editor_Draw();
|
||||
V_UpdatePalette (false);
|
||||
Media_RecordFrame();
|
||||
R2D_BrightenScreen();
|
||||
Media_RecordFrame();
|
||||
|
||||
if (key_dest_mask & kdm_console)
|
||||
Con_DrawConsole(vid.height/2, false);
|
||||
else
|
||||
Con_DrawConsole(0, false);
|
||||
SCR_DrawCursor();
|
||||
if (R2D_Flush)
|
||||
R2D_Flush();
|
||||
VID_SwapBuffers();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (Media_ShowFilm())
|
||||
{
|
||||
|
@ -158,76 +155,71 @@ qboolean GLSCR_UpdateScreen (void)
|
|||
V_UpdatePalette (false);
|
||||
R2D_BrightenScreen();
|
||||
Media_RecordFrame();
|
||||
if (R2D_Flush)
|
||||
R2D_Flush();
|
||||
GL_Set2D (false);
|
||||
VID_SwapBuffers();
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// do 3D refresh drawing, and then update the screen
|
||||
//
|
||||
SCR_SetUpToDrawConsole ();
|
||||
|
||||
noworld = false;
|
||||
nohud = false;
|
||||
|
||||
if (r_clear.ival)
|
||||
else
|
||||
{
|
||||
GL_ForceDepthWritable();
|
||||
qglClearColor((r_clear.ival&1)?1:0, (r_clear.ival&2)?1:0, (r_clear.ival&4)?1:0, 1);
|
||||
qglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
depthcleared = true;
|
||||
}
|
||||
//
|
||||
// do 3D refresh drawing, and then update the screen
|
||||
//
|
||||
SCR_SetUpToDrawConsole ();
|
||||
|
||||
noworld = false;
|
||||
nohud = false;
|
||||
|
||||
if (r_clear.ival)
|
||||
{
|
||||
GL_ForceDepthWritable();
|
||||
qglClearColor((r_clear.ival&1)?1:0, (r_clear.ival&2)?1:0, (r_clear.ival&4)?1:0, 1);
|
||||
qglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
depthcleared = true;
|
||||
}
|
||||
|
||||
#ifdef VM_CG
|
||||
if (CG_Refresh())
|
||||
nohud = true;
|
||||
else
|
||||
if (CG_Refresh())
|
||||
nohud = true;
|
||||
else
|
||||
#endif
|
||||
#ifdef CSQC_DAT
|
||||
if (CSQC_DrawView())
|
||||
nohud = true;
|
||||
else
|
||||
if (CSQC_DrawView())
|
||||
nohud = true;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (uimenu != 1)
|
||||
{
|
||||
if (r_worldentity.model && cls.state == ca_active)
|
||||
V_RenderView (nohud);
|
||||
else
|
||||
if (uimenu != 1)
|
||||
{
|
||||
noworld = true;
|
||||
if (r_worldentity.model && cls.state == ca_active)
|
||||
V_RenderView (nohud);
|
||||
else
|
||||
{
|
||||
noworld = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GL_Set2D (false);
|
||||
|
||||
scr_con_forcedraw = false;
|
||||
if (noworld)
|
||||
{
|
||||
//draw the levelshot or the conback fullscreen
|
||||
if (R2D_DrawLevelshot())
|
||||
;
|
||||
else if (scr_con_current != vid.height)
|
||||
R2D_ConsoleBackground(0, vid.height, true);
|
||||
else
|
||||
scr_con_forcedraw = true;
|
||||
|
||||
nohud = true;
|
||||
}
|
||||
|
||||
SCR_DrawTwoDimensional(uimenu, nohud);
|
||||
|
||||
V_UpdatePalette (false);
|
||||
R2D_BrightenScreen();
|
||||
Media_RecordFrame();
|
||||
}
|
||||
|
||||
GL_Set2D (false);
|
||||
|
||||
scr_con_forcedraw = false;
|
||||
if (noworld)
|
||||
{
|
||||
//draw the levelshot or the conback fullscreen
|
||||
if (R2D_DrawLevelshot())
|
||||
;
|
||||
else if (scr_con_current != vid.height)
|
||||
R2D_ConsoleBackground(0, vid.height, true);
|
||||
else
|
||||
scr_con_forcedraw = true;
|
||||
|
||||
nohud = true;
|
||||
}
|
||||
|
||||
SCR_DrawTwoDimensional(uimenu, nohud);
|
||||
|
||||
V_UpdatePalette (false);
|
||||
R2D_BrightenScreen();
|
||||
|
||||
Media_RecordFrame();
|
||||
|
||||
RSpeedShow();
|
||||
|
||||
if (R2D_Flush)
|
||||
R2D_Flush();
|
||||
|
||||
|
|
|
@ -1444,7 +1444,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
|
|||
for(;;)
|
||||
{
|
||||
size_t len;
|
||||
int i;
|
||||
int i, j;
|
||||
char *type, *idx, *next;
|
||||
char *token = com_token;
|
||||
|
||||
|
@ -1487,6 +1487,15 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
|
|||
if (prog->numsamplers < i+1)
|
||||
prog->numsamplers = i+1;
|
||||
|
||||
/*for (j = 0; sh_defaultsamplers[j].name; j++)
|
||||
{
|
||||
if (!strcmp(token, sh_defaultsamplers[j].name+2))
|
||||
{
|
||||
Con_Printf("%s: %s is an internal texture name\n", name, token);
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
|
||||
//I really want to use layout(binding = %i) here, but its specific to the glsl version (which we don't really know yet)
|
||||
Q_strlcatfz(prescript, &offset, sizeof(prescript), "#define s_%s s_t%u\nuniform %s%s s_%s;\n", token, i, strncmp(type, "sampler", 7)?"sampler":"", type, token);
|
||||
}
|
||||
|
@ -3947,13 +3956,15 @@ qboolean Shader_Init (void)
|
|||
}
|
||||
}
|
||||
|
||||
memset(wibuf, 0xff, sizeof(wibuf));
|
||||
if (!qrenderer)
|
||||
r_whiteimage = r_nulltex;
|
||||
else
|
||||
{
|
||||
memset(wibuf, 0xff, sizeof(wibuf));
|
||||
r_whiteimage = R_LoadTexture("$whiteimage", 4, 4, TF_RGBA32, wibuf, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA);
|
||||
memset(wibuf, 0, sizeof(wibuf));
|
||||
r_blackimage = R_LoadTexture("$blackimage", 4, 4, TF_RGBA32, wibuf, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA);
|
||||
memset(wibuf, 0, sizeof(wibuf));
|
||||
r_blackimage = R_LoadTexture("$blackimage", 4, 4, TF_RGBA32, wibuf, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA);
|
||||
}
|
||||
|
||||
Shader_NeedReload(true);
|
||||
Shader_DoReload();
|
||||
|
|
|
@ -3689,7 +3689,7 @@ void Sh_CheckSettings(void)
|
|||
#ifdef VKQUAKE
|
||||
case QR_VULKAN:
|
||||
canshadowless = true;
|
||||
cansmap = true;
|
||||
cansmap = vk.multisamplebits==VK_SAMPLE_COUNT_1_BIT; //FIXME - we need to render shadowmaps without needing to restart the current scene.
|
||||
canstencil = false;
|
||||
break;
|
||||
#endif
|
||||
|
|
|
@ -2,6 +2,17 @@
|
|||
#if defined(GLQUAKE) && defined(USE_EGL)
|
||||
#include "gl_videgl.h"
|
||||
|
||||
//EGL_KHR_gl_colorspace
|
||||
#ifndef EGL_GL_COLORSPACE_KHR
|
||||
#define EGL_GL_COLORSPACE_KHR 0x309D
|
||||
#endif
|
||||
#ifndef EGL_GL_COLORSPACE_SRGB_KHR
|
||||
#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089
|
||||
#endif
|
||||
#ifndef EGL_GL_COLORSPACE_LINEAR_KHR
|
||||
#define EGL_GL_COLORSPACE_LINEAR_KHR 0x308A
|
||||
#endif
|
||||
|
||||
extern cvar_t vid_vsync;
|
||||
|
||||
EGLContext eglctx = EGL_NO_CONTEXT;
|
||||
|
@ -13,15 +24,16 @@ static dllhandle_t *eslibrary;
|
|||
|
||||
static EGLint (EGLAPIENTRY *qeglGetError)(void);
|
||||
|
||||
static EGLDisplay (EGLAPIENTRY *qeglGetPlatformDisplay)(EGLenum platform, void *native_display, const EGLint *attrib_list);
|
||||
static EGLDisplay (EGLAPIENTRY *qeglGetPlatformDisplay)(EGLenum platform, void *native_display, const EGLAttrib *attrib_list);
|
||||
static EGLDisplay (EGLAPIENTRY *qeglGetDisplay)(EGLNativeDisplayType display_id);
|
||||
static EGLBoolean (EGLAPIENTRY *qeglInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor);
|
||||
static EGLBoolean (EGLAPIENTRY *qeglTerminate)(EGLDisplay dpy);
|
||||
|
||||
static EGLBoolean (EGLAPIENTRY *qeglGetConfigs)(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
static EGLBoolean (EGLAPIENTRY *qeglChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
EGLBoolean (EGLAPIENTRY *qeglGetConfigAttrib)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
|
||||
|
||||
static EGLSurface (EGLAPIENTRY *qeglCreatePlatformWindowSurface)(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
|
||||
static EGLSurface (EGLAPIENTRY *qeglCreatePlatformWindowSurface)(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list);
|
||||
static EGLSurface (EGLAPIENTRY *qeglCreateWindowSurface)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
|
||||
static EGLBoolean (EGLAPIENTRY *qeglDestroySurface)(EGLDisplay dpy, EGLSurface surface);
|
||||
static EGLBoolean (EGLAPIENTRY *qeglQuerySurface)(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
|
||||
|
@ -44,6 +56,7 @@ static dllfunction_t qeglfuncs[] =
|
|||
|
||||
{(void*)&qeglGetConfigs, "eglGetConfigs"},
|
||||
{(void*)&qeglChooseConfig, "eglChooseConfig"},
|
||||
{(void*)&qeglGetConfigAttrib, "eglGetConfigAttrib"},
|
||||
|
||||
{(void*)&qeglCreateWindowSurface, "eglCreateWindowSurface"},
|
||||
{(void*)&qeglDestroySurface, "eglDestroySurface"},
|
||||
|
@ -156,7 +169,7 @@ qboolean EGL_LoadLibrary(char *driver)
|
|||
#endif
|
||||
if (!eslibrary)
|
||||
Sys_Printf("unable to load some libGL\n");
|
||||
|
||||
|
||||
Sys_Printf("Attempting to dlopen libEGL... ");
|
||||
egllibrary = Sys_LoadLibrary("libEGL", qeglfuncs);
|
||||
if (!egllibrary)
|
||||
|
@ -243,10 +256,10 @@ void EGL_Shutdown(void)
|
|||
|
||||
for (i = 0; i < countof(eglattrs); i++)
|
||||
{
|
||||
if (qeglGetContifAttrib(egldpy, cfg, eglattrs[i].attr, &val))
|
||||
Con_DPrintf("%i.%s: %i\n", cfg, eglattrs[i].attrname, val);
|
||||
if (qeglGetConfigAttrib(egldpy, cfg, eglattrs[i].attr, &val))
|
||||
Con_DPrintf("%p.%s: %i\n", cfg, eglattrs[i].attrname, val);
|
||||
else
|
||||
Con_DPrintf("%i.%s: UNKNOWN\n", cfg, eglattrs[i].attrname);
|
||||
Con_DPrintf("%p.%s: UNKNOWN\n", cfg, eglattrs[i].attrname);
|
||||
}
|
||||
}*/
|
||||
|
||||
|
@ -273,15 +286,15 @@ void EGL_SwapBuffers (void)
|
|||
qeglSwapBuffers(egldpy, eglsurf);
|
||||
/* TODO: check result? */
|
||||
TRACE(("EGL_SwapBuffers done\n"));
|
||||
|
||||
Con_Printf("EGL_SwapBuffers\n");
|
||||
}
|
||||
|
||||
qboolean EGL_Init (rendererstate_t *info, unsigned char *palette, int eglplat, void *nwindow, void *ndpy, EGLNativeWindowType windowid, EGLNativeDisplayType dpyid)
|
||||
|
||||
|
||||
qboolean EGL_InitDisplay (rendererstate_t *info, int eglplat, void *ndpy, EGLNativeDisplayType dpyid, EGLConfig *outconfig)
|
||||
{
|
||||
EGLint numconfig;
|
||||
EGLConfig cfg;
|
||||
EGLint major, minor;
|
||||
EGLint numconfig=0;
|
||||
EGLConfig cfg=0;
|
||||
EGLint major=0, minor=0;
|
||||
EGLint attrib[] =
|
||||
{
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
|
@ -296,17 +309,6 @@ qboolean EGL_Init (rendererstate_t *info, unsigned char *palette, int eglplat, v
|
|||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
EGL_NONE
|
||||
};
|
||||
EGLint wndattrib[] =
|
||||
{
|
||||
// EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_LINEAR_KHR,
|
||||
|
||||
EGL_NONE
|
||||
};
|
||||
EGLint contextattr[] =
|
||||
{
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2, //requires EGL 1.3
|
||||
EGL_NONE, EGL_NONE
|
||||
};
|
||||
|
||||
/* if (!EGL_LoadLibrary(""))
|
||||
{
|
||||
|
@ -354,7 +356,6 @@ qboolean EGL_Init (rendererstate_t *info, unsigned char *palette, int eglplat, v
|
|||
Con_Printf(CON_ERROR "EGL: can't choose config!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!numconfig)
|
||||
{
|
||||
Con_Printf(CON_ERROR "EGL: no configs!\n");
|
||||
|
@ -362,11 +363,38 @@ qboolean EGL_Init (rendererstate_t *info, unsigned char *palette, int eglplat, v
|
|||
}
|
||||
|
||||
// EGL_ShowConfig(egldpy, cfg);
|
||||
*outconfig = cfg;
|
||||
return true;
|
||||
}
|
||||
|
||||
qboolean EGL_InitWindow (rendererstate_t *info, int eglplat, void *nwindow, EGLNativeWindowType windowid, EGLConfig cfg)
|
||||
{
|
||||
EGLint contextattr[] =
|
||||
{
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2, //requires EGL 1.3
|
||||
EGL_NONE, EGL_NONE
|
||||
};
|
||||
|
||||
if (qeglCreatePlatformWindowSurface)
|
||||
{
|
||||
EGLAttrib wndattrib[] =
|
||||
{
|
||||
// EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR,
|
||||
|
||||
EGL_NONE
|
||||
};
|
||||
eglsurf = qeglCreatePlatformWindowSurface(egldpy, cfg, nwindow, info->srgb?wndattrib:NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
EGLint wndattrib[] =
|
||||
{
|
||||
// EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR,
|
||||
|
||||
EGL_NONE
|
||||
};
|
||||
eglsurf = qeglCreateWindowSurface(egldpy, cfg, windowid, info->srgb?wndattrib:NULL);
|
||||
}
|
||||
if (eglsurf == EGL_NO_SURFACE)
|
||||
{
|
||||
int err = qeglGetError();
|
||||
|
@ -376,7 +404,7 @@ qboolean EGL_Init (rendererstate_t *info, unsigned char *palette, int eglplat, v
|
|||
Con_Printf(CON_ERROR "EGL: eglCreateWindowSurface failed: %s\n", EGL_GetErrorString(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
eglctx = qeglCreateContext(egldpy, cfg, EGL_NO_SURFACE, contextattr);
|
||||
if (eglctx == EGL_NO_CONTEXT)
|
||||
{
|
||||
|
@ -389,7 +417,7 @@ qboolean EGL_Init (rendererstate_t *info, unsigned char *palette, int eglplat, v
|
|||
Con_Printf(CON_ERROR "EGL: can't make current!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (eglplat == EGL_PLATFORM_WAYLAND_KHR)
|
||||
{ //if we don't do this, only the first frame will get displayed, and we'll lock up
|
||||
qeglSwapInterval = NULL;
|
||||
|
@ -400,5 +428,6 @@ qboolean EGL_Init (rendererstate_t *info, unsigned char *palette, int eglplat, v
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -26,6 +26,13 @@ void EGL_UnloadLibrary(void);
|
|||
qboolean EGL_LoadLibrary(char *driver);
|
||||
void EGL_Shutdown(void);
|
||||
void EGL_SwapBuffers (void);
|
||||
qboolean EGL_Init (rendererstate_t *info, unsigned char *palette, int eglplatform, void *nwindow, void *ndpy, EGLNativeWindowType owindow, EGLNativeDisplayType odpy);
|
||||
|
||||
qboolean EGL_InitDisplay (rendererstate_t *info, int eglplat, void *ndpy, EGLNativeDisplayType dpyid, EGLConfig *outconfig);
|
||||
qboolean EGL_InitWindow (rendererstate_t *info, int eglplat, void *nwindow, EGLNativeWindowType windowid, EGLConfig cfg);
|
||||
//qboolean EGL_Init (rendererstate_t *info, unsigned char *palette, int eglplatform, void *nwindow, void *ndpy, EGLNativeWindowType owindow, EGLNativeDisplayType odpy);
|
||||
|
||||
//once you've created an egl display and got an egl config, some windowing systems require querying said egl config to create the window properly.
|
||||
extern EGLDisplay egldpy;
|
||||
extern EGLBoolean (EGLAPIENTRY *qeglGetConfigAttrib)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -199,6 +199,8 @@ static struct
|
|||
int (*pXUngrabPointer)(Display *display, Time time);
|
||||
int (*pXWarpPointer)(Display *display, Window src_w, Window dest_w, int src_x, int src_y, unsigned int src_width, unsigned int src_height, int dest_x, int dest_y);
|
||||
Status (*pXMatchVisualInfo)(Display *display, int screen, int depth, int class, XVisualInfo *vinfo_return);
|
||||
XVisualInfo *(*pXGetVisualInfo)(Display *display, long vinfo_mask, XVisualInfo *vinfo_template, int *nitems_return);
|
||||
|
||||
|
||||
qXErrorHandler (*pXSetErrorHandler)(XErrorHandler);
|
||||
|
||||
|
@ -295,6 +297,7 @@ static qboolean x11_initlib(void)
|
|||
{(void**)&x11.pXUngrabPointer, "XUngrabPointer"},
|
||||
{(void**)&x11.pXWarpPointer, "XWarpPointer"},
|
||||
{(void**)&x11.pXMatchVisualInfo, "XMatchVisualInfo"},
|
||||
{(void**)&x11.pXGetVisualInfo, "XGetVisualInfo"},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -3156,6 +3159,7 @@ static void GLVID_Shutdown(void)
|
|||
#ifdef USE_EGL
|
||||
case PSL_EGL:
|
||||
EGL_Shutdown();
|
||||
EGL_UnloadLibrary();
|
||||
GL_ForgetPointers();
|
||||
break;
|
||||
#endif
|
||||
|
@ -3244,7 +3248,7 @@ static struct
|
|||
Cursor (*ImageLoadCursor) (Display *dpy, const XcursorImage *image);
|
||||
void (*ImageDestroy) (XcursorImage *image);
|
||||
} xcursor;
|
||||
static void *X11VID_CreateCursorRGBA(const qbyte *rgbacursor, size_t w, size_t h, float hotx, float hoty)
|
||||
static void *X11VID_CreateCursorRGBA(const qbyte *rgbacursor, uploadfmt_t format, size_t w, size_t h, float hotx, float hoty)
|
||||
{
|
||||
Cursor *cursor;
|
||||
size_t x, y;
|
||||
|
@ -3256,9 +3260,27 @@ static void *X11VID_CreateCursorRGBA(const qbyte *rgbacursor, size_t w, size_t h
|
|||
img->yhot = hoty;
|
||||
dest = img->pixels;
|
||||
|
||||
for (y = 0; y < h; y++)
|
||||
for (x = 0; x < w; x++, rgbacursor+=4)
|
||||
*dest++ = (rgbacursor[3]<<24)|(rgbacursor[0]<<16)|(rgbacursor[1]<<8)|(rgbacursor[2]<<0); //0xARGB
|
||||
switch (format)
|
||||
{
|
||||
case PTI_BGRA8:
|
||||
case PTI_BGRX8:
|
||||
for (y = 0; y < h; y++)
|
||||
for (x = 0; x < w; x++, rgbacursor+=4)
|
||||
*dest++ = (rgbacursor[3]<<24)|(rgbacursor[2]<<16)|(rgbacursor[1]<<8)|(rgbacursor[0]<<0); //0xARGB
|
||||
break; //supported...
|
||||
case PTI_RGBA8:
|
||||
case PTI_RGBX8:
|
||||
case PTI_LLLA8:
|
||||
case PTI_LLLX8:
|
||||
for (y = 0; y < h; y++)
|
||||
for (x = 0; x < w; x++, rgbacursor+=4)
|
||||
*dest++ = (rgbacursor[3]<<24)|(rgbacursor[0]<<16)|(rgbacursor[1]<<8)|(rgbacursor[2]<<0); //0xARGB
|
||||
break;
|
||||
default:
|
||||
//panic... format wasn't supported. I hope we didn't spend ages resampling it...
|
||||
xcursor.ImageDestroy(img);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cursor = Z_Malloc(sizeof(*cursor));
|
||||
*cursor = xcursor.ImageLoadCursor(vid_dpy, img);
|
||||
|
@ -3282,15 +3304,16 @@ static void *X11VID_CreateCursor(const qbyte *imagedata, int width, int height,
|
|||
nh = height * scale;
|
||||
if (nw <= 0 || nh <= 0 || nw > 128 || nh > 128) //don't go crazy.
|
||||
return NULL;
|
||||
nd = BZ_Malloc(nw*nh*4);
|
||||
Image_ResampleTexture((unsigned int*)imagedata, width, height, (unsigned int*)nd, nw, nh);
|
||||
nd = Image_ResampleTexture(format, imagedata, width, height, NULL, nw, nh);
|
||||
if (!nd)
|
||||
return NULL; //resampling of that format didn't work for some reason...
|
||||
width = nw;
|
||||
height = nh;
|
||||
r = X11VID_CreateCursorRGBA(nd, width, height, hotx, hoty);
|
||||
r = X11VID_CreateCursorRGBA(nd, format, width, height, hotx, hoty);
|
||||
BZ_Free(nd);
|
||||
}
|
||||
else
|
||||
r = X11VID_CreateCursorRGBA(imagedata, width, height, hotx, hoty);
|
||||
r = X11VID_CreateCursorRGBA(imagedata, format, width, height, hotx, hoty);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -3777,6 +3800,9 @@ static qboolean X11VID_Init (rendererstate_t *info, unsigned char *palette, int
|
|||
int width = info->width; //can override these if vmode isn't available
|
||||
int height = info->height;
|
||||
int rate = info->rate;
|
||||
#if defined(USE_EGL)
|
||||
EGLConfig eglcfg = 0;
|
||||
#endif
|
||||
#if defined(USE_EGL) || defined(VKQUAKE)
|
||||
XVisualInfo vinfodef;
|
||||
#endif
|
||||
|
@ -3903,10 +3929,21 @@ static qboolean X11VID_Init (rendererstate_t *info, unsigned char *palette, int
|
|||
#ifdef GLQUAKE
|
||||
#ifdef USE_EGL
|
||||
case PSL_EGL:
|
||||
visinfo = &vinfodef;
|
||||
if (!x11.pXMatchVisualInfo(vid_dpy, scrnum, info->bpp?info->bpp:DefaultDepth(vid_dpy, scrnum), TrueColor, visinfo))
|
||||
if (!EGL_InitDisplay(info, EGL_PLATFORM_X11_KHR, vid_dpy, (EGLNativeDisplayType)vid_dpy, &eglcfg))
|
||||
{
|
||||
Sys_Error("Couldn't choose visual for EGL\n");
|
||||
Con_Printf("X11VID_Init: Unable to find suitable EGL config\n");
|
||||
GLVID_Shutdown();
|
||||
return false;
|
||||
}
|
||||
{
|
||||
int num_visuals;
|
||||
EGLint id;
|
||||
if (!qeglGetConfigAttrib(egldpy, eglcfg, EGL_NATIVE_VISUAL_ID, &id))
|
||||
Sys_Error("Couldn't choose visual for EGL\n");
|
||||
vinfodef.visualid = id;
|
||||
visinfo = x11.pXGetVisualInfo(vid_dpy, VisualIDMask, &vinfodef, &num_visuals);
|
||||
if (!visinfo)
|
||||
Sys_Error("Couldn't get visual info for EGL\n");
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
@ -4049,7 +4086,7 @@ static qboolean X11VID_Init (rendererstate_t *info, unsigned char *palette, int
|
|||
break;
|
||||
#ifdef USE_EGL
|
||||
case PSL_EGL:
|
||||
if (!EGL_Init(info, palette, EGL_PLATFORM_X11_KHR, &vid_window, vid_dpy, (EGLNativeWindowType)vid_window, (EGLNativeDisplayType)vid_dpy))
|
||||
if (!EGL_InitWindow(info, EGL_PLATFORM_X11_KHR, &vid_window, (EGLNativeWindowType)vid_window, eglcfg))
|
||||
{
|
||||
Con_Printf("Failed to create EGL context.\n");
|
||||
GLVID_Shutdown();
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -119,29 +119,49 @@ void R_DrawFastSky(batch_t *batch)
|
|||
void R_RenderScene (void);
|
||||
qboolean R_DrawSkyroom(shader_t *skyshader)
|
||||
{
|
||||
#ifdef GLQUAKE
|
||||
float vmat[16];
|
||||
refdef_t oldrefdef;
|
||||
|
||||
if (qrenderer != QR_OPENGL)
|
||||
return false; //FIXME
|
||||
if (r_viewcluster == -1)
|
||||
return false; //don't draw the skyroom if the camera is outside.
|
||||
|
||||
if (r_fastsky.value)
|
||||
return false; //skyrooms can be expensive.
|
||||
if (!r_refdef.skyroom_enabled || r_refdef.recurse >= R_MAX_RECURSE-1)
|
||||
return false;
|
||||
|
||||
oldrefdef = r_refdef;
|
||||
r_refdef.recurse+=1;
|
||||
|
||||
r_refdef.externalview = true;
|
||||
r_refdef.externalview = true; //an out-of-body experience...
|
||||
r_refdef.skyroom_enabled = false;
|
||||
r_refdef.forcevis = false;
|
||||
r_refdef.flags |= RDF_DISABLEPARTICLES;
|
||||
r_refdef.flags &= ~RDF_SKIPSKY;
|
||||
r_refdef.forcedvis = NULL;
|
||||
r_refdef.areabitsknown = false; //recalculate areas clientside.
|
||||
|
||||
/*work out where the camera should be (use the same angles)*/
|
||||
VectorCopy(r_refdef.skyroom_pos, r_refdef.vieworg);
|
||||
VectorCopy(r_refdef.skyroom_pos, r_refdef.pvsorigin);
|
||||
Matrix4x4_CM_ModelViewMatrixFromAxis(vmat, vpn, vright, vup, r_refdef.vieworg);
|
||||
|
||||
if (developer.ival)
|
||||
if (r_worldentity.model->funcs.PointContents(r_worldentity.model, NULL, r_refdef.skyroom_pos) & FTECONTENTS_SOLID)
|
||||
Con_DPrintf("Skyroom position %.1f %.1f %.1f in solid\n", r_refdef.skyroom_pos[0], r_refdef.skyroom_pos[1], r_refdef.skyroom_pos[2]);
|
||||
|
||||
/*if (cl.skyrotate)
|
||||
{
|
||||
vec3_t axis[3];
|
||||
float ang = cl.skyrotate * cl.time;
|
||||
if (!cl.skyaxis[0]&&!cl.skyaxis[1]&&!cl.skyaxis[2])
|
||||
VectorSet(cl.skyaxis, 0,0,1);
|
||||
RotatePointAroundVector(axis[0], cl.skyaxis, vpn, ang);
|
||||
RotatePointAroundVector(axis[1], cl.skyaxis, vright, ang);
|
||||
RotatePointAroundVector(axis[2], cl.skyaxis, vup, ang);
|
||||
Matrix4x4_CM_ModelViewMatrixFromAxis(vmat, axis[0], axis[1], axis[2], r_refdef.vieworg);
|
||||
}
|
||||
else*/
|
||||
Matrix4x4_CM_ModelViewMatrixFromAxis(vmat, vpn, vright, vup, r_refdef.vieworg);
|
||||
R_SetFrustum (r_refdef.m_projection_std, vmat);
|
||||
|
||||
//now determine the stuff the backend will use.
|
||||
|
@ -159,16 +179,7 @@ qboolean R_DrawSkyroom(shader_t *skyshader)
|
|||
AngleVectors (r_refdef.viewangles, vpn, vright, vup);
|
||||
VectorCopy (r_refdef.vieworg, r_origin);
|
||||
|
||||
GLBE_SelectEntity(&r_worldentity);
|
||||
GL_ForceDepthWritable();
|
||||
qglClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
currententity = NULL;
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -208,7 +219,6 @@ qboolean R_DrawSkyChain (batch_t *batch)
|
|||
if (skyshader->prog) //glsl is expected to do the whole skybox/warpsky thing itself, with no assistance from this legacy code.
|
||||
{
|
||||
//if the first pass is transparent in some form, then be prepared to give it a skyroom behind.
|
||||
R_DrawSkyroom(skyshader);
|
||||
return false; //draw as normal...
|
||||
}
|
||||
}
|
||||
|
@ -218,7 +228,7 @@ qboolean R_DrawSkyChain (batch_t *batch)
|
|||
else
|
||||
skyboxtex = NULL;
|
||||
|
||||
if (R_DrawSkyroom(skyshader))
|
||||
if (r_refdef.flags & RDF_SKIPSKY)
|
||||
{ //don't obscure the skyroom if the sky shader is opaque.
|
||||
qboolean opaque = false;
|
||||
if (skyshader->numpasses)
|
||||
|
|
|
@ -82,7 +82,7 @@ static cvar_t pr_no_playerphysics = CVARFD("pr_no_playerphysics", "0", CVAR_LATC
|
|||
static cvar_t pr_no_parsecommand = CVARFD("pr_no_parsecommand", "0", 0, "Provides a way around invalid mod usage of SV_ParseClientCommand, eg xonotic.");
|
||||
|
||||
extern cvar_t pr_sourcedir;
|
||||
cvar_t pr_ssqc_progs = CVARAF("progs", "", "sv_progs", CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_NOTFROMSERVER);
|
||||
cvar_t pr_ssqc_progs = CVARAFD("sv_progs", "", "progs", CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_NOTFROMSERVER, "Specifies the filename of the gamecode to use serverside. Empty means autodetect - typically loading either progs or qwprogs depending on gamedir priority, then based upon deathmatch settings.");
|
||||
static cvar_t pr_nonetaccess = CVARD("pr_nonetaccess", "0", "Block all direct access to network buffers (the writebyte builtin and friends will ignore the call)."); //prevent write_... builtins from doing anything. This means we can run any mod, specific to any engine, on the condition that it also has a qw or nq crc.
|
||||
|
||||
static cvar_t pr_overridebuiltins = CVAR("pr_overridebuiltins", "1");
|
||||
|
@ -99,6 +99,7 @@ static cvar_t sv_gameplayfix_setmodelrealbox = CVARD("sv_gameplayfix_setmodelrea
|
|||
#endif
|
||||
static cvar_t sv_gameplayfix_setmodelsize_qw = CVARD("sv_gameplayfix_setmodelsize_qw", "0", "The setmodel builtin will act as a setsize for QuakeWorld mods also.");
|
||||
cvar_t dpcompat_nopreparse = CVARD("dpcompat_nopreparse", "0", "Xonotic uses svc_tempentity with unknowable lengths mixed with other data that needs to be translated. This cvar disables any attempt to translate or pre-parse network messages, including disabling nq/qw cross compatibility. NOTE: because preparsing will be disabled, messages might not get backbuffered correctly if too much reliable data is written.");
|
||||
static cvar_t dpcompat_precachesoundhack = CVARD("dpcompat_precachesoundhack", "0", "Changes the behaviour of only the ssqc's precache_sound to return a precache index. precache_model and csqc's precaches are unchanged.");
|
||||
//static cvar_t dpcompat_traceontouch = CVARD("dpcompat_traceontouch", "0", "Report trace plane etc when an entity touches another.");
|
||||
extern cvar_t sv_listen_dp;
|
||||
|
||||
|
@ -1568,6 +1569,7 @@ void PR_Init(void)
|
|||
Cvar_Register (&pr_ssqc_progs, cvargroup_progs);
|
||||
Cvar_Register (&pr_compatabilitytest, cvargroup_progs);
|
||||
|
||||
Cvar_Register (&dpcompat_precachesoundhack, cvargroup_progs);
|
||||
Cvar_Register (&dpcompat_nopreparse, cvargroup_progs);
|
||||
Cvar_Register (&pr_nonetaccess, cvargroup_progs);
|
||||
Cvar_Register (&pr_overridebuiltins, cvargroup_progs);
|
||||
|
@ -4347,7 +4349,7 @@ static void QCBUILTIN PF_precache_file (pubprogfuncs_t *prinst, struct globalvar
|
|||
FS_FLocateFile(s, FSLF_IFFOUND, NULL);
|
||||
}
|
||||
|
||||
int PF_precache_sound_Internal (pubprogfuncs_t *prinst, const char *s)
|
||||
int PF_precache_sound_Internal (pubprogfuncs_t *prinst, const char *s, qboolean queryonly)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -4362,6 +4364,8 @@ int PF_precache_sound_Internal (pubprogfuncs_t *prinst, const char *s)
|
|||
{
|
||||
if (!sv.strings.sound_precache[i])
|
||||
{
|
||||
if (queryonly)
|
||||
return 0;
|
||||
#ifdef VM_Q1
|
||||
if (svs.gametype == GT_Q1QVM)
|
||||
sv.strings.sound_precache[i] = s;
|
||||
|
@ -4389,18 +4393,30 @@ int PF_precache_sound_Internal (pubprogfuncs_t *prinst, const char *s)
|
|||
if (!strcmp(sv.strings.sound_precache[i], s))
|
||||
return i;
|
||||
}
|
||||
PR_BIError (prinst, "PF_precache_sound: overflow");
|
||||
if (!queryonly)
|
||||
PR_BIError (prinst, "PF_precache_sound: overflow");
|
||||
return 0;
|
||||
}
|
||||
static void QCBUILTIN PF_precache_sound (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
const char *s;
|
||||
int idx;
|
||||
|
||||
s = PR_GetStringOfs(prinst, OFS_PARM0);
|
||||
|
||||
G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
|
||||
idx = PF_precache_sound_Internal(prinst, s, false);
|
||||
|
||||
PF_precache_sound_Internal(prinst, s);
|
||||
if (dpcompat_precachesoundhack.ival)
|
||||
G_FLOAT(OFS_RETURN) = idx; //returns the index as a float.
|
||||
else
|
||||
G_INT(OFS_RETURN) = G_INT(OFS_PARM0); //returns the filename as a string.
|
||||
}
|
||||
static void QCBUILTIN PF_getsoundindex (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
const char *s = PR_GetStringOfs(prinst, OFS_PARM0);
|
||||
qboolean queryonly = (svprogfuncs->callargc >= 2)?G_FLOAT(OFS_PARM1):false;
|
||||
|
||||
G_FLOAT(OFS_RETURN) = PF_precache_sound_Internal(prinst, s, queryonly);
|
||||
}
|
||||
|
||||
int PF_precache_model_Internal (pubprogfuncs_t *prinst, const char *s, qboolean queryonly)
|
||||
|
@ -4459,7 +4475,8 @@ int PF_precache_model_Internal (pubprogfuncs_t *prinst, const char *s, qboolean
|
|||
return i;
|
||||
}
|
||||
}
|
||||
PR_BIError (prinst, "PF_precache_model: overflow");
|
||||
if (!queryonly)
|
||||
PR_BIError (prinst, "PF_precache_model: overflow");
|
||||
return 0;
|
||||
}
|
||||
static void QCBUILTIN PF_precache_model (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
|
@ -7442,7 +7459,7 @@ static void QCBUILTIN PF_clientcommand (pubprogfuncs_t *prinst, struct globalvar
|
|||
|
||||
|
||||
|
||||
const char *SV_CheckRejectConnection(netadr_t *adr, const char *uinfo, unsigned int protocol, unsigned int pext1, unsigned int pext2, char *guid)
|
||||
const char *SV_CheckRejectConnection(netadr_t *adr, const char *uinfo, unsigned int protocol, unsigned int pext1, unsigned int pext2, unsigned int ezpext1, char *guid)
|
||||
{
|
||||
char addrstr[256];
|
||||
char clfeatures[4096], *bp;
|
||||
|
@ -7532,6 +7549,19 @@ const char *SV_CheckRejectConnection(netadr_t *adr, const char *uinfo, unsigned
|
|||
Info_SetValueForKey(clfeatures, "PEXT2_VOICECHAT", "1", sizeof(clfeatures));
|
||||
if (pext2 & PEXT2_REPLACEMENTDELTAS)
|
||||
Info_SetValueForKey(clfeatures, "PEXT2_REPLACEMENTDELTAS", "1", sizeof(clfeatures));
|
||||
if (pext2 & PEXT2_MAXPLAYERS)
|
||||
Info_SetValueForKey(clfeatures, "PEXT2_MAXPLAYERS", "1", sizeof(clfeatures));
|
||||
if (pext2 & PEXT2_PREDINFO)
|
||||
Info_SetValueForKey(clfeatures, "PEXT2_PREDINFO", "1", sizeof(clfeatures));
|
||||
if (pext2 & PEXT2_NEWSIZEENCODING)
|
||||
Info_SetValueForKey(clfeatures, "PEXT2_NEWSIZEENCODING", "1", sizeof(clfeatures));
|
||||
if (pext2 & PEXT2_INFOBLOBS)
|
||||
Info_SetValueForKey(clfeatures, "PEXT2_INFOBLOBS", "1", sizeof(clfeatures));
|
||||
|
||||
if (ezpext1 & EZPEXT1_FLOATENTCOORDS)
|
||||
Info_SetValueForKey(clfeatures, "EZPEXT1_FLOATENTCOORDS", "1", sizeof(clfeatures));
|
||||
if (ezpext1 & EZPEXT1_SETANGLEREASON)
|
||||
Info_SetValueForKey(clfeatures, "EZPEXT1_SETANGLEREASON", "1", sizeof(clfeatures));
|
||||
|
||||
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv.world.edicts);
|
||||
G_INT(OFS_PARM0) = (int)PR_TempString(svprogfuncs, addrstr);
|
||||
|
@ -10663,6 +10693,7 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
|
|||
// {"findlist_radius", PF_FindListRadius, 0, 0, 0, 0, D("entity*(vector pos, float radius)", "Return a list of entities with the given string field set to the given value.")},
|
||||
// {"traceboxptr", PF_TraceBox, 0, 0, 0, 0, D("typedef struct {\nfloat allsolid;\nfloat startsolid;\nfloat fraction;\nfloat truefraction;\nentity ent;\nvector endpos;\nvector plane_normal;\nfloat plane_dist;\nint surfaceflags;\nint contents;\n} trace_t;\nvoid(trace_t *trace, vector start, vector mins, vector maxs, vector end, float nomonsters, entity forent)", "Like regular tracebox, except doesn't doesn't use any evil globals.")},
|
||||
|
||||
{"getsoundindex", PF_getsoundindex, 0, 0, 0, 0, D("float(string soundname, float queryonly)", "Provides a way to query if a sound is already precached or not. The return value can also be checked for <=255 to see if it'll work over any network protocol. The sound index can also be used for writebyte hacks, but this is discouraged - use SOUNDFLAG_UNICAST instead.")},
|
||||
{"getmodelindex", PF_getmodelindex, 0, 0, 0, 200, D("float(string modelname, optional float queryonly)", "Acts as an alternative to precache_model(foo);setmodel(bar, foo); return bar.modelindex;\nIf queryonly is set and the model was not previously precached, the builtin will return 0 without needlessly precaching the model.")},
|
||||
{"externcall", PF_externcall, 0, 0, 0, 201, D("__variant(float prnum, string funcname, ...)", "Directly call a function in a different/same progs by its name.\nprnum=0 is the 'default' or 'main' progs.\nprnum=-1 means current progs.\nprnum=-2 will scan through the active progs and will use the first it finds.")},
|
||||
{"addprogs", PF_addprogs, 0, 0, 0, 202, D("float(string progsname)", "Loads an additional .dat file into the current qcvm. The returned handle can be used with any of the externcall/externset/externvalue builtins.\nThere are cvars that allow progs to be loaded automatically.")},
|
||||
|
|
|
@ -109,28 +109,28 @@ typedef enum
|
|||
G_GETINFOKEY,
|
||||
G_MULTICAST, //35
|
||||
G_DISABLEUPDATES,
|
||||
G_WRITEBYTE,
|
||||
G_WRITECHAR,
|
||||
G_WRITESHORT,
|
||||
G_WRITEBYTE,
|
||||
G_WRITECHAR,
|
||||
G_WRITESHORT,
|
||||
G_WRITELONG, //40
|
||||
G_WRITEANGLE,
|
||||
G_WRITECOORD,
|
||||
G_WRITESTRING,
|
||||
G_WRITEANGLE,
|
||||
G_WRITECOORD,
|
||||
G_WRITESTRING,
|
||||
G_WRITEENTITY,
|
||||
G_FLUSHSIGNON, //45
|
||||
g_memset,
|
||||
g_memcpy,
|
||||
g_strncpy,
|
||||
g_sin,
|
||||
g_memcpy,
|
||||
g_strncpy,
|
||||
g_sin,
|
||||
g_cos, //50
|
||||
g_atan2,
|
||||
g_sqrt,
|
||||
g_floor,
|
||||
g_ceil,
|
||||
g_atan2,
|
||||
g_sqrt,
|
||||
g_floor,
|
||||
g_ceil,
|
||||
g_acos, //55
|
||||
G_CMD_ARGC,
|
||||
G_CMD_ARGV,
|
||||
G_TraceBox, //was G_TraceCapsule
|
||||
G_TraceBox, //was G_TraceCapsule, which is a misnomer.
|
||||
G_FS_OpenFile,
|
||||
G_FS_CloseFile, //60
|
||||
G_FS_ReadFile,
|
||||
|
@ -214,7 +214,7 @@ typedef enum
|
|||
|
||||
typedef enum
|
||||
{
|
||||
F_INT,
|
||||
F_INT,
|
||||
F_FLOAT,
|
||||
F_LSTRING, // string on disk, pointer in memory, TAG_LEVEL
|
||||
// F_GSTRING, // string on disk, pointer in memory, TAG_GAME
|
||||
|
@ -817,7 +817,7 @@ static qintptr_t QVM_Remove_Ent (void *offset, quintptr_t mask, const qintptr_t
|
|||
|
||||
static qintptr_t QVM_Precache_Sound (void *offset, quintptr_t mask, const qintptr_t *arg)
|
||||
{
|
||||
return PF_precache_sound_Internal(svprogfuncs, VM_POINTER(arg[0]));
|
||||
return PF_precache_sound_Internal(svprogfuncs, VM_POINTER(arg[0]), false);
|
||||
}
|
||||
static qintptr_t QVM_Precache_Model (void *offset, quintptr_t mask, const qintptr_t *arg)
|
||||
{
|
||||
|
@ -1786,7 +1786,7 @@ static qintptr_t QVM_uri_query (void *offset, quintptr_t mask, const qintptr_t *
|
|||
const char *data = VM_POINTER(arg[4]);
|
||||
size_t datasize = VM_LONG(arg[5]);
|
||||
extern cvar_t pr_enable_uriget;
|
||||
|
||||
|
||||
if (!pr_enable_uriget.ival)
|
||||
{
|
||||
Con_Printf("QVM_uri_query(\"%s\"): %s disabled\n", url, pr_enable_uriget.name);
|
||||
|
@ -1856,6 +1856,29 @@ static qintptr_t QVM_pointerstat (void *offset, quintptr_t mask, const qintptr_t
|
|||
return 0;
|
||||
}
|
||||
|
||||
static qintptr_t QVM_VisibleTo (void *offset, quintptr_t mask, const qintptr_t *arg)
|
||||
{
|
||||
unsigned int a0 = VM_LONG(arg[0]);
|
||||
unsigned int a1 = VM_LONG(arg[1]);
|
||||
if (a0 < sv.world.num_edicts || a1 < sv.world.num_edicts)
|
||||
{
|
||||
pvscache_t *viewer = &q1qvmprogfuncs.edicttable[a0]->pvsinfo;
|
||||
pvscache_t *viewee = &q1qvmprogfuncs.edicttable[a1]->pvsinfo;
|
||||
if (viewer->num_leafs && viewee->num_leafs)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < viewer->num_leafs; i++)
|
||||
{
|
||||
int areas[] = {2,viewer->areanum, viewer->areanum2};
|
||||
qbyte *pvs = sv.world.worldmodel->funcs.ClusterPVS(sv.world.worldmodel, viewer->leafnums[i], NULL, PVM_FAST);
|
||||
if (sv.world.worldmodel->funcs.EdictInFatPVS(sv.world.worldmodel, viewee, pvs, areas))
|
||||
return true; //viewer can see viewee
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static qintptr_t QVM_Map_Extension (void *offset, quintptr_t mask, const qintptr_t *arg);
|
||||
|
||||
typedef qintptr_t (*traps_t) (void *offset, quintptr_t mask, const qintptr_t *arg);
|
||||
|
@ -1898,24 +1921,24 @@ traps_t bitraps[G_MAX] =
|
|||
QVM_GetInfoKey,
|
||||
QVM_Multicast, //35
|
||||
QVM_DisableUpdates,
|
||||
QVM_WriteByte,
|
||||
QVM_WriteChar,
|
||||
QVM_WriteShort,
|
||||
QVM_WriteByte,
|
||||
QVM_WriteChar,
|
||||
QVM_WriteShort,
|
||||
QVM_WriteLong, //40
|
||||
QVM_WriteAngle,
|
||||
QVM_WriteCoord,
|
||||
QVM_WriteString,
|
||||
QVM_WriteAngle,
|
||||
QVM_WriteCoord,
|
||||
QVM_WriteString,
|
||||
QVM_WriteEntity,
|
||||
QVM_FlushSignon, //45
|
||||
QVM_memset,
|
||||
QVM_memcpy,
|
||||
QVM_strncpy,
|
||||
QVM_sin,
|
||||
QVM_memcpy,
|
||||
QVM_strncpy,
|
||||
QVM_sin,
|
||||
QVM_cos, //50
|
||||
QVM_atan2,
|
||||
QVM_sqrt,
|
||||
QVM_floor,
|
||||
QVM_ceil,
|
||||
QVM_atan2,
|
||||
QVM_sqrt,
|
||||
QVM_floor,
|
||||
QVM_ceil,
|
||||
QVM_acos, //55
|
||||
QVM_Cmd_ArgC,
|
||||
QVM_Cmd_ArgV,
|
||||
|
@ -1975,6 +1998,7 @@ struct
|
|||
{"pointparticles", QVM_pointparticles},
|
||||
{"clientstat", QVM_clientstat}, //csqc extension
|
||||
{"pointerstat", QVM_pointerstat}, //csqc extension
|
||||
{"VisibleTo", QVM_VisibleTo}, //alternative to mvdsv's visclients hack
|
||||
|
||||
//sql?
|
||||
//model querying?
|
||||
|
@ -2072,7 +2096,7 @@ void Q1QVM_Shutdown(qboolean notifygame)
|
|||
Q_strncpyz(svs.clients[i].namebuf, svs.clients[i].name, sizeof(svs.clients[i].namebuf));
|
||||
svs.clients[i].name = svs.clients[i].namebuf;
|
||||
}
|
||||
if (notifygame)
|
||||
if (notifygame && gvars)
|
||||
VM_Call(q1qvm, GAME_SHUTDOWN, 0, 0, 0);
|
||||
VM_Destroy(q1qvm);
|
||||
q1qvm = NULL;
|
||||
|
@ -2150,13 +2174,19 @@ qboolean PR_LoadQ1QVM(void)
|
|||
qintptr_t limit;
|
||||
extern cvar_t pr_maxedicts;
|
||||
|
||||
const char *fname = pr_ssqc_progs.string;
|
||||
if (!*fname)
|
||||
fname = "qwprogs";
|
||||
|
||||
Q1QVM_Shutdown(true);
|
||||
|
||||
q1qvm = VM_Create("qwprogs", com_nogamedirnativecode.ival?NULL:syscallnative, "qwprogs", syscallqvm);
|
||||
q1qvm = VM_Create(fname, com_nogamedirnativecode.ival?NULL:syscallnative, fname, syscallqvm);
|
||||
if (!q1qvm)
|
||||
q1qvm = VM_Create("qwprogs", syscallnative, "qwprogs", NULL);
|
||||
q1qvm = VM_Create(fname, syscallnative, fname, NULL);
|
||||
if (!q1qvm)
|
||||
{
|
||||
if (com_nogamedirnativecode.ival && COM_FCheckExists(va("%s"ARCH_DL_POSTFIX, fname)))
|
||||
Con_Printf(CON_WARNING"%s"ARCH_DL_POSTFIX" exists, but is blocked from loading due to known bugs in other engines. If this is from a safe source then either ^aset com_nogamedirnativecode 0^a or rename to eg %s%s_%s"ARCH_DL_POSTFIX"\n", fname, ((host_parms.binarydir && *host_parms.binarydir)?host_parms.binarydir:host_parms.basedir), fname, FS_GetGamedir(false));
|
||||
if (svprogfuncs == &q1qvmprogfuncs)
|
||||
sv.world.progs = svprogfuncs = NULL;
|
||||
return false;
|
||||
|
@ -2238,7 +2268,7 @@ qboolean PR_LoadQ1QVM(void)
|
|||
gdn = (gameDataN_t*)((char*)VM_MemoryBase(q1qvm) + ret);
|
||||
gd.APIversion = gdn->APIversion;
|
||||
gd.sizeofent = gdn->sizeofent;
|
||||
|
||||
|
||||
gd.ents = gdn->ents;
|
||||
gd.global = gdn->global;
|
||||
gd.fields = gdn->fields;
|
||||
|
@ -2384,6 +2414,7 @@ qboolean PR_LoadQ1QVM(void)
|
|||
{
|
||||
const char *fname = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, field[i].name);
|
||||
emufields
|
||||
Con_DPrintf("Extension field %s is not supported\n", fname);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2394,6 +2425,7 @@ qboolean PR_LoadQ1QVM(void)
|
|||
{
|
||||
const char *fname = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, field[i].name);
|
||||
emufields
|
||||
Con_DPrintf("Extension field %s is not supported\n", fname);
|
||||
}
|
||||
}
|
||||
#undef emufield
|
||||
|
@ -2490,7 +2522,7 @@ qboolean Q1QVM_GameConsoleCommand(void)
|
|||
|
||||
//FIXME: if an rcon command from someone on the server, mvdsv sets self to match the ip of that player
|
||||
//this is not required (broken by proxies anyway) but is a nice handy feature
|
||||
|
||||
|
||||
pr_global_struct->time = sv.world.physicstime;
|
||||
oldself = pr_global_struct->self; //these are usually useless
|
||||
oldother = pr_global_struct->other; //but its possible that someone makes a mod that depends on the 'mod' command working via redirectcmd+co
|
||||
|
|
|
@ -1097,7 +1097,7 @@ extern vfsfile_t *sv_fraglogfile;
|
|||
//===========================================================
|
||||
|
||||
void SV_AddDebugPolygons(void);
|
||||
const char *SV_CheckRejectConnection(netadr_t *adr, const char *uinfo, unsigned int protocol, unsigned int pext1, unsigned int pext2, char *guid);
|
||||
const char *SV_CheckRejectConnection(netadr_t *adr, const char *uinfo, unsigned int protocol, unsigned int pext1, unsigned int pext2, unsigned int ezpext1, char *guid);
|
||||
|
||||
//
|
||||
//sv_ccmds.c
|
||||
|
@ -1159,7 +1159,7 @@ typedef struct
|
|||
#endif
|
||||
unsigned int ftepext1;
|
||||
unsigned int ftepext2;
|
||||
// unsigned int ezpext1;
|
||||
unsigned int ezpext1;
|
||||
int qport; //part of the qw protocol to avoid issues with buggy routers that periodically renumber cl2sv ports.
|
||||
#ifdef HUFFNETWORK
|
||||
int huffcrc; //network compression stuff
|
||||
|
|
|
@ -379,6 +379,15 @@ static void SV_Give_f (void)
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(HAVE_LEGACY) && defined(HAVE_SERVER)
|
||||
static void SV_redundantcommand_f(void)
|
||||
{
|
||||
if (cl_warncmd.ival)
|
||||
Con_Printf("%s is obsolete, redundant, or otherwise outdated.\n", Cmd_Argv(0));
|
||||
}
|
||||
#endif
|
||||
|
||||
static int QDECL ShowMapList (const char *name, qofs_t flags, time_t mtime, void *parm, searchpathfuncs_t *spath)
|
||||
{
|
||||
const char *levelshots[] =
|
||||
|
@ -2337,6 +2346,7 @@ void SV_Serverinfo_f (void)
|
|||
{
|
||||
Con_TPrintf ("Server info settings:\n");
|
||||
InfoBuf_Print (&svs.info, "");
|
||||
Con_Printf("[%u]\n", (unsigned int)svs.info.totalsize);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2426,6 +2436,7 @@ static void SV_Localinfo_f (void)
|
|||
{
|
||||
Con_TPrintf ("Local info settings:\n");
|
||||
InfoBuf_Print (&svs.localinfo, "");
|
||||
Con_Printf("[%u]\n", (unsigned int)svs.localinfo.totalsize);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3197,6 +3208,16 @@ void SV_InitOperatorCommands (void)
|
|||
Cmd_AddCommand ("listmaps", SV_MapList_f);
|
||||
Cmd_AddCommand ("maplist", SV_MapList_f);
|
||||
Cmd_AddCommand ("maps", SV_MapList_f);
|
||||
#if defined(HAVE_LEGACY) && defined(HAVE_SERVER)
|
||||
Cmd_AddCommandD ("check_maps", SV_redundantcommand_f, "Obsolete, specific to ktpro. Modern mods should use search_begin instead.");
|
||||
Cmd_AddCommandD ("sys_select_timeout", SV_redundantcommand_f, "Redundant - server will throttle according to tick rates instead.");
|
||||
Cmd_AddCommandD ("sv_downloadchunksperframe", SV_redundantcommand_f, "Flawed - downloads instead proceed at the client's drate (or rate) setting instead of ignoring it entirely.");
|
||||
Cmd_AddCommandD ("sv_speedcheck", SV_redundantcommand_f, "Obsolete - movetime is instead metered over time, instead of randomly kicking everyone due to dodgy timer hardware on the server.");
|
||||
Cmd_AddCommandD ("sv_enableprofile", SV_redundantcommand_f, "Debug setting that is not implemented.");
|
||||
Cmd_AddCommandD ("sv_progsname", SV_redundantcommand_f, "Use sv_progs instead.");
|
||||
Cmd_AddCommandD ("download_map_url", SV_redundantcommand_f, "Redundant - individual maps will probably download faster than the user can open a browser at the given url.");
|
||||
Cmd_AddCommandD ("sv_progtype", SV_redundantcommand_f, "Use sv_progs instead. Using to block .dll loading is insufficient with buggy clients around.");
|
||||
#endif
|
||||
|
||||
Cmd_AddCommand ("heartbeat", SV_Heartbeat_f);
|
||||
|
||||
|
|
|
@ -38,8 +38,6 @@ int sv_max_staticentities;
|
|||
staticsound_state_t *sv_staticsounds;
|
||||
int sv_max_staticsounds;
|
||||
|
||||
char localinfo[MAX_LOCALINFO_STRING+1]; // local game info
|
||||
|
||||
extern cvar_t skill;
|
||||
extern cvar_t sv_cheats;
|
||||
extern cvar_t sv_bigcoords;
|
||||
|
|
|
@ -118,6 +118,7 @@ cvar_t sv_listen_dp = CVARD("sv_listen_dp", "0", "Allows the server to respond
|
|||
cvar_t sv_listen_q3 = CVAR("sv_listen_q3", "0");
|
||||
#endif
|
||||
cvar_t sv_reconnectlimit = CVARD("sv_reconnectlimit", "0", "Blocks dupe connection within the specified length of time .");
|
||||
cvar_t sv_use_dns = CVARD("sv_use_dns", "", "Performs a reverse-dns lookup in order to report actual ip addresses of clients.");
|
||||
extern cvar_t net_enable_dtls;
|
||||
cvar_t sv_reportheartbeats = CVARD("sv_reportheartbeats", "2", "Print a notice each time a heartbeat is sent to a master server. When set to 2, the message will be displayed once.");
|
||||
cvar_t sv_heartbeat_interval = CVARD("sv_heartbeat_interval", "110", "Interval between heartbeats. Low values are abusive, high values may cause NAT/ghost issues.");
|
||||
|
@ -160,7 +161,7 @@ cvar_t fraglimit = CVARF("fraglimit", "" , CVAR_SERVERINFO);
|
|||
cvar_t timelimit = CVARF("timelimit", "" , CVAR_SERVERINFO);
|
||||
cvar_t teamplay = CVARF("teamplay", "" , CVAR_SERVERINFO);
|
||||
cvar_t samelevel = CVARF("samelevel", "" , CVAR_SERVERINFO);
|
||||
cvar_t sv_playerslots = CVARAD("sv_playerslots", "",
|
||||
cvar_t sv_playerslots = CVARAD("sv_playerslots", "",
|
||||
"maxplayers", "Specify maximum number of player/spectator/bot slots, new value takes effect on the next map (this may result in players getting kicked). This should generally be set to maxclients+maxspectators. Leave blank for a default value.\nMaximum value of "STRINGIFY(MAX_CLIENTS)". Values above 16 will result in issues with vanilla NQ clients. Effective values other than 32 will result in issues with vanilla QW clients.");
|
||||
cvar_t maxclients = CVARAFD("maxclients", "8",
|
||||
"sv_maxclients", CVAR_SERVERINFO, "Specify the maximum number of players allowed on the server at once. Can be changed mid-map.");
|
||||
|
@ -275,6 +276,9 @@ void SV_Shutdown (void)
|
|||
Plug_Shutdown(true);
|
||||
#endif
|
||||
Mod_Shutdown(true);
|
||||
#ifdef PACKAGEMANAGER
|
||||
PM_Shutdown();
|
||||
#endif
|
||||
COM_DestroyWorkerThread();
|
||||
FS_Shutdown();
|
||||
#ifdef PLUGINS
|
||||
|
@ -282,11 +286,8 @@ void SV_Shutdown (void)
|
|||
#endif
|
||||
Cvar_Shutdown();
|
||||
Cmd_Shutdown();
|
||||
#ifdef PACKAGEMANAGER
|
||||
PM_Shutdown();
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
InfoBuf_Clear(&svs.info, true);
|
||||
InfoBuf_Clear(&svs.localinfo, true);
|
||||
|
||||
|
@ -353,7 +354,6 @@ void VARGS SV_Error (char *error, ...)
|
|||
sv.spawned_observer_slots = 0;
|
||||
|
||||
|
||||
SV_UnspawnServer();
|
||||
#ifndef SERVERONLY
|
||||
if (cls.state)
|
||||
{
|
||||
|
@ -367,12 +367,15 @@ void VARGS SV_Error (char *error, ...)
|
|||
extern cvar_t cl_disconnectreason;
|
||||
extern jmp_buf host_abort;
|
||||
SCR_EndLoadingPlaque();
|
||||
SV_UnspawnServer();
|
||||
Cvar_Set(&cl_disconnectreason, va("SV_Error: %s", string));
|
||||
inerror=false;
|
||||
longjmp (host_abort, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
sys_nounload = true;
|
||||
SV_UnspawnServer();
|
||||
SV_Shutdown ();
|
||||
|
||||
Sys_Error ("SV_Error: %s\n",string);
|
||||
|
@ -987,7 +990,7 @@ void SV_FullClientUpdate (client_t *client, client_t *to)
|
|||
{
|
||||
for (i = 0; i < sv.allocated_client_slots; i++)
|
||||
{
|
||||
SV_FullClientUpdate(client, &svs.clients[i]);
|
||||
SV_FullClientUpdate(client, &svs.clients[i]);
|
||||
}
|
||||
#ifdef MVD_RECORDING
|
||||
if (sv.mvdrecording)
|
||||
|
@ -1286,7 +1289,7 @@ static void SVC_GetInfo (char *challenge, int fullstatus)
|
|||
Info_SetValueForKey(resp, "sv_maxclients", maxclients.string, sizeof(response) - (resp-response));
|
||||
Info_SetValueForKey(resp, "mapname", InfoBuf_ValueForKey(&svs.info, "map"), sizeof(response) - (resp-response));
|
||||
resp += strlen(resp);
|
||||
//now include the full/regular serverinfo
|
||||
//now include the full/regular serverinfo
|
||||
resp += InfoBuf_ToString(&svs.info, resp, sizeof(response) - (resp-response), prioritykeys, ignorekeys, NULL, NULL, NULL);
|
||||
*resp = 0;
|
||||
//and any possibly-long qc status string
|
||||
|
@ -2131,20 +2134,23 @@ void SV_ClientProtocolExtensionsChanged(client_t *client)
|
|||
|
||||
|
||||
//void NET_AdrToStringResolve (netadr_t *adr, void (*resolved)(void *ctx, void *data, size_t a, size_t b), void *ctx, size_t a, size_t b);
|
||||
/*static void SV_UserDNSResolved(void *ctx, void *data, size_t idx, size_t uid)
|
||||
static void SV_UserDNSResolved(void *ctx, void *data, size_t idx, size_t uid)
|
||||
{
|
||||
if (idx < svs.allocated_client_slots)
|
||||
{
|
||||
if (svs.clients[idx].userid == uid)
|
||||
client_t *cl = &svs.clients[idx];
|
||||
if (cl->userid == uid)
|
||||
{
|
||||
Z_Free(svs.clients[idx].reversedns);
|
||||
svs.clients[idx].reversedns = data;
|
||||
Z_Free(cl->reversedns);
|
||||
cl->reversedns = data;
|
||||
SV_LogPlayer(cl, va("dns %s", cl->reversedns));
|
||||
return;
|
||||
}
|
||||
}
|
||||
//client ran away before the dns completed
|
||||
Con_DPrintf("stale dns lookup result: %s\n", (char*)data);
|
||||
Z_Free(data);
|
||||
}*/
|
||||
}
|
||||
|
||||
client_t *SV_AddSplit(client_t *controller, char *info, int id)
|
||||
{
|
||||
|
@ -2161,7 +2167,7 @@ client_t *SV_AddSplit(client_t *controller, char *info, int id)
|
|||
SV_PrintToClient(controller, PRINT_HIGH, "Your client doesn't support splitscreen\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
for (curclients = 0, prev = cl = controller; cl; cl = cl->controlled)
|
||||
{
|
||||
prev = cl;
|
||||
|
@ -2705,7 +2711,7 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info)
|
|||
temp.edict = ent;
|
||||
|
||||
{
|
||||
const char *reject = SV_CheckRejectConnection(&info->adr, info->userinfo, info->protocol, info->ftepext1, info->ftepext2, info->guid);
|
||||
const char *reject = SV_CheckRejectConnection(&info->adr, info->userinfo, info->protocol, info->ftepext1, info->ftepext2, info->ezpext1, info->guid);
|
||||
if (reject)
|
||||
{
|
||||
SV_RejectMessage(info->protocol, "%s", reject);
|
||||
|
@ -2764,8 +2770,6 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info)
|
|||
newcl->userinfo.ChangeCTX = &svs.clients[i].userinfo;
|
||||
InfoBuf_FromString(&newcl->userinfo, info->userinfo, false);
|
||||
|
||||
// NET_AdrToStringResolve(&adr, SV_UserDNSResolved, NULL, newcl-svs.clients, newcl->userid);
|
||||
|
||||
newcl->challenge = info->challenge;
|
||||
newcl->zquake_extensions = atoi(InfoBuf_ValueForKey(&newcl->userinfo, "*z_ext"));
|
||||
InfoBuf_SetStarKey(&newcl->userinfo, "*z_ext", "");
|
||||
|
@ -3051,6 +3055,10 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info)
|
|||
#ifdef NQPROT
|
||||
newcl->netchan.incoming_reliable_sequence = info->expectedreliablesequence;
|
||||
#endif
|
||||
|
||||
if (sv_use_dns.ival)
|
||||
NET_AdrToStringResolve(&info->adr, SV_UserDNSResolved, NULL, newcl-svs.clients, newcl->userid);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3085,6 +3093,7 @@ void SVC_DirectConnect(int expectedreliablesequence)
|
|||
info.mtu = 0;
|
||||
info.ftepext1 = 0;
|
||||
info.ftepext2 = 0;
|
||||
info.ezpext1 = 0;
|
||||
*info.guid = 0;
|
||||
|
||||
if (*Cmd_Argv(1) == '\\')
|
||||
|
@ -3232,7 +3241,7 @@ void SVC_DirectConnect(int expectedreliablesequence)
|
|||
else
|
||||
{
|
||||
//fte: connectN is no longer supported (multiple userinfos packed into a single packet was a bad idea when userinfos can be so large
|
||||
if (atoi(Cmd_Argv(0)+7))
|
||||
/*if (atoi(Cmd_Argv(0)+7))
|
||||
{
|
||||
int numssclients = atoi(Cmd_Argv(0)+7);
|
||||
if (numssclients!=1)
|
||||
|
@ -3241,7 +3250,7 @@ void SVC_DirectConnect(int expectedreliablesequence)
|
|||
Con_TPrintf ("* rejected connect from old client\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
version = atoi(Cmd_Argv(1));
|
||||
if (version >= 31 && version <= 34)
|
||||
|
@ -3375,6 +3384,13 @@ void SVC_DirectConnect(int expectedreliablesequence)
|
|||
Con_DPrintf("Client supports 0x%x fte2 extensions\n", info.ftepext2);
|
||||
}
|
||||
break;
|
||||
case PROTOCOL_VERSION_EZQUAKE1:
|
||||
if (info.protocol == SCP_QUAKEWORLD)
|
||||
{
|
||||
info.ezpext1 = Q_atoi(Cmd_Argv(1));
|
||||
Con_DPrintf("Client supports 0x%x ez1 extensions\n", info.ezpext1);
|
||||
}
|
||||
break;
|
||||
case PROTOCOL_VERSION_HUFFMAN:
|
||||
#ifdef HUFFNETWORK
|
||||
info.huffcrc = Q_atoi(Cmd_Argv(1));
|
||||
|
@ -4938,6 +4954,8 @@ float SV_Frame (void)
|
|||
svs.framenum = 0;
|
||||
|
||||
delay = sv_maxtic.value;
|
||||
if (isDedicated && sv.spawned_client_slots == 0 && sv.spawned_observer_slots == 0)
|
||||
delay = max(delay, 1); //when idle, don't keep waking up for no reason
|
||||
|
||||
// keep the random time dependent
|
||||
rand ();
|
||||
|
@ -4953,7 +4971,7 @@ float SV_Frame (void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
isidle = !isDedicated && sv.allocated_client_slots == 1 && Key_Dest_Has(~kdm_game) && cls.state == ca_active;
|
||||
/*server is effectively paused in SP/coop if there are no clients/spectators*/
|
||||
if (sv.spawned_client_slots == 0 && sv.spawned_observer_slots == 0 && !deathmatch.ival)
|
||||
|
@ -5337,6 +5355,7 @@ void SV_InitLocal (void)
|
|||
#endif
|
||||
sv_listen_qw.restriction = RESTRICT_MAX; //no disabling this over rcon.
|
||||
Cvar_Register (&sv_reconnectlimit, cvargroup_servercontrol);
|
||||
Cvar_Register (&sv_use_dns, cvargroup_servercontrol);
|
||||
Cvar_Register (&fraglog_public, cvargroup_servercontrol);
|
||||
|
||||
SVNET_RegisterCvars();
|
||||
|
|
|
@ -2596,6 +2596,8 @@ qboolean SV_Physics (void)
|
|||
}
|
||||
|
||||
maxtics = sv_limittics.ival;
|
||||
if (sv.spawned_observer_slots==0&&sv.spawned_client_slots==0)
|
||||
maxtics = 1; //no players on the server. let timings slide
|
||||
|
||||
// don't bother running a frame if sys_ticrate seconds haven't passed
|
||||
while (1)
|
||||
|
|
|
@ -1107,10 +1107,10 @@ int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const
|
|||
return Sys_EnumerateFiles2(truepath, strlen(gpath)+1, match, func, parm, spath);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Sys_CloseLibrary(dllhandle_t *lib)
|
||||
{
|
||||
if (sys_nounload)
|
||||
return;
|
||||
dlclose((void*)lib);
|
||||
}
|
||||
dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs)
|
||||
|
|
|
@ -36,12 +36,12 @@ usercmd_t cmd;
|
|||
|
||||
void QDECL SV_NQPhysicsUpdate(cvar_t *var, char *oldvalue)
|
||||
{
|
||||
if (!strcmp(var->string, "auto"))
|
||||
if (!strcmp(var->string, "auto") || !strcmp(var->string, ""))
|
||||
{ //prediction requires nq physics, so use it by default in multiplayer.
|
||||
if (progstype == PROG_QW || (!isDedicated && sv.allocated_client_slots > 1))
|
||||
var->ival = 1;
|
||||
else
|
||||
var->ival = 0;
|
||||
else
|
||||
var->ival = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ cvar_t cmd_allowaccess = CVAR("cmd_allowaccess", "0"); //set to 1 to allow cmd t
|
|||
cvar_t cmd_gamecodelevel = CVAR("cmd_gamecodelevel", STRINGIFY(RESTRICT_LOCAL)); //execution level which gamecode is told about (for unrecognised commands)
|
||||
|
||||
cvar_t sv_pure = CVARFD("sv_pure", "", CVAR_SERVERINFO, "The most evil cvar in the world, many clients will ignore this.\n0=standard quake rules.\n1=clients should prefer files within packages present on the server.\n2=clients should use *only* files within packages present on the server.\nDue to quake 1.01/1.06 differences, a setting of 2 only works in total conversions.");
|
||||
cvar_t sv_nqplayerphysics = CVARAFCD("sv_nqplayerphysics", "0", "sv_nomsec", 0, SV_NQPhysicsUpdate, "Disable player prediction and run NQ-style player physics instead. This can be used for compatibility with mods that expect exact behaviour.");
|
||||
cvar_t sv_nqplayerphysics = CVARAFCD("sv_nqplayerphysics", "auto", "sv_nomsec", 0, SV_NQPhysicsUpdate, "Disable player prediction and run NQ-style player physics instead. This can be used for compatibility with mods that expect exact behaviour.");
|
||||
|
||||
#ifdef HAVE_LEGACY
|
||||
cvar_t sv_brokenmovetypes = CVARD("sv_brokenmovetypes", "0", "Emulate vanilla quakeworld by forcing MOVETYPE_WALK on all players. Shouldn't be used for any games other than QuakeWorld.");
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
//FIXME: instead of switching rendertargets and back, we should be using an alternative queue.
|
||||
|
||||
#define PERMUTATION_BEM_FP16 (1u<<12)
|
||||
#define PERMUTATION_BEM_MULTISAMPLE (1u<<13)
|
||||
#define PERMUTATION_BEM_DEPTHONLY (1u<<14)
|
||||
#define PERMUTATION_BEM_WIREFRAME (1u<<15)
|
||||
|
||||
|
@ -41,7 +43,7 @@ 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 unsigned int vk_usedynamicstaging;
|
||||
|
||||
#ifdef RTLIGHTS
|
||||
static void VK_TerminateShadowMap(void);
|
||||
|
@ -53,11 +55,31 @@ static void R_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist
|
|||
#define MAX_TMUS 32
|
||||
|
||||
extern texid_t r_whiteimage, missing_texture_gloss, missing_texture_normal;
|
||||
texid_t r_blackimage;
|
||||
extern texid_t r_blackimage;
|
||||
|
||||
static void BE_RotateForEntity (const entity_t *e, const model_t *mod);
|
||||
void VKBE_SetupLightCBuffer(dlight_t *l, vec3_t colour);
|
||||
|
||||
#ifdef VK_EXT_debug_utils
|
||||
static void DebugSetName(VkObjectType objtype, uint64_t handle, const char *name)
|
||||
{
|
||||
if (vkSetDebugUtilsObjectNameEXT)
|
||||
{
|
||||
VkDebugUtilsObjectNameInfoEXT info =
|
||||
{
|
||||
VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
|
||||
NULL,
|
||||
objtype,
|
||||
handle,
|
||||
name?name:"UNNAMED"
|
||||
};
|
||||
vkSetDebugUtilsObjectNameEXT(vk.device, &info);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define DebugSetName(t,h,n)
|
||||
#endif
|
||||
|
||||
/*========================================== tables for deforms =====================================*/
|
||||
#define frand() (rand()*(1.0/RAND_MAX))
|
||||
#define FTABLE_SIZE 1024
|
||||
|
@ -1069,11 +1091,13 @@ qboolean VK_LoadBlob(program_t *prog, void *blobdata, const char *name)
|
|||
info.codeSize = blob->vertlength;
|
||||
info.pCode = (uint32_t*)((char*)blob+blob->vertoffset);
|
||||
VkAssert(vkCreateShaderModule(vk.device, &info, vkallocationcb, &vert));
|
||||
DebugSetName(VK_OBJECT_TYPE_SHADER_MODULE, (uint64_t)vert, name);
|
||||
|
||||
info.flags = 0;
|
||||
info.codeSize = blob->fraglength;
|
||||
info.pCode = (uint32_t*)((char*)blob+blob->fragoffset);
|
||||
VkAssert(vkCreateShaderModule(vk.device, &info, vkallocationcb, &frag));
|
||||
DebugSetName(VK_OBJECT_TYPE_SHADER_MODULE, (uint64_t)frag, name);
|
||||
|
||||
prog->vert = vert;
|
||||
prog->frag = frag;
|
||||
|
@ -1253,14 +1277,6 @@ void VKBE_Init(void)
|
|||
|
||||
FTable_Init();
|
||||
|
||||
{
|
||||
unsigned char bibuf[4*4*4] = {0};
|
||||
if (!qrenderer)
|
||||
r_blackimage = r_nulltex;
|
||||
else
|
||||
r_blackimage = R_LoadTexture("$blackimage", 4, 4, TF_RGBA32, bibuf, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA);
|
||||
}
|
||||
|
||||
shaderstate.depthonly = R_RegisterShader("depthonly", SUF_NONE,
|
||||
"{\n"
|
||||
"program depthonly\n"
|
||||
|
@ -2828,7 +2844,10 @@ static void BE_CreatePipeline(program_t *p, unsigned int shaderflags, unsigned i
|
|||
}
|
||||
|
||||
ms.pSampleMask = NULL;
|
||||
ms.rasterizationSamples = vk.multisamplebits;
|
||||
if (permu & PERMUTATION_BEM_MULTISAMPLE)
|
||||
ms.rasterizationSamples = vk.multisamplebits;
|
||||
else
|
||||
ms.rasterizationSamples = 1;
|
||||
// ms.sampleShadingEnable = VK_TRUE; //call the fragment shader multiple times, instead of just once per final pixel
|
||||
// ms.minSampleShading = 0.25;
|
||||
ds.depthTestEnable = (blendflags&SBITS_MISC_NODEPTHTEST)?VK_FALSE:VK_TRUE;
|
||||
|
@ -3017,7 +3036,12 @@ static void BE_CreatePipeline(program_t *p, unsigned int shaderflags, unsigned i
|
|||
pipeCreateInfo.pColorBlendState = &cb;
|
||||
pipeCreateInfo.pDynamicState = &dyn;
|
||||
pipeCreateInfo.layout = p->layout;
|
||||
pipeCreateInfo.renderPass = (permu&PERMUTATION_BEM_DEPTHONLY)?vk.shadow_renderpass:vk.renderpass[0];
|
||||
i = (permu&PERMUTATION_BEM_DEPTHONLY)?RP_DEPTHONLY:RP_FULLCLEAR;
|
||||
if (permu&PERMUTATION_BEM_MULTISAMPLE)
|
||||
i |= RP_MULTISAMPLE;
|
||||
if (permu&PERMUTATION_BEM_FP16)
|
||||
i |= RP_FP16;
|
||||
pipeCreateInfo.renderPass = VK_GetRenderPass(i);
|
||||
pipeCreateInfo.subpass = 0;
|
||||
pipeCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
|
||||
pipeCreateInfo.basePipelineIndex = -1; //used to create derivatives for pipelines created in the same call.
|
||||
|
@ -3025,6 +3049,7 @@ static void BE_CreatePipeline(program_t *p, unsigned int shaderflags, unsigned i
|
|||
// pipeCreateInfo.flags = VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT;
|
||||
|
||||
err = vkCreateGraphicsPipelines(vk.device, vk.pipelinecache, 1, &pipeCreateInfo, vkallocationcb, &pipe->pipeline);
|
||||
DebugSetName(VK_OBJECT_TYPE_PIPELINE, (uint64_t)pipe->pipeline, p->name);
|
||||
|
||||
if (err)
|
||||
{ //valid err values are VK_ERROR_OUT_OF_HOST_MEMORY, VK_ERROR_OUT_OF_DEVICE_MEMORY, VK_ERROR_INVALID_SHADER_NV
|
||||
|
@ -3728,6 +3753,11 @@ void VKBE_SelectMode(backendmode_t mode)
|
|||
shaderstate.mode = mode;
|
||||
shaderstate.modepermutation = 0;
|
||||
|
||||
if (vk.rendertarg->rpassflags & RP_MULTISAMPLE)
|
||||
shaderstate.modepermutation |= PERMUTATION_BEM_MULTISAMPLE;
|
||||
if (vk.rendertarg->rpassflags & RP_FP16)
|
||||
shaderstate.modepermutation |= PERMUTATION_BEM_FP16;
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
default:
|
||||
|
@ -4637,6 +4667,7 @@ struct vkbe_rtpurge
|
|||
{
|
||||
VkFramebuffer framebuffer;
|
||||
vk_image_t colour;
|
||||
vk_image_t mscolour;
|
||||
vk_image_t depth;
|
||||
};
|
||||
static void VKBE_RT_Purge(void *ptr)
|
||||
|
@ -4644,33 +4675,39 @@ static void VKBE_RT_Purge(void *ptr)
|
|||
struct vkbe_rtpurge *ctx = ptr;
|
||||
vkDestroyFramebuffer(vk.device, ctx->framebuffer, vkallocationcb);
|
||||
VK_DestroyVkTexture(&ctx->depth);
|
||||
VK_DestroyVkTexture(&ctx->mscolour);
|
||||
VK_DestroyVkTexture(&ctx->colour);
|
||||
}
|
||||
void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qboolean clear, unsigned int flags)
|
||||
{
|
||||
//sooooo much work...
|
||||
VkImageCreateInfo colour_imginfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
|
||||
VkImageCreateInfo mscolour_imginfo;
|
||||
VkImageCreateInfo depth_imginfo;
|
||||
struct vkbe_rtpurge *purge;
|
||||
static VkClearValue clearvalues[2];
|
||||
static VkClearValue clearvalues[3];
|
||||
|
||||
if (clear)
|
||||
targ->restartinfo.renderPass = vk.renderpass[2];
|
||||
else
|
||||
targ->restartinfo.renderPass = vk.renderpass[1]; //don't care
|
||||
targ->restartinfo.clearValueCount = 2;
|
||||
targ->restartinfo.clearValueCount = 3;
|
||||
targ->depthcleared = true; //will be once its activated.
|
||||
|
||||
if (targ->width == width && targ->height == height && targ->q_colour.flags == flags)
|
||||
if (targ->width == width && targ->height == height && targ->q_colour.flags == flags && (!(targ->rpassflags&RP_MULTISAMPLE))==(targ->mscolour.image==NULL))
|
||||
{
|
||||
if (clear || targ->firstuse)
|
||||
targ->restartinfo.renderPass = VK_GetRenderPass(RP_FULLCLEAR|targ->rpassflags);
|
||||
else
|
||||
targ->restartinfo.renderPass = VK_GetRenderPass(RP_DEPTHCLEAR|targ->rpassflags); //don't care
|
||||
return; //no work to do.
|
||||
}
|
||||
|
||||
if (targ->framebuffer)
|
||||
{ //schedule the old one to be destroyed at the end of the current frame. DIE OLD ONE, DIE!
|
||||
purge = VK_AtFrameEnd(VKBE_RT_Purge, NULL, sizeof(*purge));
|
||||
purge->framebuffer = targ->framebuffer;
|
||||
purge->colour = targ->colour;
|
||||
purge->mscolour = targ->mscolour;
|
||||
purge->depth = targ->depth;
|
||||
memset(&targ->colour, 0, sizeof(targ->colour));
|
||||
memset(&targ->mscolour, 0, sizeof(targ->mscolour));
|
||||
memset(&targ->depth, 0, sizeof(targ->depth));
|
||||
targ->framebuffer = VK_NULL_HANDLE;
|
||||
}
|
||||
|
@ -4686,9 +4723,14 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
|
|||
targ->height = height;
|
||||
|
||||
if (width == 0 && height == 0)
|
||||
{
|
||||
targ->restartinfo.renderPass = NULL;
|
||||
return; //destroyed
|
||||
}
|
||||
targ->restartinfo.renderPass = VK_GetRenderPass(RP_FULLCLEAR|targ->rpassflags);
|
||||
|
||||
colour_imginfo.format = vk.backbufformat;
|
||||
//colour buffer is always 1 sample. if multisampling then we have a hidden 'mscolour' image that is paired with the depth, resolvnig to the 'colour' image.
|
||||
colour_imginfo.format = (targ->rpassflags&RP_FP16)?VK_FORMAT_R16G16B16A16_SFLOAT:vk.backbufformat;
|
||||
colour_imginfo.flags = 0;
|
||||
colour_imginfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
colour_imginfo.extent.width = width;
|
||||
|
@ -4706,16 +4748,20 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
|
|||
VkAssert(vkCreateImage(vk.device, &colour_imginfo, vkallocationcb, &targ->colour.image));
|
||||
|
||||
depth_imginfo = colour_imginfo;
|
||||
depth_imginfo.format = VK_FORMAT_D32_SFLOAT;
|
||||
depth_imginfo.format = vk.depthformat;
|
||||
depth_imginfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT|VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
if (targ->rpassflags&RP_MULTISAMPLE)
|
||||
{
|
||||
mscolour_imginfo = colour_imginfo;
|
||||
depth_imginfo.samples = mscolour_imginfo.samples = vk.multisamplebits;
|
||||
VkAssert(vkCreateImage(vk.device, &mscolour_imginfo, vkallocationcb, &targ->mscolour.image));
|
||||
VK_AllocateBindImageMemory(&targ->mscolour, true);
|
||||
}
|
||||
VkAssert(vkCreateImage(vk.device, &depth_imginfo, vkallocationcb, &targ->depth.image));
|
||||
|
||||
VK_AllocateBindImageMemory(&targ->colour, true);
|
||||
VK_AllocateBindImageMemory(&targ->depth, true);
|
||||
|
||||
// set_image_layout(vk.frame->cbuf, targ->colour.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
// set_image_layout(vk.frame->cbuf, targ->depth.image, VK_IMAGE_ASPECT_DEPTH_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
|
||||
{
|
||||
VkImageViewCreateInfo ivci = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
|
||||
ivci.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||
|
@ -4734,6 +4780,14 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
|
|||
ivci.image = targ->colour.image;
|
||||
VkAssert(vkCreateImageView(vk.device, &ivci, vkallocationcb, &targ->colour.view));
|
||||
|
||||
if (targ->rpassflags&RP_MULTISAMPLE)
|
||||
{
|
||||
ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
ivci.format = mscolour_imginfo.format;
|
||||
ivci.image = targ->mscolour.image;
|
||||
VkAssert(vkCreateImageView(vk.device, &ivci, vkallocationcb, &targ->mscolour.view));
|
||||
}
|
||||
|
||||
ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
ivci.format = depth_imginfo.format;
|
||||
ivci.image = targ->depth.image;
|
||||
|
@ -4771,8 +4825,8 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
|
|||
VkFramebufferCreateInfo fbinfo = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO};
|
||||
VkImageView attachments[3] = {targ->colour.view, targ->depth.view, targ->mscolour.view};
|
||||
fbinfo.flags = 0;
|
||||
fbinfo.renderPass = vk.renderpass[2];
|
||||
fbinfo.attachmentCount = (vk.multisamplebits!=VK_SAMPLE_COUNT_1_BIT)?3:2;
|
||||
fbinfo.renderPass = targ->restartinfo.renderPass;
|
||||
fbinfo.attachmentCount = (targ->rpassflags&RP_MULTISAMPLE)?3:2;
|
||||
fbinfo.pAttachments = attachments;
|
||||
fbinfo.width = width;
|
||||
fbinfo.height = height;
|
||||
|
@ -4826,9 +4880,9 @@ void VKBE_RT_Gen_Cube(struct vk_rendertarg_cube *targ, uint32_t size, qboolean c
|
|||
for (f = 0; f < 6; f++)
|
||||
{
|
||||
if (clear)
|
||||
targ->face[f].restartinfo.renderPass = vk.renderpass[2];
|
||||
targ->face[f].restartinfo.renderPass = VK_GetRenderPass(RP_FULLCLEAR|targ->face[f].rpassflags);
|
||||
else
|
||||
targ->face[f].restartinfo.renderPass = vk.renderpass[1]; //don't care
|
||||
targ->face[f].restartinfo.renderPass = VK_GetRenderPass(RP_DEPTHCLEAR|targ->face[f].rpassflags); //don't care
|
||||
targ->face[f].restartinfo.clearValueCount = 2;
|
||||
}
|
||||
|
||||
|
@ -4972,7 +5026,7 @@ void VKBE_RT_Gen_Cube(struct vk_rendertarg_cube *targ, uint32_t size, qboolean c
|
|||
VkFramebufferCreateInfo fbinfo = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO};
|
||||
VkImageView attachments[2] = {targ->face[f].colour.view, targ->face[f].depth.view};
|
||||
fbinfo.flags = 0;
|
||||
fbinfo.renderPass = vk.renderpass[2];
|
||||
fbinfo.renderPass = VK_GetRenderPass(RP_FULLCLEAR|targ->face[f].rpassflags);
|
||||
fbinfo.attachmentCount = countof(attachments);
|
||||
fbinfo.pAttachments = attachments;
|
||||
fbinfo.width = size;
|
||||
|
@ -5033,12 +5087,14 @@ void VKBE_RT_Begin(struct vk_rendertarg *targ)
|
|||
targ->prevtarg = vk.rendertarg;
|
||||
vk.rendertarg = targ;
|
||||
|
||||
VKBE_SelectMode(shaderstate.mode);
|
||||
|
||||
vkCmdBeginRenderPass(vk.rendertarg->cbuf, &targ->restartinfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
//future reuse shouldn't clear stuff
|
||||
if (targ->restartinfo.clearValueCount)
|
||||
{
|
||||
targ->depthcleared = true;
|
||||
targ->restartinfo.renderPass = vk.renderpass[0];
|
||||
targ->restartinfo.renderPass = VK_GetRenderPass(RP_RESUME|targ->rpassflags);
|
||||
targ->restartinfo.clearValueCount = 0;
|
||||
}
|
||||
|
||||
|
@ -5080,6 +5136,8 @@ void VKBE_RT_End(struct vk_rendertarg *targ)
|
|||
|
||||
// VK_Submit_Work(VkCommandBuffer cmdbuf, VkSemaphore semwait, VkPipelineStageFlags semwaitstagemask, VkSemaphore semsignal, VkFence fencesignal, struct vkframe *presentframe, struct vk_fencework *fencedwork)
|
||||
#endif
|
||||
|
||||
VKBE_SelectMode(shaderstate.mode);
|
||||
}
|
||||
|
||||
static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
|
||||
|
@ -5094,8 +5152,6 @@ static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
|
|||
return false;
|
||||
if (shaderstate.mode != BEM_STANDARD && shaderstate.mode != BEM_DEPTHDARK)
|
||||
return false;
|
||||
if (vk.multisamplebits != VK_SAMPLE_COUNT_1_BIT)
|
||||
return false; //multisample rendering can't deal with this.
|
||||
oldbem = shaderstate.mode;
|
||||
oldil = shaderstate.identitylighting;
|
||||
// targ = vk.rendertarg;
|
||||
|
@ -5901,12 +5957,6 @@ static void VK_TerminateShadowMap(void)
|
|||
struct shadowmaps_s *shad;
|
||||
unsigned int sbuf, i;
|
||||
|
||||
if (vk.shadow_renderpass != VK_NULL_HANDLE)
|
||||
{
|
||||
vkDestroyRenderPass(vk.device, vk.shadow_renderpass, vkallocationcb);
|
||||
vk.shadow_renderpass = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
for (sbuf = 0; sbuf < countof(shaderstate.shadow); sbuf++)
|
||||
{
|
||||
shad = &shaderstate.shadow[sbuf];
|
||||
|
@ -5945,7 +5995,7 @@ qboolean VKBE_BeginShadowmap(qboolean isspot, uint32_t width, uint32_t height)
|
|||
unsigned int i;
|
||||
VkFramebufferCreateInfo fbinfo = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO};
|
||||
VkImageCreateInfo imginfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
|
||||
imginfo.format = VK_FORMAT_D32_SFLOAT;
|
||||
imginfo.format = vk.depthformat;
|
||||
imginfo.flags = 0;
|
||||
imginfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
imginfo.extent.width = width;
|
||||
|
@ -5974,48 +6024,8 @@ qboolean VKBE_BeginShadowmap(qboolean isspot, uint32_t width, uint32_t height)
|
|||
VkAssert(vkBindImageMemory(vk.device, shad->image, shad->memory, 0));
|
||||
}
|
||||
|
||||
if (vk.shadow_renderpass == VK_NULL_HANDLE)
|
||||
{
|
||||
VkAttachmentReference depth_reference;
|
||||
VkAttachmentDescription attachments[1] = {{0}};
|
||||
VkSubpassDescription subpass = {0};
|
||||
VkRenderPassCreateInfo rp_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO};
|
||||
|
||||
depth_reference.attachment = 0;
|
||||
depth_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
|
||||
attachments[depth_reference.attachment].format = imginfo.format;
|
||||
attachments[depth_reference.attachment].samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachments[depth_reference.attachment].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
attachments[depth_reference.attachment].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachments[depth_reference.attachment].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachments[depth_reference.attachment].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachments[depth_reference.attachment].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
|
||||
attachments[depth_reference.attachment].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
|
||||
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpass.flags = 0;
|
||||
subpass.inputAttachmentCount = 0;
|
||||
subpass.pInputAttachments = NULL;
|
||||
subpass.colorAttachmentCount = 0;
|
||||
subpass.pColorAttachments = NULL;
|
||||
subpass.pResolveAttachments = NULL;
|
||||
subpass.pDepthStencilAttachment = &depth_reference;
|
||||
subpass.preserveAttachmentCount = 0;
|
||||
subpass.pPreserveAttachments = NULL;
|
||||
|
||||
rp_info.attachmentCount = countof(attachments);
|
||||
rp_info.pAttachments = attachments;
|
||||
rp_info.subpassCount = 1;
|
||||
rp_info.pSubpasses = &subpass;
|
||||
rp_info.dependencyCount = 0;
|
||||
rp_info.pDependencies = NULL;
|
||||
|
||||
VkAssert(vkCreateRenderPass(vk.device, &rp_info, vkallocationcb, &vk.shadow_renderpass));
|
||||
}
|
||||
|
||||
fbinfo.flags = 0;
|
||||
fbinfo.renderPass = vk.shadow_renderpass;
|
||||
fbinfo.renderPass = VK_GetRenderPass(RP_DEPTHONLY);
|
||||
fbinfo.attachmentCount = 1;
|
||||
fbinfo.width = width;
|
||||
fbinfo.height = height;
|
||||
|
@ -6059,7 +6069,7 @@ qboolean VKBE_BeginShadowmap(qboolean isspot, uint32_t width, uint32_t height)
|
|||
}
|
||||
|
||||
shad->buf[i].qimage.vkimage = &shad->buf[i].vimage;
|
||||
shad->buf[i].vimage.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
|
||||
shad->buf[i].vimage.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
fbinfo.pAttachments = &shad->buf[i].vimage.view;
|
||||
VkAssert(vkCreateFramebuffer(vk.device, &fbinfo, vkallocationcb, &shad->buf[i].framebuffer));
|
||||
|
@ -6086,7 +6096,7 @@ qboolean VKBE_BeginShadowmap(qboolean isspot, uint32_t width, uint32_t height)
|
|||
imgbarrier.subresourceRange.layerCount = 1;
|
||||
imgbarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
imgbarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
vkCmdPipelineBarrier(vk.rendertarg->cbuf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, NULL, 0, NULL, 1, &imgbarrier);
|
||||
vkCmdPipelineBarrier(vk.rendertarg->cbuf, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT|VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, &imgbarrier);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -6094,7 +6104,7 @@ qboolean VKBE_BeginShadowmap(qboolean isspot, uint32_t width, uint32_t height)
|
|||
VkRenderPassBeginInfo rpass = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO};
|
||||
clearval.depthStencil.depth = 1;
|
||||
clearval.depthStencil.stencil = 0;
|
||||
rpass.renderPass = vk.shadow_renderpass;
|
||||
rpass.renderPass = VK_GetRenderPass(RP_DEPTHONLY);
|
||||
rpass.framebuffer = shad->buf[sbuf].framebuffer;
|
||||
rpass.renderArea.offset.x = 0;
|
||||
rpass.renderArea.offset.y = 0;
|
||||
|
@ -6206,6 +6216,9 @@ void VKBE_BeginShadowmapFace(void)
|
|||
wrekt.extent.width = viewport.width;
|
||||
wrekt.extent.height = viewport.height;
|
||||
vkCmdSetScissor(vk.rendertarg->cbuf, 0, 1, &wrekt);
|
||||
|
||||
//shadowmaps never multisample...
|
||||
shaderstate.modepermutation &= ~(PERMUTATION_BEM_MULTISAMPLE|PERMUTATION_BEM_FP16);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -74,8 +74,8 @@ static int VK_Submit_Thread(void *arg);
|
|||
#endif
|
||||
static void VK_Submit_DoWork(void);
|
||||
|
||||
static void VK_DestroyRenderPass(void);
|
||||
static void VK_CreateRenderPass(void);
|
||||
static void VK_DestroyRenderPasses(void);
|
||||
VkRenderPass VK_GetRenderPass(int pass);
|
||||
static void VK_Shutdown_PostProc(void);
|
||||
|
||||
struct vulkaninfo_s vk;
|
||||
|
@ -140,6 +140,19 @@ char *VK_VKErrorToString(VkResult err)
|
|||
case VK_ERROR_OUT_OF_POOL_MEMORY_KHR: return "VK_ERROR_OUT_OF_POOL_MEMORY_KHR";
|
||||
case VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR: return "VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR";
|
||||
|
||||
#ifdef VK_EXT_image_drm_format_modifier
|
||||
case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT: return "VK_ERROR_OUT_OF_POOL_MEMORY_KHR";
|
||||
#endif
|
||||
#ifdef VK_EXT_descriptor_indexing
|
||||
case VK_ERROR_FRAGMENTATION_EXT: return "VK_ERROR_OUT_OF_POOL_MEMORY_KHR";
|
||||
#endif
|
||||
#ifdef VK_EXT_global_priority
|
||||
case VK_ERROR_NOT_PERMITTED_EXT: return "VK_ERROR_OUT_OF_POOL_MEMORY_KHR";
|
||||
#endif
|
||||
#ifdef VK_EXT_buffer_device_address
|
||||
case VK_ERROR_INVALID_DEVICE_ADDRESS_EXT: return "VK_ERROR_OUT_OF_POOL_MEMORY_KHR";
|
||||
#endif
|
||||
|
||||
//irrelevant parts of the enum
|
||||
case VK_RESULT_RANGE_SIZE:
|
||||
case VK_RESULT_MAX_ENUM:
|
||||
|
@ -206,6 +219,9 @@ char *DebugAnnotObjectToString(VkObjectType t)
|
|||
case VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX: return "VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX";
|
||||
case VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT: return "VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT";
|
||||
case VK_OBJECT_TYPE_VALIDATION_CACHE_EXT: return "VK_OBJECT_TYPE_VALIDATION_CACHE_EXT";
|
||||
#ifdef VK_NV_ray_tracing
|
||||
case VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV: return "VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV";
|
||||
#endif
|
||||
case VK_OBJECT_TYPE_RANGE_SIZE:
|
||||
case VK_OBJECT_TYPE_MAX_ENUM:
|
||||
break;
|
||||
|
@ -489,6 +505,7 @@ static qboolean VK_CreateSwapChain(void)
|
|||
VkImageView attachments[3];
|
||||
VkFramebufferCreateInfo fb_info = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO};
|
||||
VkSampleCountFlagBits oldms;
|
||||
uint32_t rpassflags = 0;
|
||||
|
||||
VkFormat oldformat = vk.backbufformat;
|
||||
VkFormat olddepthformat = vk.depthformat;
|
||||
|
@ -790,7 +807,7 @@ static qboolean VK_CreateSwapChain(void)
|
|||
|
||||
if (vk.backbufformat != swapinfo.imageFormat)
|
||||
{
|
||||
VK_DestroyRenderPass();
|
||||
VK_DestroyRenderPasses();
|
||||
reloadshaders = true;
|
||||
}
|
||||
vk.backbufformat = swapinfo.imageFormat;
|
||||
|
@ -865,25 +882,24 @@ static qboolean VK_CreateSwapChain(void)
|
|||
oldms = vk.multisamplebits;
|
||||
|
||||
vk.multisamplebits = VK_SAMPLE_COUNT_1_BIT;
|
||||
#ifdef _DEBUG
|
||||
if (vid_multisample.ival>1)
|
||||
{
|
||||
VkSampleCountFlags fl = vk.limits.framebufferColorSampleCounts & vk.limits.framebufferDepthSampleCounts;
|
||||
Con_Printf("Warning: vulkan multisample does not work with rtlights or render targets etc etc\n");
|
||||
// Con_Printf("Warning: vulkan multisample does not work with rtlights or render targets etc etc\n");
|
||||
for (i = 1; i < 30; i++)
|
||||
if ((fl & (1<<i)) && (1<<i) <= vid_multisample.ival)
|
||||
vk.multisamplebits = (1<<i);
|
||||
}
|
||||
#endif
|
||||
|
||||
rpassflags = RP_PRESENTABLE;
|
||||
|
||||
//destroy+recreate the renderpass if something changed that prevents them being compatible (this also requires rebuilding all the pipelines too, which sucks).
|
||||
if (oldms != vk.multisamplebits || oldformat != vk.backbufformat || olddepthformat != vk.depthformat)
|
||||
{
|
||||
VK_DestroyRenderPass();
|
||||
VK_DestroyRenderPasses();
|
||||
reloadshaders = true;
|
||||
}
|
||||
|
||||
VK_CreateRenderPass();
|
||||
if (reloadshaders)
|
||||
{
|
||||
Shader_NeedReload(true);
|
||||
|
@ -894,11 +910,14 @@ static qboolean VK_CreateSwapChain(void)
|
|||
attachments[1] = VK_NULL_HANDLE; //depth
|
||||
attachments[2] = VK_NULL_HANDLE; //mscolour
|
||||
|
||||
fb_info.renderPass = vk.renderpass[0];
|
||||
if (vk.multisamplebits != VK_SAMPLE_COUNT_1_BIT)
|
||||
if (rpassflags & RP_MULTISAMPLE)
|
||||
fb_info.attachmentCount = 3;
|
||||
else
|
||||
{
|
||||
rpassflags &= ~RP_PRESENTABLE;
|
||||
fb_info.attachmentCount = 2;
|
||||
}
|
||||
fb_info.renderPass = VK_GetRenderPass(RP_FULLCLEAR|rpassflags);
|
||||
fb_info.pAttachments = attachments;
|
||||
fb_info.width = swapinfo.imageExtent.width;
|
||||
fb_info.height = swapinfo.imageExtent.height;
|
||||
|
@ -948,7 +967,7 @@ static qboolean VK_CreateSwapChain(void)
|
|||
depthinfo.extent.depth = 1;
|
||||
depthinfo.mipLevels = 1;
|
||||
depthinfo.arrayLayers = 1;
|
||||
depthinfo.samples = vk.multisamplebits;
|
||||
depthinfo.samples = (rpassflags & RP_MULTISAMPLE)?vk.multisamplebits:VK_SAMPLE_COUNT_1_BIT;
|
||||
depthinfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
depthinfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
depthinfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
|
@ -984,7 +1003,7 @@ static qboolean VK_CreateSwapChain(void)
|
|||
}
|
||||
|
||||
//if we're using multisampling, create the intermediate multisample texture that we're actually going to render to.
|
||||
if (vk.multisamplebits != VK_SAMPLE_COUNT_1_BIT)
|
||||
if (rpassflags & RP_MULTISAMPLE)
|
||||
{
|
||||
//mscolour image
|
||||
{
|
||||
|
@ -1047,6 +1066,7 @@ static qboolean VK_CreateSwapChain(void)
|
|||
vid.pixelwidth = swapinfo.imageExtent.width;
|
||||
vid.pixelheight = swapinfo.imageExtent.height;
|
||||
R2D_Console_Resize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1127,7 +1147,7 @@ void VK_UpdateFiltering(image_t *imagelist, int filtermip[3], int filterpic[3],
|
|||
for (i = 0; i < countof(vk.mipcap); i++)
|
||||
vk.mipcap[i] = mipcap[i];
|
||||
vk.lodbias = lodbias;
|
||||
vk.max_anistophy = bound(1.0, anis, vk.max_anistophy_limit);
|
||||
vk.max_anistophy = bound(1.0, anis, vk.limits.maxSamplerAnisotropy);
|
||||
|
||||
while(imagelist)
|
||||
{
|
||||
|
@ -1562,6 +1582,7 @@ void *VK_FencedBegin(void (*passed)(void *work), size_t worksize)
|
|||
cbai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
cbai.commandBufferCount = 1;
|
||||
VkAssert(vkAllocateCommandBuffers(vk.device, &cbai, &w->cbuf));
|
||||
DebugSetName(VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)w->cbuf, "VK_FencedBegin");
|
||||
cmdinf.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
cmdinf.pInheritanceInfo = &cmdinh;
|
||||
vkBeginCommandBuffer(w->cbuf, &cmdinf);
|
||||
|
@ -1996,7 +2017,7 @@ void VK_Set2D(void)
|
|||
VkClearValue clearvalues[1];
|
||||
clearvalues[0].depthStencil.depth = 1.0;
|
||||
clearvalues[0].depthStencil.stencil = 0;
|
||||
rpiinfo.renderPass = vk.renderpass[1];
|
||||
rpiinfo.renderPass = VK_GetRenderPass(RP_CLEARDEPTH);
|
||||
rpiinfo.renderArea.offset.x = r_refdef.pxrect.x;
|
||||
rpiinfo.renderArea.offset.y = r_refdef.pxrect.y;
|
||||
rpiinfo.renderArea.extent.width = r_refdef.pxrect.width;
|
||||
|
@ -2503,10 +2524,13 @@ void VK_R_RenderView (void)
|
|||
|
||||
if (R_CanBloom())
|
||||
r_refdef.flags |= RDF_BLOOM;
|
||||
|
||||
if (vid_hardwaregamma.ival == 4 && (v_gamma.value!=1||v_contrast.value!=1||v_contrastboost.value!=1||v_brightness.value!=0))
|
||||
r_refdef.flags |= RDF_SCENEGAMMA;
|
||||
}
|
||||
|
||||
if (vk.multisamplebits != VK_SAMPLE_COUNT_1_BIT) //these are unsupported right now.
|
||||
r_refdef.flags &= ~(RDF_CUSTOMPOSTPROC|RDF_ANTIALIAS|RDF_BLOOM);
|
||||
// if (vk.multisamplebits != VK_SAMPLE_COUNT_1_BIT) //these are unsupported right now.
|
||||
// r_refdef.flags &= ~(RDF_CUSTOMPOSTPROC|RDF_ANTIALIAS|RDF_BLOOM);
|
||||
|
||||
//
|
||||
// figure out the viewport
|
||||
|
@ -2534,7 +2558,7 @@ void VK_R_RenderView (void)
|
|||
r_refdef.pxrect.maxheight = vid.pixelheight;
|
||||
}
|
||||
|
||||
if (renderscale != 1.0)
|
||||
if (renderscale != 1.0 || vk.multisamplebits != VK_SAMPLE_COUNT_1_BIT)
|
||||
{
|
||||
r_refdef.flags |= RDF_RENDERSCALE;
|
||||
if (renderscale < 0)
|
||||
|
@ -2551,11 +2575,16 @@ void VK_R_RenderView (void)
|
|||
//FIXME: if we're meant to be using msaa, render the scene to an msaa target and then resolve.
|
||||
|
||||
postproc_buf = 0;
|
||||
if (r_refdef.flags & (RDF_ALLPOSTPROC|RDF_RENDERSCALE))
|
||||
if (r_refdef.flags & (RDF_ALLPOSTPROC|RDF_RENDERSCALE|RDF_SCENEGAMMA))
|
||||
{
|
||||
r_refdef.pxrect.x = 0;
|
||||
r_refdef.pxrect.y = 0;
|
||||
rt = &postproc[postproc_buf++%countof(postproc)];
|
||||
rt->rpassflags = 0;
|
||||
if (vk.multisamplebits!=VK_SAMPLE_COUNT_1_BIT)
|
||||
rt->rpassflags |= RP_MULTISAMPLE;
|
||||
if (r_refdef.flags&RDF_SCENEGAMMA) //if we're doing scenegamma here, use an fp16 target for extra precision
|
||||
rt->rpassflags |= RP_FP16;
|
||||
VKBE_RT_Gen(rt, r_refdef.pxrect.width, r_refdef.pxrect.height, false, (r_renderscale.value < 0)?RT_IMAGEFLAGS-IF_LINEAR+IF_NEAREST:RT_IMAGEFLAGS);
|
||||
}
|
||||
else
|
||||
|
@ -2631,6 +2660,40 @@ void VK_R_RenderView (void)
|
|||
if (!vk.scenepp_waterwarp)
|
||||
VK_Init_PostProc();
|
||||
//FIXME: chain renderpasses as required.
|
||||
|
||||
if (r_refdef.flags & RDF_SCENEGAMMA)
|
||||
{
|
||||
shader_t *s = R_RegisterShader("fte_scenegamma", 0,
|
||||
"{\n"
|
||||
"program defaultgammacb\n"
|
||||
"affine\n"
|
||||
"{\n"
|
||||
"map $sourcecolour\n"
|
||||
"nodepthtest\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
r_refdef.flags &= ~RDF_SCENEGAMMA;
|
||||
vk.sourcecolour = &rt->q_colour;
|
||||
if (r_refdef.flags & RDF_ALLPOSTPROC)
|
||||
{
|
||||
rt = &postproc[postproc_buf++];
|
||||
rt->rpassflags = 0;
|
||||
VKBE_RT_Gen(rt, 320, 200, false, RT_IMAGEFLAGS);
|
||||
}
|
||||
else
|
||||
rt = rtscreen;
|
||||
if (rt != rtscreen)
|
||||
VKBE_RT_Begin(rt);
|
||||
R2D_ImageColours (v_gammainverted.ival?v_gamma.value:(1/v_gamma.value), v_contrast.value, v_brightness.value, v_contrastboost.value);
|
||||
R2D_Image(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, 0, 0, 1, 1, s);
|
||||
R2D_ImageColours (1, 1, 1, 1);
|
||||
R2D_Flush();
|
||||
if (rt != rtscreen)
|
||||
VKBE_RT_End(rt);
|
||||
}
|
||||
|
||||
if (r_refdef.flags & RDF_WATERWARP)
|
||||
{
|
||||
r_refdef.flags &= ~RDF_WATERWARP;
|
||||
|
@ -2638,6 +2701,7 @@ void VK_R_RenderView (void)
|
|||
if (r_refdef.flags & RDF_ALLPOSTPROC)
|
||||
{
|
||||
rt = &postproc[postproc_buf++];
|
||||
rt->rpassflags = 0;
|
||||
VKBE_RT_Gen(rt, 320, 200, false, RT_IMAGEFLAGS);
|
||||
}
|
||||
else
|
||||
|
@ -2656,6 +2720,7 @@ void VK_R_RenderView (void)
|
|||
if (r_refdef.flags & RDF_ALLPOSTPROC)
|
||||
{
|
||||
rt = &postproc[postproc_buf++];
|
||||
rt->rpassflags = 0;
|
||||
VKBE_RT_Gen(rt, 320, 200, false, RT_IMAGEFLAGS);
|
||||
}
|
||||
else
|
||||
|
@ -2675,6 +2740,7 @@ void VK_R_RenderView (void)
|
|||
if (r_refdef.flags & RDF_ALLPOSTPROC)
|
||||
{
|
||||
rt = &postproc[postproc_buf++];
|
||||
rt->rpassflags = 0;
|
||||
VKBE_RT_Gen(rt, 320, 200, false, RT_IMAGEFLAGS);
|
||||
}
|
||||
else
|
||||
|
@ -3132,6 +3198,7 @@ VkCommandBuffer VK_AllocFrameCBuf(void)
|
|||
cbai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
cbai.commandBufferCount = frame->maxcbufs - frame->numcbufs;
|
||||
VkAssert(vkAllocateCommandBuffers(vk.device, &cbai, frame->cbufs+frame->numcbufs));
|
||||
DebugSetName(VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)frame->cbufs[frame->numcbufs], "VK_AllocFrameCBuf");
|
||||
}
|
||||
return frame->cbufs[frame->numcbufs++];
|
||||
}
|
||||
|
@ -3192,11 +3259,23 @@ qboolean VK_SCR_GrabBackBuffer(void)
|
|||
else
|
||||
{
|
||||
//friendly wait
|
||||
VkResult err = vkWaitForFences(vk.device, 1, &vk.acquirefences[vk.aquirenext%ACQUIRELIMIT], VK_FALSE, UINT64_MAX);
|
||||
if (err)
|
||||
int failures = 0;
|
||||
for(;;)
|
||||
{
|
||||
if (err == VK_ERROR_DEVICE_LOST)
|
||||
VkResult err = vkWaitForFences(vk.device, 1, &vk.acquirefences[vk.aquirenext%ACQUIRELIMIT], VK_FALSE, 1000000000);
|
||||
|
||||
if (err == VK_SUCCESS)
|
||||
break;
|
||||
else if (err == VK_TIMEOUT)
|
||||
{
|
||||
if (++failures == 5)
|
||||
Sys_Error("waiting for fence for over 5 seconds. Assuming bug.");
|
||||
continue;
|
||||
}
|
||||
else if (err == VK_ERROR_DEVICE_LOST)
|
||||
Sys_Error("Vulkan device lost");
|
||||
else if (err != VK_ERROR_OUT_OF_HOST_MEMORY && err != VK_ERROR_OUT_OF_DEVICE_MEMORY)
|
||||
Sys_Error("vkWaitForFences returned unspecified result: %s", VK_VKErrorToString(err));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -3250,7 +3329,7 @@ qboolean VK_SCR_GrabBackBuffer(void)
|
|||
|
||||
// vkCmdWriteTimestamp(vk.frame->cbuf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, querypool, vk.bufferidx*2+0);
|
||||
|
||||
if (vk.multisamplebits == VK_SAMPLE_COUNT_1_BIT)
|
||||
if (!(vk.rendertarg->rpassflags & RP_PRESENTABLE))
|
||||
{
|
||||
VkImageMemoryBarrier imgbarrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER};
|
||||
imgbarrier.pNext = NULL;
|
||||
|
@ -3271,7 +3350,6 @@ qboolean VK_SCR_GrabBackBuffer(void)
|
|||
imgbarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
imgbarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
imgbarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
vk.frame->backbuf->firstuse = false;
|
||||
}
|
||||
vk.rendertarg->colour.layout = imgbarrier.newLayout;
|
||||
vkCmdPipelineBarrier(vk.rendertarg->cbuf, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, NULL, 0, NULL, 1, &imgbarrier);
|
||||
|
@ -3295,6 +3373,7 @@ qboolean VK_SCR_GrabBackBuffer(void)
|
|||
}
|
||||
|
||||
{
|
||||
int rp = vk.frame->backbuf->rpassflags;
|
||||
VkClearValue clearvalues[3];
|
||||
extern cvar_t r_clear;
|
||||
VkRenderPassBeginInfo rpbi = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO};
|
||||
|
@ -3308,7 +3387,7 @@ qboolean VK_SCR_GrabBackBuffer(void)
|
|||
clearvalues[1].depthStencil.depth = 1.0;
|
||||
clearvalues[1].depthStencil.stencil = 0;
|
||||
|
||||
if (vk.multisamplebits != VK_SAMPLE_COUNT_1_BIT)
|
||||
if (rp & RP_MULTISAMPLE)
|
||||
{
|
||||
clearvalues[2].color.float32[0] = !!(r_clear.ival & 1);
|
||||
clearvalues[2].color.float32[1] = !!(r_clear.ival & 2);
|
||||
|
@ -3319,10 +3398,10 @@ qboolean VK_SCR_GrabBackBuffer(void)
|
|||
else
|
||||
rpbi.clearValueCount = 2;
|
||||
|
||||
if (r_clear.ival)
|
||||
rpbi.renderPass = vk.renderpass[2];
|
||||
if (r_clear.ival || vk.frame->backbuf->firstuse)
|
||||
rpbi.renderPass = VK_GetRenderPass(RP_FULLCLEAR|rp);
|
||||
else
|
||||
rpbi.renderPass = vk.renderpass[1]; //may still clear
|
||||
rpbi.renderPass = VK_GetRenderPass(RP_DEPTHCLEAR|rp);
|
||||
rpbi.framebuffer = vk.frame->backbuf->framebuffer;
|
||||
rpbi.renderArea.offset.x = 0;
|
||||
rpbi.renderArea.offset.y = 0;
|
||||
|
@ -3336,10 +3415,11 @@ qboolean VK_SCR_GrabBackBuffer(void)
|
|||
|
||||
rpbi.clearValueCount = 0;
|
||||
rpbi.pClearValues = NULL;
|
||||
rpbi.renderPass = vk.renderpass[0];
|
||||
rpbi.renderPass = VK_GetRenderPass(RP_RESUME|rp);
|
||||
vk.rendertarg->restartinfo = rpbi;
|
||||
vk.rendertarg->depthcleared = true;
|
||||
}
|
||||
vk.frame->backbuf->firstuse = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -3495,7 +3575,7 @@ qboolean VK_SCR_UpdateScreen (void)
|
|||
vkCmdCopyImageToBuffer(vk.frame->cbuf, vk.frame->backbuf->colour.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1, ®ion);
|
||||
}*/
|
||||
|
||||
if (vk.multisamplebits == VK_SAMPLE_COUNT_1_BIT)
|
||||
if (!(vk.frame->backbuf->rpassflags & RP_PRESENTABLE))
|
||||
{
|
||||
VkImageMemoryBarrier imgbarrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER};
|
||||
imgbarrier.pNext = NULL;
|
||||
|
@ -3553,7 +3633,7 @@ void VKBE_RenderToTextureUpdate2d(qboolean destchanged)
|
|||
{
|
||||
}
|
||||
|
||||
static void VK_DestroyRenderPass(void)
|
||||
static void VK_DestroyRenderPasses(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < countof(vk.renderpass); i++)
|
||||
|
@ -3565,112 +3645,127 @@ static void VK_DestroyRenderPass(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
static void VK_CreateRenderPass(void)
|
||||
VkRenderPass VK_GetRenderPass(int pass)
|
||||
{
|
||||
int pass;
|
||||
int numattachments;
|
||||
static VkAttachmentReference color_reference;
|
||||
static VkAttachmentReference depth_reference;
|
||||
static VkAttachmentReference resolve_reference;
|
||||
static VkAttachmentDescription attachments[3] = {{0}};
|
||||
static VkSubpassDescription subpass = {0};
|
||||
static VkRenderPassCreateInfo rp_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO};
|
||||
static VkAttachmentReference color_reference;
|
||||
static VkAttachmentReference depth_reference;
|
||||
static VkAttachmentReference resolve_reference;
|
||||
static VkAttachmentDescription attachments[3] = {{0}};
|
||||
static VkSubpassDescription subpass = {0};
|
||||
static VkRenderPassCreateInfo rp_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO};
|
||||
|
||||
//two render passes are compatible for piplines when they match exactly except for:
|
||||
//initial and final layouts in attachment descriptions.
|
||||
//load and store operations in attachment descriptions.
|
||||
//image layouts in attachment references.
|
||||
|
||||
if (vk.multisamplebits == VK_SAMPLE_COUNT_1_BIT)
|
||||
pass &= ~RP_MULTISAMPLE; //no difference
|
||||
|
||||
for (pass = 0; pass < 3; pass++)
|
||||
if (vk.renderpass[pass] != VK_NULL_HANDLE)
|
||||
return vk.renderpass[pass]; //already built
|
||||
|
||||
numattachments = 0;
|
||||
if ((pass&3)==RP_DEPTHONLY)
|
||||
color_reference.attachment = ~(uint32_t)0; //no colour buffer...
|
||||
else
|
||||
color_reference.attachment = numattachments++;
|
||||
depth_reference.attachment = numattachments++;
|
||||
resolve_reference.attachment = ~(uint32_t)0;
|
||||
if ((pass & RP_MULTISAMPLE) && color_reference.attachment != ~(uint32_t)0)
|
||||
{ //if we're using multisample, then render to a third texture, with a resolve to the original colour texture.
|
||||
resolve_reference.attachment = color_reference.attachment;
|
||||
color_reference.attachment = numattachments++;
|
||||
}
|
||||
|
||||
color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
depth_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
resolve_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
if (color_reference.attachment != ~(uint32_t)0)
|
||||
{
|
||||
if (vk.renderpass[pass] != VK_NULL_HANDLE)
|
||||
continue;
|
||||
|
||||
numattachments = 0;
|
||||
if (vk.multisamplebits != VK_SAMPLE_COUNT_1_BIT)
|
||||
{
|
||||
resolve_reference.attachment = numattachments++;
|
||||
depth_reference.attachment = numattachments++;
|
||||
color_reference.attachment = numattachments++;
|
||||
}
|
||||
else
|
||||
{
|
||||
color_reference.attachment = numattachments++;
|
||||
depth_reference.attachment = numattachments++;
|
||||
resolve_reference.attachment = ~(uint32_t)0;
|
||||
}
|
||||
|
||||
color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
depth_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
resolve_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
attachments[color_reference.attachment].format = vk.backbufformat;
|
||||
attachments[color_reference.attachment].samples = vk.multisamplebits;
|
||||
attachments[color_reference.attachment].format = (pass&RP_FP16)?VK_FORMAT_R16G16B16A16_SFLOAT:vk.backbufformat;
|
||||
attachments[color_reference.attachment].samples = (pass & RP_MULTISAMPLE)?vk.multisamplebits:VK_SAMPLE_COUNT_1_BIT;
|
||||
// attachments[color_reference.attachment].loadOp = pass?VK_ATTACHMENT_LOAD_OP_LOAD:VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachments[color_reference.attachment].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachments[color_reference.attachment].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachments[color_reference.attachment].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachments[color_reference.attachment].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
attachments[color_reference.attachment].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
}
|
||||
|
||||
if (depth_reference.attachment != ~(uint32_t)0)
|
||||
{
|
||||
attachments[depth_reference.attachment].format = vk.depthformat;
|
||||
attachments[depth_reference.attachment].samples = vk.multisamplebits;
|
||||
attachments[depth_reference.attachment].samples = (pass & RP_MULTISAMPLE)?vk.multisamplebits:VK_SAMPLE_COUNT_1_BIT;
|
||||
// attachments[depth_reference.attachment].loadOp = pass?VK_ATTACHMENT_LOAD_OP_LOAD:VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
attachments[depth_reference.attachment].storeOp = VK_ATTACHMENT_STORE_OP_STORE;//VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachments[depth_reference.attachment].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachments[depth_reference.attachment].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachments[depth_reference.attachment].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
attachments[depth_reference.attachment].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
|
||||
if (resolve_reference.attachment != ~(uint32_t)0)
|
||||
{
|
||||
attachments[resolve_reference.attachment].format = vk.backbufformat;
|
||||
attachments[resolve_reference.attachment].samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachments[resolve_reference.attachment].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachments[resolve_reference.attachment].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachments[resolve_reference.attachment].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachments[resolve_reference.attachment].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachments[resolve_reference.attachment].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
attachments[resolve_reference.attachment].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
}
|
||||
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpass.flags = 0;
|
||||
subpass.inputAttachmentCount = 0;
|
||||
subpass.pInputAttachments = NULL;
|
||||
subpass.colorAttachmentCount = 1;
|
||||
subpass.pColorAttachments = &color_reference;
|
||||
subpass.pResolveAttachments = (resolve_reference.attachment != ~(uint32_t)0)?&resolve_reference:NULL;
|
||||
subpass.pDepthStencilAttachment = &depth_reference;
|
||||
subpass.preserveAttachmentCount = 0;
|
||||
subpass.pPreserveAttachments = NULL;
|
||||
|
||||
rp_info.attachmentCount = numattachments;
|
||||
rp_info.pAttachments = attachments;
|
||||
rp_info.subpassCount = 1;
|
||||
rp_info.pSubpasses = &subpass;
|
||||
rp_info.dependencyCount = 0;
|
||||
rp_info.pDependencies = NULL;
|
||||
|
||||
if (pass == 0)
|
||||
{ //nothing cleared, both are just re-loaded.
|
||||
attachments[color_reference.attachment].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
attachments[depth_reference.attachment].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
}
|
||||
else if (pass == 1)
|
||||
{ //depth cleared, colour is whatever.
|
||||
attachments[color_reference.attachment].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachments[depth_reference.attachment].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
}
|
||||
else
|
||||
{ //both cleared
|
||||
attachments[color_reference.attachment].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
attachments[depth_reference.attachment].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
}
|
||||
|
||||
VkAssert(vkCreateRenderPass(vk.device, &rp_info, vkallocationcb, &vk.renderpass[pass]));
|
||||
}
|
||||
|
||||
if (resolve_reference.attachment != ~(uint32_t)0)
|
||||
{
|
||||
attachments[resolve_reference.attachment].format = vk.backbufformat;
|
||||
attachments[resolve_reference.attachment].samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachments[resolve_reference.attachment].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachments[resolve_reference.attachment].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachments[resolve_reference.attachment].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachments[resolve_reference.attachment].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachments[resolve_reference.attachment].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
attachments[resolve_reference.attachment].finalLayout = (pass&RP_PRESENTABLE)?VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
}
|
||||
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpass.flags = 0;
|
||||
subpass.inputAttachmentCount = 0;
|
||||
subpass.pInputAttachments = NULL;
|
||||
subpass.colorAttachmentCount = 1;
|
||||
subpass.pColorAttachments = &color_reference;
|
||||
subpass.pResolveAttachments = (resolve_reference.attachment != ~(uint32_t)0)?&resolve_reference:NULL;
|
||||
subpass.pDepthStencilAttachment = &depth_reference;
|
||||
subpass.preserveAttachmentCount = 0;
|
||||
subpass.pPreserveAttachments = NULL;
|
||||
|
||||
rp_info.attachmentCount = numattachments;
|
||||
rp_info.pAttachments = attachments;
|
||||
rp_info.subpassCount = 1;
|
||||
rp_info.pSubpasses = &subpass;
|
||||
rp_info.dependencyCount = 0;
|
||||
rp_info.pDependencies = NULL;
|
||||
|
||||
switch(pass&3)
|
||||
{
|
||||
case RP_RESUME:
|
||||
//nothing cleared, both are just re-loaded.
|
||||
attachments[color_reference.attachment].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
attachments[depth_reference.attachment].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
break;
|
||||
case RP_DEPTHCLEAR:
|
||||
//depth cleared, colour is whatever.
|
||||
attachments[depth_reference.attachment].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
attachments[color_reference.attachment].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachments[depth_reference.attachment].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
break;
|
||||
case RP_FULLCLEAR:
|
||||
//both cleared
|
||||
attachments[color_reference.attachment].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
attachments[depth_reference.attachment].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
attachments[color_reference.attachment].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
attachments[depth_reference.attachment].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
break;
|
||||
case RP_DEPTHONLY:
|
||||
attachments[depth_reference.attachment].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
// attachments[color_reference.attachment].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachments[depth_reference.attachment].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
}
|
||||
|
||||
VkAssert(vkCreateRenderPass(vk.device, &rp_info, vkallocationcb, &vk.renderpass[pass]));
|
||||
DebugSetName(VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)vk.renderpass[pass], va("RP%i", pass));
|
||||
return vk.renderpass[pass];
|
||||
}
|
||||
|
||||
void VK_DoPresent(struct vkframe *theframe)
|
||||
|
@ -4031,7 +4126,6 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
|
|||
vk.triplebuffer = info->triplebuffer;
|
||||
vk.vsync = info->wait;
|
||||
vk.dopresent = dopresent?dopresent:VK_DoPresent;
|
||||
vk.max_anistophy_limit = 1.0;
|
||||
memset(&sh_config, 0, sizeof(sh_config));
|
||||
|
||||
|
||||
|
@ -4063,6 +4157,7 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
|
|||
vkEnumerateInstanceExtensionProperties(NULL, &count, ext);
|
||||
for (i = 0; i < count && extensions_count < countof(extensions); i++)
|
||||
{
|
||||
Con_DLPrintf(2, " vki: %s\n", ext[i].extensionName);
|
||||
#ifdef VK_EXT_debug_utils
|
||||
if (!strcmp(ext[i].extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME))
|
||||
havedebugutils = true;
|
||||
|
@ -4424,11 +4519,13 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
|
|||
}
|
||||
|
||||
{
|
||||
uint32_t extcount = 0;
|
||||
uint32_t extcount = 0, i;
|
||||
VkExtensionProperties *ext;
|
||||
vkEnumerateDeviceExtensionProperties(vk.gpu, NULL, &extcount, NULL);
|
||||
ext = malloc(sizeof(*ext)*extcount);
|
||||
vkEnumerateDeviceExtensionProperties(vk.gpu, NULL, &extcount, ext);
|
||||
for (i = 0; i < extcount; i++)
|
||||
Con_DLPrintf(2, " vkd: %s\n", ext[i].extensionName);
|
||||
while (extcount --> 0)
|
||||
{
|
||||
for (e = 0; e < countof(knowndevexts); e++)
|
||||
|
@ -4694,7 +4791,7 @@ void VK_Shutdown(void)
|
|||
|
||||
if (vk.cmdpool)
|
||||
vkDestroyCommandPool(vk.device, vk.cmdpool, vkallocationcb);
|
||||
VK_DestroyRenderPass();
|
||||
VK_DestroyRenderPasses();
|
||||
|
||||
if (vk.pipelinecache)
|
||||
{
|
||||
|
|
|
@ -246,7 +246,7 @@ struct vk_rendertarg
|
|||
uint32_t width;
|
||||
uint32_t height;
|
||||
|
||||
qboolean multisample;
|
||||
uint32_t rpassflags;
|
||||
qboolean depthcleared; //starting a new gameview needs cleared depth relative to other views, but the first probably won't.
|
||||
|
||||
VkRenderPassBeginInfo restartinfo;
|
||||
|
@ -315,8 +315,7 @@ extern struct vulkaninfo_s
|
|||
int filterpic[3];
|
||||
int mipcap[2];
|
||||
float lodbias;
|
||||
float max_anistophy;
|
||||
float max_anistophy_limit;
|
||||
float max_anistophy; //limits.maxSamplerAnistrophy
|
||||
|
||||
struct vk_mempool_s
|
||||
{
|
||||
|
@ -375,8 +374,14 @@ extern struct vulkaninfo_s
|
|||
struct vk_frameend *frameendjobs;
|
||||
uint32_t backbuf_count;
|
||||
|
||||
VkRenderPass shadow_renderpass; //clears depth etc.
|
||||
VkRenderPass renderpass[3]; //reload-both(resume prior renderpass), clear-depth-dontcare-colour(gl_clear==0), clear-both(cl_clear!=0)
|
||||
#define RP_RESUME 0
|
||||
#define RP_DEPTHCLEAR 1 //
|
||||
#define RP_FULLCLEAR 2
|
||||
#define RP_DEPTHONLY 3 //shadowmaps (clears depth)
|
||||
#define RP_MULTISAMPLE (1u<<2)
|
||||
#define RP_PRESENTABLE (1u<<3)
|
||||
#define RP_FP16 (1u<<4)
|
||||
VkRenderPass renderpass[1u<<5];
|
||||
VkSwapchainKHR swapchain;
|
||||
uint32_t bufferidx;
|
||||
|
||||
|
@ -525,6 +530,7 @@ char *VKVID_GetRGBInfo (int *bytestride, int *truevidwidth, int *truevidheight
|
|||
qboolean VK_SCR_UpdateScreen (void);
|
||||
|
||||
void VKBE_RenderToTextureUpdate2d(qboolean destchanged);
|
||||
VkRenderPass VK_GetRenderPass(int pass);
|
||||
|
||||
//improved rgb get that calls the callback when the data is actually available. used for video capture.
|
||||
void VKVID_QueueGetRGBData (void (*gotrgbdata) (void *rgbdata, qintptr_t bytestride, size_t width, size_t height, enum uploadfmt fmt));
|
||||
|
|
|
@ -682,6 +682,8 @@ qintptr_t Plug_Init(qintptr_t *args)
|
|||
Plug_Export("ConExecuteCommand", QI_ConExecuteCommand) &&
|
||||
Plug_Export("ConsoleLink", QI_ConsoleLink))
|
||||
{
|
||||
if (!BUILTINISVALID(MapLog_Query))
|
||||
Con_Printf("QI: Engine does not support map times\n");
|
||||
pCmd_AddCommand("qi");
|
||||
pCmd_AddCommand("quaddicted");
|
||||
return true;
|
||||
|
|
Loading…
Reference in a new issue