Implement preliminary openxr plugin. inputs are still useless (can HOPEFULLY result in some prints, but nothing else), and there's no considerations for 2d things.

Fix prediction issues with the ftenq protocol.
Fix some console image previews.
Added mod_precache cvar. set to 0 to significantly reduce memory usage in xonotic...
Prevent xonotic's random file writes from forcing full worker syncs, for faster loading.
QTV connections are now accepted only from localhost peers by default.



git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5694 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2020-05-14 15:50:26 +00:00
parent 402fd12785
commit c949500da8
57 changed files with 3441 additions and 875 deletions

View File

@ -1077,7 +1077,57 @@ ELSE()
MESSAGE(WARNING "ffmpeg library NOT available. Quake shouldn't be playing fmv anyway.")
ENDIF()
#TODO: cef plugin
#openxr plugin
FIND_PACKAGE(PkgConfig)
IF (PKGCONFIG_FOUND)
IF (NOT CMAKE_CROSSCOMPILING) #its picking up the linux headers then complaining that they're missing in mingw. also almost entirely untested so no great loss.
PKG_SEARCH_MODULE(OPENXR openxr)
ENDIF()
IF (OPENXR_FOUND)
ADD_LIBRARY(openxr MODULE
plugins/plugin.c
plugins/openxr.c
)
TARGET_INCLUDE_DIRECTORIES(openxr PRIVATE ${OPENXR_INCLUDE_DIRS} )
SET_TARGET_PROPERTIES(openxr PROPERTIES PREFIX "fteplug_")
SET_TARGET_PROPERTIES(openxr PROPERTIES LINK_FLAGS "-Wl,--no-undefined")
IF (1) #dynamically link
SET_TARGET_PROPERTIES(openxr PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES};${FTE_DEFINES};XR_NO_PROTOTYPES")
TARGET_LINK_LIBRARIES(openxr ${SYS_LIBS})
ELSE() #statically link
SET_TARGET_PROPERTIES(openxr PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES};${FTE_DEFINES}")
TARGET_LINK_LIBRARIES(openxr ${SYS_LIBS} ${OPENXR_LIBRARIES})
ENDIF()
SET(INSTALLTARGS ${INSTALLTARGS} openxr)
ELSE()
MESSAGE(WARNING "openxr library NOT available. Quake is already a reality anyway.")
ENDIF()
ENDIF()
#cef plugin
#libcef itself can be obtained from http://opensource.spotify.com/cefbuilds/index.html (minimal builds, which still ends up with a 940mb libcef.so - yes, actual size)
#(be sure to manually strip the binary of its debug info)
IF (0)
FIND_PATH (CEF_PATH include/cef_version.h /tmp/cef/cef_binary_81.3.1+gb2b49f1+chromium-81.0.4044.113_linux64_minimal)
#FIND_LIBRARY(CEF_LIBRARIES cef ${CEF_PATH}/Release)
IF (CEF_PATH)
ADD_LIBRARY(cef MODULE
plugins/plugin.c
plugins/cef/cef.c
)
TARGET_INCLUDE_DIRECTORIES(cef PRIVATE ${CEF_PATH}/..)
if (CEF_LIBRARIES)
SET_TARGET_PROPERTIES(cef PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES};${FTE_DEFINES};LIBCEF_STATIC")
TARGET_LINK_LIBRARIES(cef ${SYS_LIBS} ${CEF_LIBRARIES} ${CMAKE_DL_LIBS})
ELSE()
SET_TARGET_PROPERTIES(cef PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES};${FTE_DEFINES};LIBCEF_DYNAMIC")
TARGET_LINK_LIBRARIES(cef ${SYS_LIBS} ${CMAKE_DL_LIBS})
ENDIF()
SET_TARGET_PROPERTIES(cef PROPERTIES PREFIX "fteplug_")
SET_TARGET_PROPERTIES(cef PROPERTIES LINK_FLAGS "-Wl,--no-undefined")
ENDIF()
ENDIF()
IF(NOT ANDROID)
#XMPP/jabber client plugin
@ -1115,6 +1165,7 @@ ADD_CUSTOM_TARGET(menusys ALL
quakec/menusys/menu.src
quakec/menusys/menusys/mitems.qc
quakec/menusys/menusys/mitems_common.qc
quakec/menusys/menusys/mitem_frame.qc
quakec/menusys/menusys/mitem_desktop.qc
quakec/menusys/menusys/mitem_exmenu.qc
quakec/menusys/menusys/mitem_edittext.qc

View File

@ -1718,9 +1718,9 @@ DEPCXX?=$(CXX)
ARCH:=$(ARCH)
BASELDFLAGS:=-L$(ARCHLIBS) $(BASELDFLAGS)
default: help
-include Makefile_private
.default: help
all: rel
rel: sv-rel m-rel qcc-rel
dbg: sv-dbg m-dbg qcc-dbg

View File

@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "cl_master.h"
#include "cl_ignore.h"
#include "shader.h"
#include "vr.h"
#include <ctype.h>
// callbacks
void QDECL CL_Sbar_Callback(struct cvar_s *var, char *oldvalue);
@ -184,6 +185,7 @@ cvar_t cl_download_redirection = CVARFD("cl_download_redirection", "2", CVAR_NOT
cvar_t cl_download_mapsrc = CVARFD("cl_download_mapsrc", "", CVAR_ARCHIVE, "Specifies an http location prefix for map downloads. EG: \"http://example.com/path/quakemaps/\"");
cvar_t cl_download_packages = CVARFD("cl_download_packages", "1", CVAR_NOTFROMSERVER, "0=Do not download packages simply because the server is using them. 1=Download and load packages as needed (does not affect games which do not use this package). 2=Do download and install permanently (use with caution!)");
cvar_t requiredownloads = CVARFD("requiredownloads","1", CVAR_ARCHIVE, "0=join the game before downloads have even finished (might be laggy). 1=wait for all downloads to complete before joining.");
cvar_t mod_precache = CVARD("mod_precache","1", "Controls when models are loaded.\n0: Load them only when they're visible.\n1: Load them upfront.\n2: Lazily load them to shorten load times at the risk of brief stuttering during only the start of the map.");
cvar_t cl_muzzleflash = CVAR("cl_muzzleflash", "1");
@ -2695,8 +2697,8 @@ void CL_Packet_f (void)
if (Cmd_FromGamecode()) //some mvdsv servers stuffcmd a packet command which lets them know which ip the client is from.
{ //unfortunatly, 50% of servers are badly configured resulting in them poking local services that THEY MUST NOT HAVE ACCESS TO.
char *addrdesc;
char *realdesc;
const char *addrdesc;
const char *realdesc;
if (cls.demoplayback)
{
Con_DPrintf ("Not sending realip packet from demo\n");
@ -4091,13 +4093,13 @@ static void CL_Curl_f(void)
usage |= 4;
else if (!strcmp(arg, "--for"))
{
alreadyhave = true; //assume we have it.
for (i++; i < argc-1; i++)
alreadyhave = true; //assume we have a package that satisfies the file name.
for (i++; i < argc-1; i++) //all but the last...
{
arg = Cmd_Argv(i);
if (!CL_CheckDLFile(arg))
{
alreadyhave = false;
alreadyhave = false; //I guess we didn't after all.
break;
}
}
@ -4477,10 +4479,43 @@ void CL_CrashMeError_f(void)
Sys_Error("crashme! %s", Cmd_Args());
}
static char *ShowTime(unsigned int seconds)
{
char buf[1024];
char *b = buf;
*b = 0;
if (seconds > 60)
{
if (seconds > 60*60)
{
if (seconds > 24*60*60)
{
strcpy(b, va("%id ", seconds/(24*60*60)));
b += strlen(b);
seconds %= 24*60*60;
}
strcpy(b, va("%ih ", seconds/(60*60)));
b += strlen(b);
seconds %= 60*60;
}
strcpy(b, va("%im ", seconds/60));
b += strlen(b);
seconds %= 60;
}
strcpy(b, va("%is", seconds));
b += strlen(b);
return va("%s", buf);
}
void CL_Status_f(void)
{
extern world_t csqc_world;
char adr[128];
float pi, po, bi, bo;
NET_PrintAddresses(cls.sockets);
NET_PrintConnectionsStatus(cls.sockets);
if (NET_GetRates(cls.sockets, &pi, &po, &bi, &bo))
@ -4578,6 +4613,42 @@ void CL_Status_f(void)
if (cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
Con_Printf("\treplacement deltas\n");
}
if (cl.worldmodel)
{
Con_Printf("map uptime : %s\n", ShowTime(cl.time));
COM_FileBase(cl.worldmodel->name, adr, sizeof(adr));
Con_Printf ("current map : %s (%s)\n", adr, cl.levelname);
}
if (csqc_world.progs)
{
extern int num_sfx;
int count = 0, i;
edict_t *e;
for (i = 0; i < csqc_world.num_edicts; i++)
{
e = EDICT_NUM_PB(csqc_world.progs, i);
if (e && e->ereftype == ER_FREE && sv.time - e->freetime > 0.5)
continue; //free, and older than the zombie time
count++;
}
Con_Printf("entities : %i/%i/%i (mem: %.1f%%)\n", count, csqc_world.num_edicts, csqc_world.max_edicts, 100*(float)(csqc_world.progs->stringtablesize/(double)csqc_world.progs->stringtablemaxsize));
for (count = 1; count < MAX_PRECACHE_MODELS; count++)
if (!*cl.model_csqcname[count])
break;
Con_Printf("models : %i/%i\n", count, MAX_PRECACHE_MODELS);
Con_Printf("sounds : %i/\n", num_sfx); //there is a limit, its just private. :(
for (count = 1; count < MAX_SSPARTICLESPRE; count++)
if (!cl.particle_csname[count])
break;
if (count!=1)
Con_Printf("particles : %i/%i\n", count, MAX_SSPARTICLESPRE);
if (cl.csqcdebug)
Con_Printf("csqc debug : true\n");
}
Con_Printf("gamedir : %s\n", FS_GetGamedir(true));
}
void CL_Demo_SetSpeed_f(void)
@ -4771,6 +4842,7 @@ void CL_Init (void)
Cvar_Register (&cl_teamchatsound, cl_controlgroup);
Cvar_Register (&requiredownloads, cl_controlgroup);
Cvar_Register (&mod_precache, cl_controlgroup);
Cvar_Register (&cl_standardchat, cl_controlgroup);
Cvar_Register (&msg_filter, cl_controlgroup);
Cvar_Register (&msg_filter_frags, cl_controlgroup);
@ -5894,6 +5966,7 @@ double Host_Frame (double time)
qboolean idle;
extern int r_blockvidrestart;
static qboolean hadwork;
qboolean vrsync;
RSpeedLocals();
@ -5902,7 +5975,8 @@ double Host_Frame (double time)
return 0; // something bad happened, or the server disconnected
}
newrealtime = Media_TweekCaptureFrameTime(realtime, time);
vrsync = vid.vr?vid.vr->SyncFrame(&time):false; //fiddle with frame timings
newrealtime = Media_TweekCaptureFrameTime(realtime, time); //fiddle with time some more
time = newrealtime - realtime;
realtime = newrealtime;
@ -5945,7 +6019,7 @@ double Host_Frame (double time)
if (!cls.timedemo)
CL_ReadPackets ();
if (idle && cl_idlefps.value > 0)
if (idle && cl_idlefps.value > 0 && !vrsync)
{
double idlesec = 1.0 / cl_idlefps.value;
if (idlesec > 0.1)
@ -6020,7 +6094,7 @@ double Host_Frame (double time)
#ifdef HAVE_MEDIA_ENCODER
&& Media_Capturing() != 2
#endif
)
&& !vrsync)
{
// realtime += spare/1000; //don't use it all!
double newspare = CL_FilterTime((spare/1000 + realtime - oldrealtime)*1000, maxfps, 1.5, maxfpsignoreserver);

View File

@ -276,14 +276,14 @@ static const char *svc_nqstrings[] =
"NEW PROTOCOL(75)", //75
"NEW PROTOCOL(76)", //76
"NEW PROTOCOL(77)", //77
"nqsvcfte_updatestatstring(78)", //78
"nqsvcfte_updatestatfloat(79)", //79
"nqsvcfte_updatestatstring", //78
"nqsvcfte_updatestatfloat", //79
"NEW PROTOCOL(80)", //80
"NEW PROTOCOL(81)", //81
"NEW PROTOCOL(82)", //82
"nqsvcfte_cgamepacket(83)", //83
"nqsvcfte_cgamepacket", //83
"nqsvcfte_voicechat", //84
"nqsvcfte_setangledelta(85)", //85
"nqsvcfte_setangledelta", //85
"nqsvcfte_updateentities", //86
"NEW PROTOCOL(87)", //87
"NEW PROTOCOL(88)", //88
@ -291,7 +291,7 @@ static const char *svc_nqstrings[] =
};
#endif
extern cvar_t requiredownloads, cl_standardchat, msg_filter, msg_filter_frags, msg_filter_pickups, cl_countpendingpl, cl_download_mapsrc;
extern cvar_t requiredownloads, mod_precache, cl_standardchat, msg_filter, msg_filter_frags, msg_filter_pickups, cl_countpendingpl, cl_download_mapsrc;
int oldparsecountmod;
int parsecountmod;
double parsecounttime;
@ -1354,6 +1354,9 @@ static int CL_LoadModels(int stage, qboolean dontactuallyload)
cl.model_precache[i] = NULL;
else
#endif
if (!cls.timedemo && i!=1 && mod_precache.ival != 1)
cl.model_precache[i] = Mod_FindName (Mod_FixName(cl.model_name[i], cl.model_name[1]));
else
cl.model_precache[i] = Mod_ForName (Mod_FixName(cl.model_name[i], cl.model_name[1]), MLV_WARN);
S_ExtraUpdate();
@ -1839,6 +1842,16 @@ void CL_RequestNextDownload (void)
}
}
if (mod_precache.ival >= 2)
{
int i;
for (i=1 ; i<MAX_PRECACHE_MODELS ; i++)
{
if (cl.model_precache[i] && cl.model_precache[i]->loadstate == MLS_NOTLOADED)
Mod_LoadModel(cl.model_precache[i], MLV_WARN);
}
}
}
}

View File

@ -1130,7 +1130,7 @@ void CL_PredictMovePNum (int seat)
from.frame = i;
from.time = backdate->senttime;
from.cmd = &backdate->cmd[seat];
if (to.frame > pv->prop.sequence)
if (cl.inframes[to.frame&UPDATE_MASK].ackframe > pv->prop.sequence)
continue; //if we didn't predict to this frame yet, then the waterjump etc state will be invalid, so try to go for an older frame so that it actually propagates properly.
if (from.time < simtime && from.frame != to.frame)
break; //okay, we found the first frame that is older, no need to continue looking
@ -1184,7 +1184,8 @@ void CL_PredictMovePNum (int seat)
}
if (i == pe->num_entities && pv->nolocalplayer)
{
//return; //no player, nothing makes sense any more.
if (cls.state >= ca_active)
return; //no player, nothing makes sense any more.
from.state = &nullstate;
nopred = true;
}
@ -1243,6 +1244,11 @@ void CL_PredictMovePNum (int seat)
{
int stopframe;
//Con_Printf("Pred %i to %i\n", to.frame+1, min(from.frame+UPDATE_BACKUP, cl.movesequence));
//fix up sequence numbers for nq
int validsequence = cl.inframes[cl.validsequence&UPDATE_MASK].ackframe;
from.frame = cl.inframes[from.frame&UPDATE_MASK].ackframe;
to.frame = cl.inframes[to.frame&UPDATE_MASK].ackframe;
for (i=to.frame+1, stopframe=min(from.frame+UPDATE_BACKUP, cl.movesequence) ; i < stopframe; i++)
{
outframe_t *of = &cl.outframes[i & UPDATE_MASK];
@ -1273,7 +1279,7 @@ void CL_PredictMovePNum (int seat)
VectorCopy(pv->prop.gravitydir, from.state->gravitydir);
}
CL_PredictUsercmd (seat, trackent, from.state, to.state, to.cmd);
if (i <= cl.validsequence && simtime >= to.time)
if (i <= validsequence && simtime >= to.time)
{ //this frame is final keep track of our propagated values.
pv->prop.onground = pmove.onground;
pv->prop.jump_held = pmove.jump_held;

View File

@ -7484,8 +7484,8 @@ void Image_GenerateMips(struct pendingtextureinfo *mips, unsigned int flags)
{
int mip;
if (mips->type != PTI_2D)
return; //blurgh
if (mips->type == PTI_3D)
return; //3d mipmaps are more complicated to compute.
if (flags & IF_NOMIPMAP)
return;
@ -7493,6 +7493,9 @@ void Image_GenerateMips(struct pendingtextureinfo *mips, unsigned int flags)
if (sh_config.can_genmips && mips->encoding != PTI_P8)
return;
if (mips->mip[0].depth != 1)
return; //blurgh. we can't deal with layers.
switch(mips->encoding)
{
case TF_TRANS8:
@ -12745,6 +12748,8 @@ struct pendingtextureinfo *Image_LoadMipsFromMemory(int flags, const char *iname
mips = Z_Malloc(sizeof(*mips));
mips->type = (flags & IF_TEXTYPEMASK)>>IF_TEXTYPESHIFT;
if (mips->type == PTI_ANY)
mips->type = PTI_2D; //d
if (Image_GenMip0(mips, flags, rgbadata, NULL, imgwidth, imgheight, format, true))
{
Image_GenerateMips(mips, flags);

View File

@ -1694,7 +1694,7 @@ changed:
}
static qboolean menu_mousedown;
extern menu_t *menu_script;
extern emenu_t *menu_script;
static void M_Draw (menu_t *menu)
{
emenu_t *m = (emenu_t*)menu;

View File

@ -1,3 +1,6 @@
#ifndef MERGED_H
#define MERGED_H
#ifdef VKQUAKE
//we need some types available elsewhere, but don't really want to have to include the entire vulkan api everywhere.
//unfortunately, vulkan's handle types are not well defined.
@ -515,4 +518,4 @@ typedef struct rendererinfo_s {
texid_t R2D_RT_Configure(const char *id, int width, int height, uploadfmt_t rtfmt, unsigned int imageflags);
texid_t R2D_RT_GetTexture(const char *id, unsigned int *width, unsigned int *height);
#endif //MERGED_H

View File

@ -815,34 +815,45 @@ void QCBUILTIN PF_CL_is_cached_pic (pubprogfuncs_t *prinst, struct globalvars_s
void QCBUILTIN PF_CL_precache_pic (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
extern cvar_t pr_precachepic_slow;
const char *str;
mpic_t *pic;
float fromwad;
unsigned int flags;
#define PIC_FROMWAD 1 /*obsolete, probably better to just use gfx/foo.lmp instead*/
//#define PIC_TEMPORARY 2 /*DP, not meaningful here*/
//#define PIC_NOCLAMP 4 /*DP, not useful here - use a shader instead*/
//#define PIC_MIPMAP 8 /*DP, not useful here - use a shader instead*/
#define PRECACHE_PIC_DOWNLOAD 256 /*block until loaded, downloading if missing*/
#define PRECACHE_PIC_TEST 512 /*block until loaded*/
G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
str = PR_GetStringOfs(prinst, OFS_PARM0);
if (prinst->callargc > 1)
fromwad = G_FLOAT(OFS_PARM1);
flags = G_FLOAT(OFS_PARM1);
else
fromwad = false;
flags = 0;
if (fromwad)
if (pr_precachepic_slow.ival)
flags |= PRECACHE_PIC_DOWNLOAD|PRECACHE_PIC_TEST;
if (flags & PIC_FROMWAD)
pic = R2D_SafePicFromWad(str);
else
{
pic = R2D_SafeCachePic(str);
if ((!pic || !R_GetShaderSizes(pic, NULL, NULL, true)) && cls.state
if ((flags & PRECACHE_PIC_DOWNLOAD) && cls.state //if we're allowed to download it...
&& strchr(str, '.') //only try to download it if it looks as though it contains a path.
#ifndef CLIENTONLY
&& !sv.active
&& !sv.active //not if we're already the server...
#endif
&& strchr(str, '.')) //only try to download it if it looks as though it contains a path.
&& (!pic || !R_GetShaderSizes(pic, NULL, NULL, true))) //and it wasn't loaded...
CL_CheckOrEnqueDownloadFile(str, str, 0);
}
if (pic && R_GetShaderSizes(pic, NULL, NULL, true))
G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
else
G_INT(OFS_RETURN) = 0;
if (flags & PRECACHE_PIC_TEST)
if (!pic || !R_GetShaderSizes(pic, NULL, NULL, true))
G_INT(OFS_RETURN) = 0;
}
#ifdef CSQC_DAT

View File

@ -369,6 +369,8 @@ void COM_AddWork(wgroup_t thread, void(*func)(void *ctx, void *data, size_t a, s
void COM_InsertWork(wgroup_t tg, void(*func)(void *ctx, void *data, size_t a, size_t b), void *ctx, void *data, size_t a, size_t b); //high priority
qboolean COM_HasWork(void);
void COM_WorkerFullSync(void);
void COM_WorkerLock(void); //callable on main thread to temporarily suspend workers (in a safe location)
void COM_WorkerUnlock(void);
void COM_DestroyWorkerThread(void);
void COM_WorkerPartialSync(void *priorityctx, int *address, int value); //aka: while(*address==value)wait();
extern void *com_resourcemutex; //random mutex to simplify resource creation type stuff.
@ -384,6 +386,8 @@ void COM_AssertMainThread(const char *msg);
#define COM_InsertWork(t,f,a,b,c,d) (f)((a),(b),(c),(d))
#define COM_WorkerPartialSync(c,a,v)
#define COM_WorkerFullSync()
#define COM_WorkerLock()
#define COM_WorkerUnlock()
#define COM_HasWork() false
#define COM_DoWork(t,l) false
#define COM_AssertMainThread(msg)

View File

@ -598,7 +598,10 @@ qbyte *R_MarkLeaves_Q2 (void);
qbyte *R_MarkLeaves_Q3 (void);
void R_SetFrustum (float projmat[16], float viewmat[16]);
void R_SetRenderer(rendererinfo_t *ri);
void R_RegisterRenderer(rendererinfo_t *ri);
qboolean R_RegisterRenderer(void *module, rendererinfo_t *ri);
struct plugvrfuncs_s;
qboolean R_RegisterVRDriver(void *module, struct plugvrfuncs_s *vrfuncs);
qboolean R_UnRegisterModule(void *module);
void R_AnimateLight (void);
void R_UpdateHDR(vec3_t org);
void R_UpdateLightStyle(unsigned int style, const char *stylestring, float r, float g, float b);
@ -645,7 +648,7 @@ extern cvar_t r_shadow_realtime_dlight, r_shadow_realtime_dlight_shadows;
extern cvar_t r_shadow_realtime_dlight_ambient;
extern cvar_t r_shadow_realtime_dlight_diffuse;
extern cvar_t r_shadow_realtime_dlight_specular;
extern cvar_t r_shadow_realtime_world, r_shadow_realtime_world_shadows, r_shadow_realtime_world_lightmaps;
extern cvar_t r_shadow_realtime_world, r_shadow_realtime_world_shadows, r_shadow_realtime_world_lightmaps, r_shadow_realtime_world_importlightentitiesfrommap;
extern cvar_t r_shadow_shadowmapping;
extern cvar_t r_mirroralpha;
extern cvar_t r_wateralpha;

View File

@ -4,8 +4,13 @@
#include "gl_draw.h"
#include "shader.h"
#include "glquake.h"
#include "vr.h"
#include <string.h>
#ifdef __GLIBC__
#include <malloc.h> //for malloc_trim
#endif
#define DEFAULT_WIDTH 640
#define DEFAULT_HEIGHT 480
@ -1213,74 +1218,93 @@ rendererinfo_t dedicatedrendererinfo = {
extern rendererinfo_t headlessrenderer;
#endif
rendererinfo_t *rendererinfo[16] =
static struct
{
void *module;
rendererinfo_t *ri;
} rendererinfo[16] =
{
#ifdef GLQUAKE
#ifdef FTE_RPI
&rpirendererinfo,
{NULL, &rpirendererinfo},
#endif
&openglrendererinfo,
{NULL, &openglrendererinfo},
#ifdef USE_EGL
&eglrendererinfo,
{NULL, &eglrendererinfo},
#endif
#endif
#ifdef D3D9QUAKE
&d3d9rendererinfo,
{NULL, &d3d9rendererinfo},
#endif
#ifdef VKQUAKE
&vkrendererinfo,
{NULL, &vkrendererinfo},
#if defined(_WIN32) && defined(GLQUAKE) && !defined(FTE_SDL)
&nvvkrendererinfo,
{NULL, &nvvkrendererinfo},
#endif
#endif
#ifdef D3D11QUAKE
&d3d11rendererinfo,
{NULL, &d3d11rendererinfo},
#endif
#ifdef SWQUAKE
&swrendererinfo,
{NULL, &swrendererinfo},
#endif
#ifdef D3D8QUAKE
&d3d8rendererinfo,
{NULL, &d3d8rendererinfo},
#endif
#ifdef WAYLANDQUAKE
#ifdef GLQUAKE
&rendererinfo_wayland_gl,
{NULL, &rendererinfo_wayland_gl},
#endif
#ifdef VKQUAKE
&rendererinfo_wayland_vk,
{NULL, &rendererinfo_wayland_vk},
#endif
#endif
#ifdef GLQUAKE
&fbdevrendererinfo, //direct stuff that doesn't interact well with the system should always be low priority
{NULL, &fbdevrendererinfo}, //direct stuff that doesn't interact well with the system should always be low priority
#endif
#ifndef NPQTV
&dedicatedrendererinfo,
{NULL, &dedicatedrendererinfo},
#endif
#ifdef HEADLESSQUAKE
&headlessrenderer,
{NULL, &headlessrenderer},
#ifdef VKQUAKE
//&headlessvkrendererinfo,
//{NULL, &headlessvkrendererinfo},
#endif
#endif
};
void R_RegisterRenderer(rendererinfo_t *ri)
qboolean R_RegisterRenderer(void *module, rendererinfo_t *ri)
{
size_t i;
for (i = 0; i < countof(rendererinfo); i++)
{ //already registered
if (rendererinfo[i] == ri)
return;
if (rendererinfo[i].ri == ri)
return true;
}
for (i = 0; i < countof(rendererinfo); i++)
{ //register it in the first empty slot
if (!rendererinfo[i])
if (!rendererinfo[i].ri)
{
rendererinfo[i] = ri;
return;
rendererinfo[i].module = module;
rendererinfo[i].ri = ri;
return true;
}
}
Sys_Printf("unable to register renderer %s\n", ri->description);
return false;
}
static plugvrfuncs_t *vrfuncs;
qboolean R_RegisterVRDriver(void *module, plugvrfuncs_t *vr)
{
if (!vrfuncs)
{
vrfuncs = vr;
return true;
}
Sys_Printf("unable to register renderer %s\n", vr->description);
return false;
}
void R_SetRenderer(rendererinfo_t *ri)
@ -1365,6 +1389,10 @@ void R_ShutdownRenderer(qboolean devicetoo)
if (VID_DeInit && devicetoo)
{
if (vid.vr)
vid.vr->Shutdown();
vid.vr = NULL;
TRACE(("dbg: R_ApplyRenderer: VID_DeInit\n"));
VID_DeInit();
}
@ -1430,6 +1458,10 @@ qboolean R_ApplyRenderer (rendererstate_t *newr)
R_ShutdownRenderer(true);
Con_DPrintf("video shutdown took %f seconds\n", Sys_DoubleTime() - time);
#ifdef __GLIBC__
malloc_trim(0);
#endif
if (qrenderer == QR_NONE)
{
if (newr->renderer->rtype == qrenderer && currentrendererstate.renderer)
@ -1951,6 +1983,7 @@ qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
newr->rate = vid_refreshrate.value;
newr->stereo = (r_stereo_method.ival == 1);
newr->srgb = vid_srgb.ival;
newr->vr = vrfuncs;
#if defined(_WIN32) && !defined(FTE_SDL)
if (newr->bpp && newr->bpp < 24)
@ -1990,9 +2023,9 @@ qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
{ //special hack so that android doesn't weird out when not focused.
for (i = 0; i < countof(rendererinfo); i++)
{
if (rendererinfo[i] && rendererinfo[i]->name[0] && rendererinfo[i]->rtype == QR_HEADLESS)
if (rendererinfo[i].ri && rendererinfo[i].ri->name[0] && rendererinfo[i].ri->rtype == QR_HEADLESS)
{
newr->renderer = rendererinfo[i];
newr->renderer = rendererinfo[i].ri;
break;
}
}
@ -2005,11 +2038,11 @@ qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
//I'd like to just qsort the renderers, but that isn't stable and might reorder gl+d3d etc.
for (i = 0; i < countof(rendererinfo); i++)
{
pri = R_PriorityForRenderer(rendererinfo[i]);
pri = R_PriorityForRenderer(rendererinfo[i].ri);
if (pri > bestpri)
{
bestpri = pri;
newr->renderer = rendererinfo[i];
newr->renderer = rendererinfo[i].ri;
}
}
}
@ -2018,27 +2051,27 @@ qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
int count;
for (i = 0, count = 0; i < countof(rendererinfo); i++)
{
if (!rendererinfo[i] || !rendererinfo[i]->description)
if (!rendererinfo[i].ri || !rendererinfo[i].ri->description)
continue; //not valid in this build. :(
if (rendererinfo[i]->rtype == QR_NONE || //dedicated servers are not useful
rendererinfo[i]->rtype == QR_HEADLESS || //headless appears buggy
rendererinfo[i]->rtype == QR_SOFTWARE ) //software is just TOO buggy/limited for us to care.
if (rendererinfo[i].ri->rtype == QR_NONE || //dedicated servers are not useful
rendererinfo[i].ri->rtype == QR_HEADLESS || //headless appears buggy
rendererinfo[i].ri->rtype == QR_SOFTWARE ) //software is just TOO buggy/limited for us to care.
continue;
count++;
}
count = rand()%count;
for (i = 0; i < countof(rendererinfo); i++)
{
if (!rendererinfo[i] || !rendererinfo[i]->description)
if (!rendererinfo[i].ri || !rendererinfo[i].ri->description)
continue; //not valid in this build. :(
if (rendererinfo[i]->rtype == QR_NONE ||
rendererinfo[i]->rtype == QR_HEADLESS ||
rendererinfo[i]->rtype == QR_SOFTWARE )
if (rendererinfo[i].ri->rtype == QR_NONE ||
rendererinfo[i].ri->rtype == QR_HEADLESS ||
rendererinfo[i].ri->rtype == QR_SOFTWARE )
continue;
if (!count--)
{
newr->renderer = rendererinfo[i];
Con_Printf("randomly selected renderer: %s\n", rendererinfo[i]->description);
newr->renderer = rendererinfo[i].ri;
Con_Printf("randomly selected renderer: %s\n", rendererinfo[i].ri->description);
break;
}
}
@ -2048,20 +2081,20 @@ qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
int bestpri = -2, pri;
for (i = 0; i < countof(rendererinfo); i++)
{
if (!rendererinfo[i] || !rendererinfo[i]->description)
if (!rendererinfo[i].ri || !rendererinfo[i].ri->description)
continue; //not valid in this build. :(
for (j = 4-1; j >= 0; j--)
{
if (!rendererinfo[i]->name[j])
if (!rendererinfo[i].ri->name[j])
continue;
if (!stricmp(rendererinfo[i]->name[j], com_token))
if (!stricmp(rendererinfo[i].ri->name[j], com_token))
{
pri = R_PriorityForRenderer(rendererinfo[i]);
pri = R_PriorityForRenderer(rendererinfo[i].ri);
if (pri > bestpri)
{
bestpri = pri;
newr->renderer = rendererinfo[i];
newr->renderer = rendererinfo[i].ri;
}
break; //try the next renderer now.
}
@ -2182,6 +2215,12 @@ void R_RestartRenderer (rendererstate_t *newr)
rendererinfo_t *skip = newr->renderer;
struct sortedrenderers_s sorted[countof(rendererinfo)];
if (failed && newr->vr)
{
Con_Printf(CON_NOTICE "Trying without vr\n");
newr->vr = NULL;
failed = !R_ApplyRenderer(newr);
}
if (failed && newr->fullscreen == 1)
{
Con_Printf(CON_NOTICE "Trying fullscreen windowed"CON_DEFAULT"\n");
@ -2213,7 +2252,7 @@ void R_RestartRenderer (rendererstate_t *newr)
for (i = 0; i < countof(sorted); i++)
{
sorted[i].index = i;
sorted[i].r = rendererinfo[i];
sorted[i].r = rendererinfo[i].ri;
sorted[i].pri = R_PriorityForRenderer(sorted[i].r);
}
qsort(sorted, countof(sorted), sizeof(sorted[0]), R_SortRenderers);
@ -2295,7 +2334,7 @@ void R_SetRenderer_f (void)
for (i = 0; i < countof(sorted); i++)
{
sorted[i].index = i;
sorted[i].r = rendererinfo[i];
sorted[i].r = rendererinfo[i].ri;
sorted[i].pri = R_PriorityForRenderer(sorted[i].r);
}
qsort(sorted, countof(sorted), sizeof(sorted[0]), R_SortRenderers);
@ -2337,7 +2376,7 @@ static void R_UpdateRendererOpts(void)
for (i = 0; i < countof(sorted); i++)
{
sorted[i].index = i;
sorted[i].r = rendererinfo[i];
sorted[i].r = rendererinfo[i].ri;
sorted[i].pri = R_PriorityForRenderer(sorted[i].r);
}
qsort(sorted, countof(sorted), sizeof(sorted[0]), R_SortRenderers);

View File

@ -54,6 +54,7 @@ typedef struct {
char subrenderer[MAX_QPATH]; //external driver
char devicename[MAX_QPATH]; //device name (usually monitor)
struct rendererinfo_s *renderer;
struct plugvrfuncs_s *vr; //the vr driver we're trying to use.
} rendererstate_t;
#ifndef SERVERONLY
extern rendererstate_t currentrendererstate;
@ -116,6 +117,8 @@ typedef struct
qboolean forcecursor;
float forcecursorpos[2]; //in physical pixels
struct plugvrfuncs_s *vr; //how do deal with VR contexts.
} viddef_t;
extern viddef_t vid; // global video state

89
engine/client/vr.h Normal file
View File

@ -0,0 +1,89 @@
#include "merged.h"
typedef struct vrsetup_s
{
//engine-set
size_t structsize;
enum
{
VR_HEADLESS, //not to be confused with decapitation
VR_EGL,
VR_X11_GLX,
// VR_ANDROID_EGL,
VR_WIN_WGL,
VR_VULKAN, //vulkan has no platform variation
VR_D3D11, //d3d11 only works on windows, so no platform variation
} vrplatform; //the type of renderer/args getting inited. abort if unknown.
void *userctx; //for use in callbacks.
qboolean (*createinstance)(struct vrsetup_s *, char *instanceextensions, void *result); //used by vulkan, can be null for other renderers
//vr-set (by preinit)
struct
{
int major, minor;
} minver, maxver;
unsigned int deviceid[2];
char *deviceextensions;
//engine-set (for full init)
//this stuff is intentionally at the end
union {
struct
{
void *display;
int visualid;
void *glxfbconfig;
unsigned long drawable; //really int32
void *glxcontext;
} x11_glx;
struct
{
void *(*getprocaddr)(const char *name);
void *egldisplay;
void *eglconfig;
void *eglcontext;
} egl;
struct
{
void *hdc;
void *hglrc;
} wgl;
struct
{
void *device;
} d3d;
struct
{ //sometimes pointers, sometimes ints. nasty datatypes that suck. this is hideous.
#ifndef VulkanAPIRandomness
#if defined(__LP64__) || defined(_WIN64)
#define VulkanAPIRandomness void*
#elif defined(_MSC_VER) && _MSC_VER < 1300
#define VulkanAPIRandomness __int64
#else
#define VulkanAPIRandomness long long
#endif
#endif
VulkanAPIRandomness instance;
VulkanAPIRandomness physicaldevice;
VulkanAPIRandomness device;
unsigned int queuefamily;
unsigned int queueindex;
} vk;
};
} vrsetup_t;
//interface registered by plugins for VR stuff.
typedef struct plugvrfuncs_s
{
const char *description;
qboolean (*Prepare) (vrsetup_t *setupinfo); //called before graphics context init
qboolean (*Init) (vrsetup_t *setupinfo, rendererstate_t *info); //called after graphics context init
qboolean (*SyncFrame)(double *frametime); //called in the client's main loop, to block/tweak frame times. True means the game should render as fast as possible.
qboolean (*Render) (void(*rendereye)(texid_t tex, vec4_t fovoverride, vec3_t axisorg[4]));
void (*Shutdown) (void);
#define plugvrfuncs_name "VR"
} plugvrfuncs_t;

View File

@ -853,9 +853,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef FTE_TARGET_WEB
#define MAX_EDICTS ((1<<15)-1)
#else
//#define MAX_EDICTS ((1<<22)-1) // expandable up to 22 bits
#define MAX_EDICTS ((1<<18)-1) // expandable up to 22 bits
#define MAX_EDICTS ((1<<22)-1) // expandable up to 22 bits
//#define MAX_EDICTS ((1<<18)-1) // expandable up to 22 bits
#endif
#define MAX_NET_LIGHTSTYLES (INVALID_LIGHTSTYLE+1) // 16bit. the last index MAY be used to signify an invalid lightmap in the bsp, but is still valid for rtlights.
#define MAX_STANDARDLIGHTSTYLES 64
#define MAX_PRECACHE_MODELS 4096 // 14bit.

View File

@ -739,7 +739,7 @@ static void Cmd_Exec_f (void)
Con_TPrintf ("couldn't exec %s. check permissions.\n", name);
return;
}
if (cl_warncmd.ival || developer.ival || cvar_watched)
if (cl_warncmd.ival || developer.ival || cvar_watched || dpcompat_console.ival)
{
if (loc.search)
Con_TPrintf ("execing ^[^7%s\\tip\\from %s/%s^]\n", name, loc.search->logicalpath, name);
@ -3964,7 +3964,7 @@ static void Cmd_WriteConfig_f(void)
MasterInfo_WriteServers();
#endif
f = FS_OpenWithFriends(fname, sysname, sizeof(sysname), 4, "quake.rc", "hexen.rc", "*.cfg", "configs/*.cfg");
f = FS_OpenWithFriends(fname, sysname, sizeof(sysname), 4, "quake.rc", "hexen.rc", "*.cfg", "configs/*.cfg", "dlcache/*.pk3*");
all = cfg_save_all.ival;
}

View File

@ -1978,6 +1978,7 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in
lerpcutoff = inf->lerpcutoff * r_lerpmuzzlehack.value;
if (Sh_StencilShadowsActive() || e->fatness || lerpcutoff)
{
memset(&meshcache.vbo.coord2, 0, sizeof(meshcache.vbo.coord2));
mesh->xyz2_array = NULL;
mesh->xyz_blendw[0] = 1;
mesh->xyz_blendw[1] = 0;

View File

@ -5410,6 +5410,8 @@ static int COM_WorkerThread(void *arg)
{
while(COM_DoWork(group, true))
{
if (thread->request == WR_DIE)
break;
if (worker_sleeptime.value)
{
Sys_UnlockConditional(com_workercondition[group]);
@ -5512,6 +5514,51 @@ void COM_DestroyWorkerThread(void)
com_resourcemutex = NULL;
}
//Dangerous: stops workers WITHOUT flushing their queue. Be SURE to 'unlock' to start them up again.
void COM_WorkerLock(void)
{
int i;
if (!com_liveworkers[WG_LOADER])
return; //nothing to do.
//add a fake worker and ask workers to die
Sys_LockConditional(com_workercondition[WG_LOADER]);
com_liveworkers[WG_LOADER] += 1;
for (i = 0; i < WORKERTHREADS; i++)
com_worker[i].request = WR_DIE; //flag them all to die
Sys_ConditionBroadcast(com_workercondition[WG_LOADER]); //and make sure they ALL wake up to check their new death values.
Sys_UnlockConditional(com_workercondition[WG_LOADER]);
//wait for the workers to stop (leaving their work, because of our fake worker)
while(com_liveworkers[WG_LOADER]>1)
{
if (!COM_DoWork(WG_MAIN, false)) //need to check this to know they're done.
COM_DoWork(WG_LOADER, false); //might as well, while we're waiting.
}
//remove our fake worker now...
Sys_LockConditional(com_workercondition[WG_LOADER]);
com_liveworkers[WG_LOADER] -= 1;
Sys_UnlockConditional(com_workercondition[WG_LOADER]);
}
//called after COM_WorkerLock
void COM_WorkerUnlock(void)
{
int i;
for (i = 0; i < WORKERTHREADS; i++)
{
if (i >= worker_count.ival)
continue; //worker stays dead
//lower thread indexes need to be (re)created
if (!com_worker[i].thread)
{
com_worker[i].request = WR_NONE;
com_worker[i].thread = Sys_CreateThread(va("loadworker_%i", i), COM_WorkerThread, &com_worker[i], 0, 256*1024);
}
}
}
//fully flushes ALL pending work.
void COM_WorkerFullSync(void)
{
@ -5690,7 +5737,7 @@ static void QDECL COM_WorkerCount_Change(cvar_t *var, char *oldvalue)
if (!*var->string)
{
count = 4;
count = var->ival = 4;
}
//try to respond to any kill requests now, so we don't get surprised by the cvar changing too often.

View File

@ -298,7 +298,7 @@ static ftemanifest_t *FS_Manifest_Clone(ftemanifest_t *oldm)
static void FS_Manifest_Print(ftemanifest_t *man)
{
char buffer[1024];
char buffer[65536];
int i, j;
if (man->updateurl)
Con_Printf("updateurl %s\n", COM_QuotedString(man->updateurl, buffer, sizeof(buffer), false));
@ -319,9 +319,45 @@ static void FS_Manifest_Print(ftemanifest_t *man)
if (man->protocolname)
Con_Printf("protocolname %s\n", COM_QuotedString(man->protocolname, buffer, sizeof(buffer), false));
if (man->defaultexec)
Con_Printf("defaultexec %s\n", COM_QuotedString(man->defaultexec, buffer, sizeof(buffer), false));
{
char *s = buffer, *e;
for (s = man->defaultexec; *s; s = e)
{
e = strchr(s, '\n');
if (e)
{
*e = 0;
Con_Printf("-%s\n", s);
*e++ = '\n';
}
else
{
Con_Printf("-%s\n", s);
e = s+strlen(s);
}
}
//Con_Printf("defaultexec %s\n", COM_QuotedString(man->defaultexec, buffer, sizeof(buffer), false));
}
if (man->defaultoverrides)
Con_Printf("%s", man->defaultoverrides);
{
char *s = buffer, *e;
for (s = man->defaultoverrides; *s; s = e)
{
e = strchr(s, '\n');
if (e)
{
*e = 0;
Con_Printf("+%s\n", s);
*e++ = '\n';
}
else
{
Con_Printf("+%s\n", s);
e = s+strlen(s);
}
}
//Con_Printf("%s", man->defaultoverrides);
}
if (man->rtcbroker)
Con_Printf("rtcbroker %s\n", COM_QuotedString(man->rtcbroker, buffer, sizeof(buffer), false));
if (man->iconname)
@ -1376,7 +1412,7 @@ static void FS_RebuildFSHash_Update(const char *fname)
}
COM_WorkerFullSync();
COM_WorkerLock();
if (!Sys_LockMutex(fs_thread_mutex))
return; //amg!
@ -1391,6 +1427,7 @@ static void FS_RebuildFSHash_Update(const char *fname)
FS_AddFileHash(depth, fname, NULL, filehandle);
Sys_UnlockMutex(fs_thread_mutex);
COM_WorkerUnlock();
}
void FS_FlushFSHashWritten(const char *fname)
@ -3490,8 +3527,8 @@ void COM_Gamedir (const char *dir, const struct gamepacks *packagespaths)
#define QCFG "set v_gammainverted 1\nset con_stayhidden 0\nset com_parseutf8 0\nset allow_download_pakcontents 1\nset allow_download_refpackages 0\nset sv_bigcoords \"\"\nmap_autoopenportals 1\n" "sv_port "STRINGIFY(PORT_QWSERVER)" "STRINGIFY(PORT_NQSERVER)"\n" ZFIXHACK EZQUAKECOMPETITIVE QRPCOMPAT QUAKESPASMSUCKS
/*NetQuake reconfiguration, to make certain people feel more at home...*/
#define NQCFG "//disablehomedir 1\n//mainconfig ftenq\ncfg_save_auto 1\n" QCFG "set sv_nqplayerphysics 1\nset cl_loopbackprotocol auto\ncl_sbar 1\nset plug_sbar 0\nset sv_port "STRINGIFY(PORT_NQSERVER)"\ncl_defaultport "STRINGIFY(PORT_NQSERVER)"\nset m_preset_chosen 1\nset vid_wait 1\nset cl_demoreel 1\n"
#define SPASMCFG NQCFG "fps_preset builtin_spasm\nset cl_demoreel 0\n"
#define FITZCFG NQCFG "fps_preset builtin_spasm\n"
#define SPASMCFG NQCFG "fps_preset builtin_spasm\nset cl_demoreel 0\ncl_sbar 2\nset gl_load24bit 1\n"
#define FITZCFG NQCFG "fps_preset builtin_spasm\ncl_sbar 2\nset gl_load24bit 1\n"
#define TENEBRAECFG NQCFG "fps_preset builtin_tenebrae\n"
//nehahra has to be weird with its extra cvars, and buggy fullbrights.
#define NEHCFG QCFG "set nospr32 0\nset cutscene 1\nalias startmap_sp \"map nehstart\"\nr_fb_bmodels 0\nr_fb_models 0\n"
@ -6197,7 +6234,7 @@ static int QDECL Mods_AddGamedir(const char *fname, qofs_t fsize, time_t mtime,
if (strchr(gamedir, ';') || !FS_GamedirIsOkay(gamedir))
{
Z_Free(gamedir);
Z_Free(desc);
return true; //don't list it if we can't use it anyway
}

View File

@ -1321,6 +1321,50 @@ void Matrix4x4_Identity(float *outm)
outm[15] = 1;
}
void Matrix4x4_CM_Projection_Offset(float *proj, float fovl, float fovr, float fovd, float fovu, float neard, float fard, qboolean d3d)
{
double xmin, xmax, ymin, ymax;
double dn = (d3d?0:-1), df = 1; //d3d outputs near as 0, opengl has near as -1. that's the only difference.
float fovy = fovu-fovd;
float fovx = fovr-fovl;
//proj
ymax = neard * tan( fovy * M_PI / 360.0 );
ymin = -ymax;
if (fovx == fovy)
{
xmax = ymax;
xmin = ymin;
}
else
{
xmax = neard * tan( fovx * M_PI / 360.0 );
xmin = -xmax;
}
proj[0] = (2*neard) / (xmax - xmin);
proj[4] = 0;
proj[8] = (xmax + xmin) / (xmax - xmin);
proj[12] = 0;
proj[1] = 0;
proj[5] = (2*neard) / (ymax - ymin);
proj[9] = (ymax + ymin) / (ymax - ymin);
proj[13] = 0;
proj[2] = 0;
proj[6] = 0;
proj[10] = (fard*df-neard*dn)/(neard-fard);
proj[14] = ((df-dn)*fard*neard)/(neard-fard);
proj[3] = 0;
proj[7] = 0;
proj[11] = -1;
proj[15] = 0;
}
void Matrix4x4_CM_Projection_Far(float *proj, float fovx, float fovy, float neard, float fard, qboolean d3d)
{
double xmin, xmax, ymin, ymax;

View File

@ -191,6 +191,7 @@ void QuaternionSlerp(const vec4_t p, vec4_t q, float t, vec4_t qt);
//projection matricies of different types... gesh
void Matrix4x4_CM_Orthographic (float *proj, float xmin, float xmax, float ymax, float ymin, float znear, float zfar);
void Matrix4x4_CM_OrthographicD3D(float *proj, float xmin, float xmax, float ymax, float ymin, float znear, float zfar);
void Matrix4x4_CM_Projection_Offset(float *proj, float fovl, float fovr, float fovu, float fovd, float neard, float fard, qboolean d3d);
void Matrix4x4_CM_Projection_Far(float *proj, float fovx, float fovy, float neard, float fard, qboolean d3d);
void Matrix4x4_CM_Projection2 (float *proj, float fovx, float fovy, float neard);
void Matrix4x4_CM_Projection_Inf(float *proj, float fovx, float fovy, float neard, qboolean d3d);

View File

@ -155,7 +155,7 @@ enum addressscope_e
ASCOPE_LAN=3,
ASCOPE_NET=4
};
enum addressscope_e NET_ClassifyAddress(netadr_t *adr, char **outdesc);
enum addressscope_e NET_ClassifyAddress(netadr_t *adr, const char **outdesc);
qboolean NET_AddrIsReliable(netadr_t *adr); //hints that the protocol is reliable. if so, we don't need to wait for acks
qboolean NET_CompareAdr (netadr_t *a, netadr_t *b);

View File

@ -128,8 +128,10 @@ cvar_t tls_ignorecertificateerrors = CVARFD("tls_ignorecertificateerrors", "0",
#endif
#if defined(TCPCONNECT) && (defined(HAVE_SERVER) || defined(HAVE_HTTPSV))
#ifdef HAVE_SERVER
cvar_t net_enable_qizmo = CVARD("net_enable_qizmo", "1", "Enables compatibility with qizmo's tcp connections serverside. Frankly, using sv_port_tcp without this is a bit pointless.");
cvar_t net_enable_qtv = CVARD("net_enable_qtv", "1", "Listens for qtv proxies, or clients using the qtvplay command.");
cvar_t net_enable_qizmo = CVARD("net_enable_qizmo", "1", "Enables serverside support for 'connect tcp://foo' or 'connect tls://foo' (with net_enable_tls), as well as qizmo's tcp connections and compatibles.");
#endif
#ifdef MVD_RECORDING
cvar_t net_enable_qtv = CVARD("net_enable_qtv", "2", "Controls whether inbound qtv requests will be honoured (both proxies and clients using qtvplay).\n0: Don't accept qtv connections.\n1: Accept connections.\n2: Accept qtv connections only from host-scopped addresses (read: 127.*.*.*, ::1, or unix sockets).");
#endif
#if defined(HAVE_SSL)
cvar_t net_enable_tls = CVARD("net_enable_tls", "0", "If enabled, binary data sent to a non-tls tcp port will be interpretted as a tls handshake (enabling https or wss over the same tcp port.");
@ -5304,12 +5306,20 @@ static enum{
//for QTV connections, we just need the method and a blank line. our qtv parser will parse the actual headers.
if (!Q_strncasecmp(st->inbuffer, "QTV", 3))
{ //FIXME: make sure its removed from epoll and not killed prematurely
int r = net_enable_qtv.ival?SV_MVD_GotQTVRequest(st->clientstream, st->inbuffer, st->inbuffer+st->inlen, &st->qtvstate):-1;
int r = -2;
const char *desc;
if (net_enable_qtv.ival == 2 && NET_ClassifyAddress(&st->remoteaddr, &desc) > ASCOPE_HOST)
;
else if (net_enable_qtv.ival)
r = SV_MVD_GotQTVRequest(st->clientstream, st->inbuffer, st->inbuffer+st->inlen, &st->qtvstate);
i = st->inlen;
memmove(st->inbuffer, st->inbuffer+i, st->inlen - (i));
st->inlen -= i;
switch(r)
{
case -2:
VFS_PUTS(st->clientstream, "QTVSV 1\n" "PERROR: net_enable_qtv is disabled on this server\n\n");
return FTETCP_KILL;
case -1: //error
return FTETCP_KILL;
case 0: //retry
@ -7720,7 +7730,7 @@ int NET_EnumerateAddresses(ftenet_connections_t *collection, struct ftenet_gener
return found;
}
static enum addressscope_e NET_ClassifyAddressipv4(int ip, char **outdesc)
static enum addressscope_e NET_ClassifyAddressipv4(int ip, const char **outdesc)
{
int scope = ASCOPE_NET;
char *desc = NULL;
@ -7742,10 +7752,10 @@ static enum addressscope_e NET_ClassifyAddressipv4(int ip, char **outdesc)
*outdesc = desc;
return scope;
}
enum addressscope_e NET_ClassifyAddress(netadr_t *adr, char **outdesc)
enum addressscope_e NET_ClassifyAddress(netadr_t *adr, const char **outdesc)
{
int scope = ASCOPE_NET;
char *desc = NULL;
const char *desc = NULL;
if (adr->type == NA_LOOPBACK)
{
@ -7773,6 +7783,12 @@ enum addressscope_e NET_ClassifyAddress(netadr_t *adr, char **outdesc)
desc = "vp-mapped";
}
}
#ifdef UNIXSOCKETS
else if (adr->type == NA_UNIX)
{
scope = ASCOPE_HOST, desc = "unix";
}
#endif
else if (adr->type == NA_IP)
scope = NET_ClassifyAddressipv4(*(int*)adr->address.ip, &desc);
if (outdesc)
@ -7792,7 +7808,7 @@ void NET_PrintAddresses(ftenet_connections_t *collection)
const char *params[sizeof(addr)/sizeof(addr[0])];
qboolean warn = true;
static const char *scopes[] = {"process", "local", "link", "lan", "net"};
char *desc;
const char *desc;
if (!collection)
return;
@ -8432,6 +8448,8 @@ void NET_Init (void)
#if defined(TCPCONNECT) && (defined(HAVE_SERVER) || defined(HAVE_HTTPSV))
#ifdef HAVE_SERVER
Cvar_Register(&net_enable_qizmo, "networking");
#endif
#ifdef MVD_RECORDING
Cvar_Register(&net_enable_qtv, "networking");
#endif
#if defined(HAVE_SSL)

View File

@ -4,6 +4,7 @@
#include "quakedef.h"
#include "fs.h"
#include "vr.h"
#define FTEENGINE
#include "../plugins/plugin.h"
@ -390,28 +391,21 @@ static qboolean QDECL PlugBI_GetPluginName(int plugnum, char *outname, size_t na
static qboolean QDECL PlugBI_ExportInterface(const char *name, void *interfaceptr, size_t structsize)
{
if (0)
;
/*
else if (!strncmp(name, "VID_DisplayDriver")) //a video driver, loaded by name as given by vid_renderer
{
FS_RegisterModuleDriver(, func);
currentplug->blockcloses++;
}
*/
#if defined(PLUGINS) && !defined(SERVERONLY)
#ifdef HAVE_MEDIA_DECODER
else if (!strcmp(name, "Media_VideoDecoder"))
Media_RegisterDecoder(currentplug, interfaceptr);
if (!strcmp(name, "Media_VideoDecoder"))
return Media_RegisterDecoder(currentplug, interfaceptr);
#endif
#ifdef HAVE_MEDIA_ENCODER
else if (!strcmp(name, "Media_VideoEncoder"))
Media_RegisterEncoder(currentplug, interfaceptr);
if (!strcmp(name, "Media_VideoEncoder"))
return Media_RegisterEncoder(currentplug, interfaceptr);
#endif
#endif
else
return 0;
return 1;
#ifdef HAVE_CLIENT
if (!strcmp(name, plugvrfuncs_name))
return R_RegisterVRDriver(currentplug, interfaceptr);
#endif
return false;
}
static cvar_t *QDECL Plug_Cvar_GetNVFDG(const char *name, const char *defaultvalue, unsigned int flags, const char *description, const char *groupname)
@ -475,6 +469,11 @@ static qboolean QDECL Plug_Cvar_Update(qhandle_t handle, int *modificationcount,
return false;
}
static void QDECL Plug_Cmd_TokenizeString(const char *text)
{
Cmd_TokenizeString(text, false, false);
}
//void Cmd_Args(char *buffer, int buffersize)
static void QDECL Plug_Cmd_Args(char *buffer, int maxsize)
{
@ -1778,6 +1777,9 @@ static void *QDECL PlugBI_GetEngineInterface(const char *interfacename, size_t s
Plug_Con_Print,
Plug_Sys_Error,
Plug_Sys_Milliseconds,
Sys_LoadLibrary,
Sys_GetAddressForName,
Sys_CloseLibrary,
};
if (structsize == sizeof(funcs))
return &funcs;
@ -1787,7 +1789,7 @@ static void *QDECL PlugBI_GetEngineInterface(const char *interfacename, size_t s
static plugcmdfuncs_t funcs =
{
Plug_Cmd_AddCommand,
NULL,//Plug_Cmd_TokenizeString,
Plug_Cmd_TokenizeString,
Plug_Cmd_Args,
Plug_Cmd_Argv,
Plug_Cmd_Argc,

View File

@ -36,6 +36,9 @@ cvar_t pr_gc_threaded = CVARD("pr_gc_threaded", "0", "Says whether to use a sepa
cvar_t pr_sourcedir = CVARD("pr_sourcedir", "src", "Subdirectory where your qc source is located. Used by the internal compiler and qc debugging functionality.");
cvar_t pr_enable_uriget = CVARD("pr_enable_uriget", "1", "Allows gamecode to make direct http requests");
cvar_t pr_enable_profiling = CVARD("pr_enable_profiling", "0", "Enables profiling support. Will run more slowly. Change the map and then use the profile_ssqc/profile_csqc commands to see the results.");
#ifdef HAVE_CLIENT
cvar_t pr_precachepic_slow = CVARD("pr_precachepic_slow", "0", "Legacy setting. Should be set to 0 where supported.");
#endif
int tokenizeqc(const char *str, qboolean dpfuckage);
void PF_buf_shutdown(pubprogfuncs_t *prinst);
@ -98,6 +101,9 @@ void PF_Common_RegisterCvars(void)
Cvar_Register (&pr_fixbrokenqccarrays, cvargroup_progs);
Cvar_Register (&utf8_enable, cvargroup_progs);
Cvar_Register (&pr_autocreatecvars, cvargroup_progs);
#ifdef HAVE_CLIENT
Cvar_Register (&pr_precachepic_slow, cvargroup_progs);
#endif
#ifdef RAGDOLL
Cmd_AddCommand("skel_info", skel_info_f);

View File

@ -83,7 +83,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PEXT2_NEWSIZEENCODING 0x00000040 //richer size encoding.
#define PEXT2_INFOBLOBS 0x00000080 //serverinfo+userinfo lengths can be MUCH higher (protocol is unbounded, but expect low sanity limits on userinfo), and contain nulls etc.
#define PEXT2_STUNAWARE 0x00000100 //changes the netchan to biased-bigendian (so lead two bits are 1 and not stun's 0, so we don't get confused)
//#define PEXT2_NEWINTENTS 0x00000200 //clc_move changes, more buttons etc
//#define PEXT2_NEWINTENTS 0x00000200 //clc_move changes, more buttons etc. vr stuff!
#define PEXT2_CLIENTSUPPORT (PEXT2_PRYDONCURSOR|PEXT2_VOICECHAT|PEXT2_SETANGLEDELTA|PEXT2_REPLACEMENTDELTAS|PEXT2_MAXPLAYERS|PEXT2_PREDINFO|PEXT2_NEWSIZEENCODING|PEXT2_INFOBLOBS|PEXT2_STUNAWARE)
//EzQuake/Mvdsv extensions. (use ezquake name, to avoid confusion about .mvd format and its protocol differences)

View File

@ -53,7 +53,7 @@ void Sys_Quit (void);
void Sys_RecentServer(char *command, char *target, char *title, char *desc);
qboolean Sys_RunInstaller(void);
typedef struct {
typedef struct dllfunction_s {
void **funcptr;
char *name;
} dllfunction_t;

View File

@ -6,6 +6,7 @@
#include "shader.h"
#include "renderque.h"
#include "resource.h"
#include "vr.h"
#define FUCKDXGI
@ -981,6 +982,7 @@ static void initD3D11(HWND hWnd, rendererstate_t *info)
static IID factiid = {0x770aae78, 0xf26f, 0x4dba, {0xa8, 0x29, 0x25, 0x3c, 0x83, 0xd1, 0xb3, 0x87}};
IDXGIFactory1 *fact = NULL;
IDXGIAdapter *adapt = NULL;
vrsetup_t vrsetup = {sizeof(vrsetup)};
dllfunction_t d3d11funcs[] =
{
{(void**)&fnc, "D3D11CreateDeviceAndSwapChain"},
@ -1000,6 +1002,7 @@ static void initD3D11(HWND hWnd, rendererstate_t *info)
if (!d3d11mod)
return;
vrsetup.vrplatform = VR_D3D11;
if (pCreateDXGIFactory1)
{
HRESULT hr;
@ -1008,9 +1011,34 @@ static void initD3D11(HWND hWnd, rendererstate_t *info)
Con_Printf("CreateDXGIFactory1 failed: %s\n", D3D_NameForResult(hr));
if (fact)
{
IDXGIFactory1_EnumAdapters(fact, 0, &adapt);
if (info->vr)
{
if (!info->vr->Prepare(&vrsetup))
{
info->vr->Shutdown();
info->vr = NULL;
}
else
{
int id = 0;
while (S_OK==IDXGIFactory1_EnumAdapters(fact, id++, &adapt))
{
DXGI_ADAPTER_DESC desc;
IDXGIAdapter_GetDesc(adapt, &desc);
if (desc.AdapterLuid.LowPart == vrsetup.deviceid[0] && desc.AdapterLuid.HighPart == vrsetup.deviceid[1])
break;
IDXGIAdapter_Release(adapt);
adapt = NULL;
}
}
}
if (!adapt)
IDXGIFactory1_EnumAdapters(fact, 0, &adapt);
}
}
else
info->vr = NULL; //o.O
initD3D11Device(hWnd, info, fnc, adapt);

View File

@ -5753,7 +5753,7 @@ int GLBE_BeginRenderBuffer_DepthOnly(texid_t depthtexture)
//state->colour is created if usedepth is set and it doesn't previously exist
int GLBE_FBO_Update(fbostate_t *state, unsigned int enables, texid_t *destcol, int mrt, texid_t destdepth, int width, int height, int layer)
{
GLenum allcolourattachments[] ={GL_COLOR_ATTACHMENT0_EXT,GL_COLOR_ATTACHMENT1_EXT,GL_COLOR_ATTACHMENT2_EXT,GL_COLOR_ATTACHMENT3_EXT,
static GLenum allcolourattachments[] ={GL_COLOR_ATTACHMENT0_EXT,GL_COLOR_ATTACHMENT1_EXT,GL_COLOR_ATTACHMENT2_EXT,GL_COLOR_ATTACHMENT3_EXT,
GL_COLOR_ATTACHMENT4_EXT,GL_COLOR_ATTACHMENT5_EXT,GL_COLOR_ATTACHMENT6_EXT,GL_COLOR_ATTACHMENT7_EXT};
int i;
int old;

View File

@ -220,7 +220,7 @@ void VK_R_BloomBlend (texid_t source, int x, int y, int w, int h)
R2D_Flush();
#if 1
/*filter the screen into a downscaled image*/
VKBE_RT_Gen(&vk_rt_filter, texwidth[0], texheight[0], false, RT_IMAGEFLAGS);
VKBE_RT_Gen(&vk_rt_filter, NULL, texwidth[0], texheight[0], false, RT_IMAGEFLAGS);
VKBE_RT_Begin(&vk_rt_filter);
vk.sourcecolour = source;
R2D_ScalePic(0, 0, vid.width, vid.height, bloomfilter);
@ -251,7 +251,7 @@ void VK_R_BloomBlend (texid_t source, int x, int y, int w, int h)
r_worldentity.glowmod[1] = 0;
VKBE_RT_Gen(&vk_rt_bloom[1][i], texwidth[i], texheight[i], false, RT_IMAGEFLAGS);
VKBE_RT_Gen(&vk_rt_bloom[1][i], NULL, texwidth[i], texheight[i], false, RT_IMAGEFLAGS);
VKBE_RT_Begin(&vk_rt_bloom[1][i]);
vk.sourcecolour = intex;
BE_SelectEntity(&r_worldentity);
@ -261,7 +261,7 @@ void VK_R_BloomBlend (texid_t source, int x, int y, int w, int h)
r_worldentity.glowmod[0] = 0;
r_worldentity.glowmod[1] = 1.0 / texheight[i];
VKBE_RT_Gen(&vk_rt_bloom[0][i], texwidth[i], texheight[i], false, RT_IMAGEFLAGS);
VKBE_RT_Gen(&vk_rt_bloom[0][i], NULL, texwidth[i], texheight[i], false, RT_IMAGEFLAGS);
VKBE_RT_Begin(&vk_rt_bloom[0][i]);
vk.sourcecolour = &vk_rt_bloom[1][i].q_colour;
BE_SelectEntity(&r_worldentity);
@ -286,10 +286,10 @@ void VK_R_BloomShutdown(void)
int i;
for (i = 0; i < MAXLEVELS; i++)
{
VKBE_RT_Gen(&vk_rt_bloom[0][i], 0, 0, false, RT_IMAGEFLAGS);
VKBE_RT_Gen(&vk_rt_bloom[1][i], 0, 0, false, RT_IMAGEFLAGS);
VKBE_RT_Gen(&vk_rt_bloom[0][i], NULL, 0, 0, false, RT_IMAGEFLAGS);
VKBE_RT_Gen(&vk_rt_bloom[1][i], NULL, 0, 0, false, RT_IMAGEFLAGS);
}
VKBE_RT_Gen(&vk_rt_filter, 0, 0, false, RT_IMAGEFLAGS);
VKBE_RT_Gen(&vk_rt_filter, NULL, 0, 0, false, RT_IMAGEFLAGS);
R_InitBloomTextures();
}

View File

@ -4323,7 +4323,7 @@ qboolean Heightmap_EdictInFatPVS (model_t *mod, const struct pvscache_s *edict,
const hmpvs_t *hmpvs = (const hmpvs_t*)pvsdata;
const hmpvsent_t *hmed = (const hmpvsent_t*)edict;
if (!hm->culldistance)
if (!hm->culldistance || !hmpvs)
return true;
//check distance
@ -4940,7 +4940,7 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
return;
case ter_ent_set:
{
int idx = G_INT(OFS_PARM1);
unsigned int idx = G_INT(OFS_PARM1);
int id;
const char *newvals;
if (idx >= MAX_EDICTS) //we need some sanity limit... many ents will get removed like lights so this one isn't quite correct, but it'll be in the right sort of ballpark.
@ -7641,20 +7641,33 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
else if (inbrush)
{
//parse a plane
//Quake: ( -0 -0 16 ) ( -0 -0 32 ) ( 64 -0 16 ) texname soffset toffset rotation sscale tscale
//hexen2:( -0 -0 16 ) ( -0 -0 32 ) ( 64 -0 16 ) texname soffset toffset rotation sscale tscale utterlypointless
//Valve: ( -0 -0 16 ) ( -0 -0 32 ) ( 64 -0 16 ) texname [x y z d] [x y z d] rotation sscale tscale
//fte : ( px py pz pd ) texname [sx sy sz sd] [tx ty tz td] 0 1 1
//q3 : ( -0 -0 16 ) ( -0 -0 32 ) ( 64 -0 16 ) texname common/caulk rotation sscale tscale detailcontents unused unused
//q3bp : brushDef { ( -0 -0 16 ) ( -0 -0 32 ) ( 64 -0 16 ) ( ( x y o ) ( x y o ) ) texname detailcontents unused unused } //generate tangent+bitangent from the normal to generate base texcoords, then transform by the given 2*3 matrix. I prefer valve's way - it rotates more cleanly.
//doom3: brushDef3 { ( px py pz pd ) ( ( x y z ) ( x y z ) ) texname detailcontents unused unused }
//Quake: ( -0 -0 16 ) ( -0 -0 32 ) ( 64 -0 16 ) texname soffset toffset rotation sscale tscale
//Hexen2: ( -0 -0 16 ) ( -0 -0 32 ) ( 64 -0 16 ) texname soffset toffset rotation sscale tscale surfvalue
//Valve: ( -0 -0 16 ) ( -0 -0 32 ) ( 64 -0 16 ) texname [x y z d] [x y z d] rotation sscale tscale
//FTE : ( px py pz pd ) texname [x y z d] [x y z d] rotation sscale tscale
//Quake2: ( -0 -0 16 ) ( -0 -0 32 ) ( 64 -0 16 ) texname soffset toffset rotation sscale tscale contents surfflags surfvalue
//Quake3: ( -0 -0 16 ) ( -0 -0 32 ) ( 64 -0 16 ) texname soffset toffset rotation sscale tscale contents surfflags surfvalue
//Q3 BP: brushDef { ( -0 -0 16 ) ( -0 -0 32 ) ( 64 -0 16 ) ( ( x y o ) ( x y o ) ) texname contents surfflags surfvalue } //generate tangent+bitangent from the normal to generate base texcoords, then transform by the given 2*3 matrix. I prefer valve's way - it rotates more cleanly.
//Doom3: brushDef3 { ( px py pz pd ) ( ( x y o ) ( x y o ) ) texname contents surfflags surfvalue }
//hexen2's extra surfvalue is completely unused, and should normally be -1
//q3 ignores all contents except detail, as well surfaceflags and surfacevalue
//220 ignores rotation, provided only for UI info, scale is still used
//we don't care whether the input is planes or points.
//if we get a [ instead of an soffset then its
brushtex_t *bt;
vec3_t d1,d2;
vec3_t points[3];
vec4_t texplane[2];
float scale[2], rot;
int p;
qboolean hlstyle = false;
enum
{
TEXTYPE_AXIAL, //urgh
TEXTYPE_PLANES,
TEXTYPE_BP, //weird 2d planes
} textype = TEXTYPE_AXIAL;
memset(points, 0, sizeof(points));
if (patch_tex)
{
@ -7695,6 +7708,40 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
return false;
}
if (token[0] == '(')
{
textype = TEXTYPE_BP;
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
if (token[0] == '(')
{
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[0][0] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[0][1] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[0][3] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
if (token[0] != ')')
return false;
}
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
if (token[0] == '(')
{
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[1][0] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[1][1] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[1][3] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
if (token[0] != ')')
return false;
}
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
if (token[0] != ')')
return false;
}
bt = Terr_Brush_FindTexture(subhm, token);
if (*token == '*')
{
@ -7716,53 +7763,57 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
else
brushcontents = FTECONTENTS_SOLID;
//halflife/valve220 format has the entire [x y z dist] plane specified.
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
if (*token == '[')
if (textype != TEXTYPE_BP)
{
hlstyle = true;
//halflife/valve220 format has the entire [x y z dist] plane specified.
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
if (*token == '[')
{
textype = TEXTYPE_PLANES;
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[0][0] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[0][1] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[0][2] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[0][3] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
//]
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
//[
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[1][0] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[1][1] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[1][2] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[1][3] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
//]
}
else
{ //vanilla quake
VectorClear(texplane[0]);
VectorClear(texplane[1]);
texplane[0][3] = atof(token); //aka soffset
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[1][3] = atof(token); //aka toffset
}
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[0][0] = atof(token);
rot = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[0][1] = atof(token);
scale[0] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[0][2] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[0][3] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
//]
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
//[
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[1][0] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[1][1] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[1][2] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[1][3] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
//]
scale[1] = atof(token);
}
else
{ //vanilla quake
VectorClear(texplane[0]);
VectorClear(texplane[1]);
texplane[0][3] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
texplane[1][3] = atof(token);
}
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
rot = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
scale[0] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
scale[1] = atof(token);
else rot = 0;
//hexen2 has some extra junk that is useless - some 'light' value, but its never used and should normally be -1.
//quake2/3 on the other hand has 3 different args. Contents SurfaceFlags SurfaceValue.
@ -7821,9 +7872,31 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
}
faces[numplanes].tex = bt;
//quake's .maps use the normal to decide which texture directions to use in some lame axially-aligned way.
if (!hlstyle)
if (textype == TEXTYPE_BP)
{
float *norm = planes[numplanes];
float RotY = -atan2(norm[2], sqrt(norm[1]*norm[1] + norm[0]*norm[0]));
float RotZ = atan2(norm[1], norm[0]);
vec3_t tx = {-sin(RotZ), cos(RotZ), 0}; //tangent
vec3_t ty = {-sin(RotY)*cos(RotZ), -sin(RotY)*sin(RotZ), -cos(RotY)}; //bitangent
vec2_t tms = {texplane[0][0],texplane[0][1]}, tmt = {texplane[1][0],texplane[1][1]}; //bah, locals reuse suck
texplane[0][0] = (tx[0] * tms[0]) + (ty[0] * tms[1]); //multiply out some matricies
texplane[0][1] = (tx[1] * tms[0]) + (ty[1] * tms[1]);
texplane[0][2] = (tx[2] * tms[0]) + (ty[2] * tms[1]);
texplane[1][0] = (tx[0] * tmt[0]) + (ty[0] * tmt[1]);
texplane[1][1] = (tx[1] * tmt[0]) + (ty[1] * tmt[1]);
texplane[1][2] = (tx[2] * tmt[0]) + (ty[2] * tmt[1]);
//scale is part of the matrix.
scale[0] = 1;
scale[1] = 1;
//FIXME: these faces should NOT be scaled by the texture's size!
}
else if (textype == TEXTYPE_PLANES)
;//texture planes were properly loaded above (the scaling below is still needed though).
else if (textype == TEXTYPE_AXIAL)
{ //quake's .maps use the normal to decide which texture directions to use in some lame axially-aligned way.
float a=fabs(planes[numplanes][0]),b=fabs(planes[numplanes][1]),c=fabs(planes[numplanes][2]);
if (a>=b&&a>=c)
texplane[0][1] = 1;
@ -7833,22 +7906,22 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
texplane[1][1] = -1;
else
texplane[1][2] = -1;
}
if (rot)
{
int mas, mat;
float s,t;
float a = rot*(M_PI/180);
float cosa = cos(a), sina=sin(a);
for (mas=0; mas<2&&!texplane[0][mas]; mas++);
for (mat=0; mat<2&&!texplane[1][mat]; mat++);
for (i = 0; i < 2; i++)
if (rot)
{
s = cosa*texplane[i][mas] - sina*texplane[i][mat];
t = sina*texplane[i][mas] + cosa*texplane[i][mat];
texplane[i][mas] = s;
texplane[i][mat] = t;
int mas, mat;
float s,t;
float a = rot*(M_PI/180);
float cosa = cos(a), sina=sin(a);
for (mas=0; mas<2&&!texplane[0][mas]; mas++);
for (mat=0; mat<2&&!texplane[1][mat]; mat++);
for (i = 0; i < 2; i++)
{
s = cosa*texplane[i][mas] - sina*texplane[i][mat];
t = sina*texplane[i][mas] + cosa*texplane[i][mat];
texplane[i][mas] = s;
texplane[i][mat] = t;
}
}
}

View File

@ -1316,13 +1316,9 @@ model_t *Mod_LoadModel (model_t *mod, enum mlverbosity_e verbose)
if (mod->loadstate == MLS_NOTLOADED && *mod->name != '*')
{
mod->loadstate = MLS_LOADING;
// if (verbose == MLV_ERROR) //if its fatal on failure (ie: world), do it on the main thread and block to wait for it.
// Mod_LoadModelWorker(mod, MLV_WARN, 0);
// else
// if (verbose == MLV_ERROR || verbose == MLV_WARNSYNC)
// Mod_LoadModelWorker(mod, NULL, verbose, 0);
// COM_AddWork(WG_MAIN, Mod_LoadModelWorker, mod, NULL, verbose, 0);
// else
if (verbose == MLV_ERROR || verbose == MLV_WARNSYNC)
COM_InsertWork(WG_LOADER, Mod_LoadModelWorker, mod, NULL, verbose, 0);
else
COM_AddWork(WG_LOADER, Mod_LoadModelWorker, mod, NULL, verbose, 0);
//block until its loaded, if we care.

View File

@ -2283,6 +2283,7 @@ void R_EditLights_RegisterCommands(void)
Cvar_Register (&r_editlights_import_ambient, "Realtime Light editing/importing");
Cvar_Register (&r_editlights_import_diffuse, "Realtime Light editing/importing");
Cvar_Register (&r_editlights_import_specular, "Realtime Light editing/importing");
Cvar_Register (&r_shadow_realtime_world_importlightentitiesfrommap, "Realtime Light editing/importing");
Cvar_Register (&r_editlights, "Realtime Light editing/importing");
Cvar_Register (&r_editlights_cursordistance, "Realtime Light editing/importing");

View File

@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "glquake.h"
#include "renderque.h"
#include "shader.h"
#include "vr.h"
void R_RenderBrushPoly (msurface_t *fa);
@ -84,27 +85,28 @@ cvar_t r_xflip = CVAR("leftisright", "0");
extern cvar_t scr_fov;
shader_t *scenepp_rescaled;
shader_t *scenepp_antialias;
shader_t *scenepp_waterwarp;
shader_t *scenepp_gamma;
static shader_t *scenepp_rescaled;
static shader_t *scenepp_antialias;
static shader_t *scenepp_waterwarp;
static shader_t *scenepp_gamma;
// post processing stuff
texid_t sceneblur_texture;
texid_t scenepp_texture_warp;
texid_t scenepp_texture_edge;
static texid_t sceneblur_texture;
static texid_t scenepp_texture_warp;
static texid_t scenepp_texture_edge;
texid_t scenepp_postproc_cube;
int scenepp_postproc_cube_size;
static int scenepp_postproc_cube_size;
fbostate_t fbo_gameview;
fbostate_t fbo_postproc;
fbostate_t fbo_postproc_cube;
static fbostate_t fbo_vr;
static fbostate_t fbo_gameview;
static fbostate_t fbo_postproc;
static fbostate_t fbo_postproc_cube;
// KrimZon - init post processing - called in GL_CheckExtensions, when they're called
// I put it here so that only this file need be changed when messing with the post
// processing shaders
void GL_InitSceneProcessingShaders_WaterWarp (void)
static void GL_InitSceneProcessingShaders_WaterWarp (void)
{
scenepp_waterwarp = NULL;
if (gl_config.arb_shader_objects)
@ -130,6 +132,7 @@ void GL_InitSceneProcessingShaders_WaterWarp (void)
void GL_ShutdownPostProcessing(void)
{
GLBE_FBO_Destroy(&fbo_vr);
GLBE_FBO_Destroy(&fbo_gameview);
GLBE_FBO_Destroy(&fbo_postproc);
GLBE_FBO_Destroy(&fbo_postproc_cube);
@ -427,56 +430,71 @@ void R_RotateForEntity (float *m, float *modelview, const entity_t *e, const mod
//==================================================================================
qboolean R_GameRectIsFullscreen(void);
/*
=============
R_SetupGL
=============
*/
void R_SetupGL (float stereooffset, int i)
static void R_SetupGL (vec3_t axisorigin[4], vec4_t fovoverrides, texid_t fbo)
{
int x, x2, y2, y, w, h;
vec3_t newa;
float fov_x, fov_y;
float fov_x, fov_y, fov_l, fov_r, fov_d, fov_u;
float fovv_x, fovv_y;
TRACE(("dbg: calling R_SetupGL\n"));
if (!r_refdef.recurse)
{
newa[0] = r_refdef.viewangles[0];
newa[1] = r_refdef.viewangles[1];
newa[2] = r_refdef.viewangles[2] + gl_screenangle.value;
if (r_refdef.stereomethod)
newa[1] += r_stereo_convergence.value * (i?0.5:-0.5); //can we get away with this cheapness? rip 6dof
if (0)
if (axisorigin)
{
vec3_t paxis[3];
AngleVectors (newa, paxis[0], paxis[1], paxis[2]);
//R_ConcatRotations(r_refdef.headaxis, paxis, vpn);
VectorMA(vec3_origin, r_refdef.headaxis[0][0], paxis[0], vpn);
VectorMA(vpn, r_refdef.headaxis[0][1], paxis[1], vpn);
VectorMA(vpn, r_refdef.headaxis[0][2], paxis[2], vpn);
VectorMA(vec3_origin, axisorigin[0][0], paxis[0], vpn);
VectorMA(vpn, axisorigin[0][1], paxis[1], vpn);
VectorMA(vpn, axisorigin[0][2], paxis[2], vpn);
VectorMA(vec3_origin, r_refdef.headaxis[1][0], paxis[0], vright);
VectorMA(vright, r_refdef.headaxis[1][1], paxis[1], vright);
VectorMA(vright, r_refdef.headaxis[1][2], paxis[2], vright);
VectorMA(vec3_origin, axisorigin[1][0], paxis[0], vright);
VectorMA(vright, axisorigin[1][1], paxis[1], vright);
VectorMA(vright, axisorigin[1][2], paxis[2], vright);
VectorMA(vec3_origin, r_refdef.headaxis[2][0], paxis[0], vup);
VectorMA(vup, r_refdef.headaxis[2][1], paxis[1], vup);
VectorMA(vup, r_refdef.headaxis[2][2], paxis[2], vup);
VectorMA(vec3_origin, axisorigin[2][0], paxis[0], vup);
VectorMA(vup, axisorigin[2][1], paxis[1], vup);
VectorMA(vup, axisorigin[2][2], paxis[2], vup);
VectorMA(r_refdef.vieworg, axisorigin[3][0], vpn, r_origin);
VectorMA(r_origin, axisorigin[3][1], vright, r_origin);
VectorMA(r_origin, axisorigin[3][2], vup, r_origin);
}
else
{
AngleVectors (newa, vpn, vright, vup);
VectorCopy(r_refdef.vieworg, r_origin);
}
VectorMA(r_refdef.vieworg, stereooffset, vright, r_origin);
VectorAdd(r_origin, r_refdef.eyeoffset, r_origin);
VectorAdd(r_origin, r_refdef.eyeoffset, r_origin); //used for vr screenshots
//
// set up viewpoint
//
if (r_refdef.flags & (RDF_ALLPOSTPROC|RDF_RENDERSCALE))
if (fbo)
{
//with VR fbo postprocessing, we disable all viewport.
r_refdef.pxrect.x = 0;
r_refdef.pxrect.y = 0;
r_refdef.pxrect.width = fbo->width;
r_refdef.pxrect.height = fbo->height;
r_refdef.pxrect.maxheight = fbo->height;
}
else if (r_refdef.flags & (RDF_ALLPOSTPROC|RDF_RENDERSCALE))
{
//with fbo postprocessing, we disable all viewport.
r_refdef.pxrect.x = 0;
@ -523,7 +541,7 @@ void R_SetupGL (float stereooffset, int i)
w = x2 - x;
h = y2 - y;
if (r_refdef.stereomethod == STEREO_CROSSEYED
/* if (r_refdef.stereomethod == STEREO_CROSSEYED
#ifdef FTE_TARGET_WEB
|| r_refdef.stereomethod == STEREO_WEBVR
#endif
@ -533,32 +551,54 @@ void R_SetupGL (float stereooffset, int i)
if (i)
x += vid.fbpwidth/2;
}
*/
r_refdef.pxrect.x = x;
r_refdef.pxrect.y = y;
r_refdef.pxrect.width = w;
r_refdef.pxrect.height = h;
r_refdef.pxrect.maxheight = vid.fbpheight;
}
fov_x = r_refdef.fov_x;
fov_y = r_refdef.fov_y;
fovv_x = r_refdef.fovv_x;
fovv_y = r_refdef.fovv_y;
if ((*r_refdef.rt_destcolour[0].texname || *r_refdef.rt_depth.texname) && strcmp(r_refdef.rt_destcolour[0].texname, "megascreeny"))
if (fovoverrides)
{
r_refdef.pxrect.y = r_refdef.pxrect.maxheight - (r_refdef.pxrect.height+r_refdef.pxrect.y);
fov_y *= -1;
fovv_y *= -1;
r_refdef.flipcull ^= SHADER_CULL_FLIP;
fov_l = fovoverrides[0];
fov_r = fovoverrides[1];
fov_d = fovoverrides[2];
fov_u = fovoverrides[3];
fov_x = fov_r-fov_l;
fov_y = fov_u-fov_d;
fovv_x = fov_x;
fovv_y = fov_y;
r_refdef.flipcull = ((fov_u < fov_d)^(fov_r < fov_l))?SHADER_CULL_FLIP:0;
}
else if ((r_refdef.flags & RDF_UNDERWATER) && !(r_refdef.flags & RDF_WATERWARP))
else
{
fov_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value);
fov_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value);
fov_x = r_refdef.fov_x;
fov_y = r_refdef.fov_y;
fovv_x = r_refdef.fovv_x;
fovv_y = r_refdef.fovv_y;
fovv_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value);
fovv_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value);
if ((*r_refdef.rt_destcolour[0].texname || *r_refdef.rt_depth.texname) && strcmp(r_refdef.rt_destcolour[0].texname, "megascreeny"))
{
r_refdef.pxrect.y = r_refdef.pxrect.maxheight - (r_refdef.pxrect.height+r_refdef.pxrect.y);
fov_y *= -1;
fovv_y *= -1;
r_refdef.flipcull ^= SHADER_CULL_FLIP;
}
else if ((r_refdef.flags & RDF_UNDERWATER) && !(r_refdef.flags & RDF_WATERWARP))
{
fov_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value);
fov_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value);
fovv_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value);
fovv_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value);
}
fov_l = -fov_x / 2;
fov_r = fov_x / 2;
fov_d = -fov_y / 2;
fov_u = fov_y / 2;
}
GL_ViewportUpdate();
@ -591,12 +631,12 @@ void R_SetupGL (float stereooffset, int i)
// yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*(scr_fov.value*2)/M_PI;
// MYgluPerspective (yfov, screenaspect, 4, 4096);
Matrix4x4_CM_Projection_Far(r_refdef.m_projection_std, fov_x, fov_y, r_refdef.mindist, r_refdef.maxdist, false);
Matrix4x4_CM_Projection_Offset(r_refdef.m_projection_std, fov_l, fov_r, fov_d, fov_u, r_refdef.mindist, r_refdef.maxdist, false);
Matrix4x4_CM_Projection_Far(r_refdef.m_projection_view, fovv_x, fovv_y, r_refdef.mindist, r_refdef.maxdist, false);
}
else
{
Matrix4x4_CM_Projection_Inf(r_refdef.m_projection_std, fov_x, fov_y, r_refdef.mindist, false);
Matrix4x4_CM_Projection_Inf(r_refdef.m_projection_std, fovv_x, fovv_y, r_refdef.mindist, false);
Matrix4x4_CM_Projection_Inf(r_refdef.m_projection_view, fovv_x, fovv_y, r_refdef.mindist, false);
}
@ -672,14 +712,70 @@ R_RenderScene
r_refdef must be set before the first call
================
*/
void R_RenderScene (void)
static void R_RenderScene_Internal(void)
{
int tmpvisents = cl_numvisedicts;
TRACE(("dbg: calling R_SetFrustrum\n"));
if (!r_refdef.recurse)
R_SetFrustum (r_refdef.m_projection_std, r_refdef.m_view);
RQ_BeginFrame();
TRACE(("dbg: calling Surf_DrawWorld\n"));
Surf_DrawWorld (); // adds static entities to the list
S_ExtraUpdate (); // don't let sound get messed up if going slow
// R_DrawDecals();
TRACE(("dbg: calling R_RenderDlights\n"));
R_RenderDlights ();
if (r_refdef.recurse)
RQ_RenderBatch();
else
RQ_RenderBatchClear();
cl_numvisedicts = tmpvisents;
}
static void R_RenderEyeScene (texid_t rendertarget, vec4_t fovoverride, vec3_t axisorigin[4])
{
refdef_t refdef = r_refdef;
int pw = vid.fbpwidth;
int ph = vid.fbpheight;
int r = 0;
if (rendertarget)
{
r = GLBE_FBO_Update(&fbo_vr, FBO_RB_DEPTH, &rendertarget, 1, r_nulltex, rendertarget->width, rendertarget->height, 0);
GL_ForceDepthWritable();
qglClear (GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
vid.fbpwidth = rendertarget->width;
vid.fbpheight = rendertarget->height;
}
R_SetupGL (axisorigin, fovoverride, rendertarget);
R_RenderScene_Internal();
if (rendertarget)
{
GLBE_FBO_Pop(r);
if (gl_finish.ival)
qglFinish();
}
r_refdef = refdef;
vid.fbpwidth = pw;
vid.fbpheight = ph;
}
static void R_RenderScene (void)
{
float stereooffset[2];
int stereoframes = 1;
int stereomode;
int i;
int tmpvisents = cl_numvisedicts; /*world rendering is allowed to add additional ents, but we don't want to keep them for recursive views*/
int cull = r_refdef.flipcull;
vec3_t axisorg[4], ang;
stereomode = r_refdef.stereomethod;
if (stereomode == STEREO_QUAD)
@ -706,7 +802,19 @@ void R_RenderScene (void)
stereoframes = 2;
}
for (i = 0; i < stereoframes; i++)
r_framecount++;
if (vid.vr && !r_refdef.recurse && vid.vr->Render(R_RenderEyeScene))
; //we drew something VR-ey
else if (stereomode == STEREO_OFF)
{
GL_ForceDepthWritable();
qglClear (GL_DEPTH_BUFFER_BIT);
r_framecount++;
R_SetupGL (NULL, NULL, NULL);
R_RenderScene_Internal();
}
else for (i = 0; i < stereoframes; i++)
{
switch (stereomode)
{
@ -765,31 +873,15 @@ void R_RenderScene (void)
r_framecount++;
}
TRACE(("dbg: calling R_SetupGL\n"));
R_SetupGL (stereooffset[i], i);
TRACE(("dbg: calling R_SetFrustrum\n"));
if (!r_refdef.recurse)
R_SetFrustum (r_refdef.m_projection_std, r_refdef.m_view);
RQ_BeginFrame();
TRACE(("dbg: calling Surf_DrawWorld\n"));
Surf_DrawWorld (); // adds static entities to the list
S_ExtraUpdate (); // don't let sound get messed up if going slow
// R_DrawDecals();
TRACE(("dbg: calling R_RenderDlights\n"));
R_RenderDlights ();
if (r_refdef.recurse)
RQ_RenderBatch();
else
RQ_RenderBatchClear();
cl_numvisedicts = tmpvisents;
ang[0] = 0;
ang[1] = r_stereo_convergence.value * (i?0.5:-0.5);
ang[2] = 0;;
AngleVectors(ang, axisorg[0], axisorg[1], axisorg[2]);
axisorg[3][0] = 0;
axisorg[3][1] = stereooffset[i];
axisorg[3][2] = 0;
R_SetupGL (axisorg, NULL, NULL);
R_RenderScene_Internal ();
}
switch (stereomode)
@ -1354,11 +1446,6 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist[2],
R_Clear
=============
*/
qboolean R_GameRectIsFullscreen(void)
{
return r_refdef.grect.x == 0 && r_refdef.grect.y == 0 && (unsigned)r_refdef.grect.width == vid.fbvwidth && (unsigned)r_refdef.grect.height == vid.fbvheight;
}
int gldepthfunc = GL_LEQUAL;
qboolean depthcleared;
void R_Clear (qboolean fbo)

View File

@ -6956,7 +6956,7 @@ void Shader_Default2D(parsestate_t *ps, const char *shortname, const void *genar
"sort additive\n"
"}\n"
);
TEXASSIGN(s->defaulttextures->base, R_LoadHiResTexture(s->name, genargs, IF_PREMULTIPLYALPHA|IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP));
TEXASSIGN(s->defaulttextures->base, R_LoadHiResTexture(s->name, genargs, IF_PREMULTIPLYALPHA|IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP|IF_HIGHPRIORITY));
}
else
{
@ -6973,7 +6973,7 @@ void Shader_Default2D(parsestate_t *ps, const char *shortname, const void *genar
"sort additive\n"
"}\n"
);
TEXASSIGN(s->defaulttextures->base, R_LoadHiResTexture(s->name, genargs, IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP));
TEXASSIGN(s->defaulttextures->base, R_LoadHiResTexture(s->name, genargs, IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP|IF_HIGHPRIORITY));
}
}
void Shader_PolygonShader(struct shaderparsestate_s *ps, const char *shortname, const void *args)

View File

@ -57,6 +57,7 @@ cvar_t r_shadow_scissor = CVARD("r_shadow_scissor", "1", "constrains stencil sha
cvar_t r_shadow_realtime_world = CVARFD ("r_shadow_realtime_world", "0", CVAR_ARCHIVE, "Enables the use of static/world realtime lights.");
cvar_t r_shadow_realtime_world_shadows = CVARF ("r_shadow_realtime_world_shadows", "1", CVAR_ARCHIVE);
cvar_t r_shadow_realtime_world_lightmaps = CVARFD ("r_shadow_realtime_world_lightmaps", "0", 0, "Specifies how much of the map's normal lightmap to retain when using world realtime lights. 0 completely replaces lighting.");
cvar_t r_shadow_realtime_world_importlightentitiesfrommap = CVARFD ("r_shadow_realtime_world_importlightentitiesfrommap", "1", 0, "Controls default loading of world lightmaps.\n0: Load explicit .rtlight files only.\n1: Load explicit lights then try fallback to parsing the entities lump.\n2: Load only the entities lump.");
cvar_t r_shadow_realtime_dlight = CVARFD ("r_shadow_realtime_dlight", "1", CVAR_ARCHIVE, "Enables the use of dynamic realtime lights, allowing explosions to use bumpmaps etc properly.");
cvar_t r_shadow_realtime_dlight_shadows = CVARFD ("r_shadow_realtime_dlight_shadows", "1", CVAR_ARCHIVE, "Allows dynamic realtime lights to cast shadows as they move.");
cvar_t r_shadow_realtime_dlight_ambient = CVAR ("r_shadow_realtime_dlight_ambient", "0");
@ -3731,7 +3732,7 @@ void Sh_PreGenerateLights(void)
if ((r_shadow_realtime_dlight.ival || r_shadow_realtime_world.ival) && rtlights_max == RTL_FIRST)
{
qboolean okay = false;
if (!okay)
if (!okay && r_shadow_realtime_world_importlightentitiesfrommap.ival <= 1)
okay |= R_LoadRTLights();
if (!okay)
{
@ -3739,9 +3740,9 @@ void Sh_PreGenerateLights(void)
R_StaticEntityToRTLight(i);
okay |= rtlights_max != RTL_FIRST;
}
if (!okay)
if (!okay && r_shadow_realtime_world_importlightentitiesfrommap.ival >= 1)
okay |= R_ImportRTLights(Mod_GetEntitiesString(cl.worldmodel));
if (!okay && r_shadow_realtime_world.ival && r_shadow_realtime_world_lightmaps.value != 1)
if (!okay && r_shadow_realtime_world.ival && r_shadow_realtime_world_lightmaps.value < 0.5)
{
r_shadow_realtime_world_lightmaps.value = 1;
Con_Printf(CON_WARNING "No lights detected in map.\n");

View File

@ -1,6 +1,7 @@
#include "quakedef.h"
#if defined(GLQUAKE) && defined(USE_EGL)
#include "gl_videgl.h"
#include "vr.h"
//EGL_KHR_gl_colorspace
#ifndef EGL_GL_COLORSPACE_KHR
@ -42,7 +43,7 @@ static EGLBoolean (EGLAPIENTRY *qeglSwapBuffers)(EGLDisplay dpy, EGLSurface surf
static EGLBoolean (EGLAPIENTRY *qeglMakeCurrent)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
static EGLContext (EGLAPIENTRY *qeglCreateContext)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
static EGLBoolean (EGLAPIENTRY *qeglDestroyContext)(EGLDisplay dpy, EGLContext ctx);
static void * (EGLAPIENTRY *qeglGetProcAddress) (char *name);
static void * (EGLAPIENTRY *qeglGetProcAddress) (const char *name);
static EGLBoolean (EGLAPIENTRY *qeglSwapInterval) (EGLDisplay display, EGLint interval);
@ -426,6 +427,25 @@ qboolean EGL_InitWindow (rendererstate_t *info, int eglplat, void *nwindow, EGLN
EGL_UpdateSwapInterval();
if (info->vr)
{
vrsetup_t vrsetup = {sizeof(vrsetup)};
vrsetup.vrplatform = VR_EGL;
vrsetup.egl.getprocaddr = qeglGetProcAddress;
vrsetup.egl.egldisplay = egldpy;
vrsetup.egl.eglconfig = cfg;
vrsetup.egl.eglcontext = eglctx;
if (!info->vr->Prepare(&vrsetup) ||
!info->vr->Init(&vrsetup, info))
{
info->vr->Shutdown();
info->vr = NULL;
}
else
vid.vr = info->vr;
}
return true;
}

View File

@ -77,6 +77,7 @@ static qboolean XVK_SetupSurface_XCB(void);
#include "gl_videgl.h"
#endif
#include "glquake.h"
#include "vr.h"
#endif
#define USE_VMODE
@ -2102,6 +2103,19 @@ static qboolean GLX_Init(rendererstate_t *info, GLXFBConfig fbconfig, XVisualInf
// extern cvar_t vid_gl_context_selfreset;
extern cvar_t vid_gl_context_noerror;
vrsetup_t setup = {sizeof(setup)};
setup.vrplatform = VR_X11_GLX;
setup.x11_glx.display = vid_dpy;
setup.x11_glx.visualid = visinfo->visualid;
setup.x11_glx.glxfbconfig = fbconfig;
setup.x11_glx.drawable = vid_window;
if (info->vr && !info->vr->Prepare(&setup))
{
info->vr->Shutdown();
info->vr = NULL;
}
if (fbconfig && glx.CreateContextAttribs)
{
unsigned int majorver=1, minorver=1;
@ -2123,6 +2137,12 @@ static qboolean GLX_Init(rendererstate_t *info, GLXFBConfig fbconfig, XVisualInf
else
minorver = 0;
if (majorver < setup.minver.major || (majorver == setup.minver.major && minorver < setup.minver.minor))
{ //if vr stuff requires a minimum version then try and ask for that now
majorver = setup.minver.major;
minorver = setup.minver.minor;
}
//some weirdness for you:
//3.0 simply marked stuff as deprecated, without removing it.
//3.1 removed it (moved to the optional GL_ARB_compatibility extension, which shouldn't be supported in a forward-compatible context).
@ -2191,6 +2211,15 @@ static qboolean GLX_Init(rendererstate_t *info, GLXFBConfig fbconfig, XVisualInf
return false;
}
setup.x11_glx.glxcontext = ctx;
if (info->vr && !info->vr->Init(&setup, info))
{
info->vr->Shutdown();
return false;
}
vid.vr = info->vr;
//okay, we have a context, now init OpenGL-proper.
return GL_Init(info, &GLX_GetSymbol);
}
@ -4323,7 +4352,7 @@ static qboolean X11VID_Init (rendererstate_t *info, unsigned char *palette, int
break;
}
#endif
Con_Printf(CON_ERROR "Failed to create a vulkan context.\n");
//Con_Printf(CON_ERROR "Failed to create a vulkan context.\n");
GLVID_Shutdown();
return false;
#endif

View File

@ -27,6 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "winquake.h"
#include "resource.h"
#include "shader.h"
#include "vr.h"
#include <commctrl.h>
#ifdef USE_EGL
@ -1447,6 +1448,8 @@ static int GLVID_SetMode (rendererstate_t *info, unsigned char *palette)
#endif
// HDC hdc;
vrsetup_t setup = {sizeof(setup)};
TRACE(("dbg: GLVID_SetMode\n"));
// so Con_Printfs don't mess us up by forcing vid and snd updates
@ -1465,6 +1468,13 @@ static int GLVID_SetMode (rendererstate_t *info, unsigned char *palette)
#ifdef VKQUAKE
case MODE_NVVULKAN:
#endif
setup.vrplatform = VR_WIN_WGL;
if (info->vr && !info->vr->Prepare(&setup))
{
info->vr->Shutdown();
info->vr = NULL;
}
// Set either the fullscreen or windowed mode
qwglChoosePixelFormatARB = NULL;
qwglGetPixelFormatAttribfvARB = NULL;
@ -1515,10 +1525,18 @@ static int GLVID_SetMode (rendererstate_t *info, unsigned char *palette)
if (modestate == MS_FULLWINDOW)
ShowWindow (dibwindow, SW_SHOWMAXIMIZED);
else
ShowWindow (dibwindow, SW_SHOWNORMAL);
ShowWindow (dibwindow, SW_SHOWNORMAL);
if (!GL_Init(info, getglfunc))
return false;
setup.wgl.hdc = maindc;
setup.wgl.hglrc = baseRC;
if (info->vr && !info->vr->Init(&setup, info))
{
info->vr->Shutdown();
return false;
}
vid.vr = info->vr;
if (qwglGetPixelFormatAttribfvARB) //just for debugging info.
{

View File

@ -13532,7 +13532,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, QCC_def_t *arraydef, char *ar
pr_scope->filen = thearray.sym->filen;
pr_scope->s_filed = thearray.sym->s_filed;
index = QCC_PR_GetSRef(type_float, "__indexg", pr_scope, true, 0, false);
index = QCC_PR_GetSRef(type_float, "__indexg", pr_scope, true, 0, GDF_PARAMETER);
scope->initialized = true;
scope->symboldata[0]._int = pr_scope - functions;
@ -13722,8 +13722,8 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, QCC_def_t *arraydef, char *ar
pr_scope->filen = thearray.sym->filen;
pr_scope->s_filed = thearray.sym->s_filed;
index = QCC_PR_GetSRef(type_float, "indexs___", pr_scope, true, 0, false);
value = QCC_PR_GetSRef(thearray.cast, "value___", pr_scope, true, 0, false);
index = QCC_PR_GetSRef(type_float, "indexs___", pr_scope, true, 0, GDF_PARAMETER);
value = QCC_PR_GetSRef(thearray.cast, "value___", pr_scope, true, 0, GDF_PARAMETER);
scope->initialized = true;
scope->symboldata[0]._int = pr_scope - functions;

View File

@ -1899,7 +1899,7 @@ void PR_SpawnInitialEntities(const char *file)
}
void SV_RegisterH2CustomTents(void);
void Q_InitProgs(qboolean cinematic)
void Q_InitProgs(enum initprogs_e flags)
{
int i, i2;
func_t f, f2;
@ -1924,189 +1924,237 @@ void Q_InitProgs(qboolean cinematic)
svs.numprogs=0;
d1 = FS_FLocateFile("progs.dat", FSLF_DONTREFERENCE|FSLF_DEEPONFAILURE|FSLF_IGNOREBASEDEPTH, NULL);
d2 = FS_FLocateFile("qwprogs.dat", FSLF_DONTREFERENCE|FSLF_DEEPONFAILURE|FSLF_IGNOREBASEDEPTH, NULL);
//FIXME id1/progs.dat vs qw/qwprogs.dat - these should be considered to have the same priority.
if (d1 < d2) //progs.dat is closer to the gamedir
strcpy(addons, "progs.dat");
else if (d1 > d2) //qwprogs.dat is closest
if (flags & INITPROGS_EDITOR)
{
strcpy(addons, "qwprogs.dat");
d1 = d2;
oldprnum = AddProgs("sseditor.dat");
PR_LoadGlabalStruct(true);
}
//both are an equal depth - same path.
else if (deathmatch.value && !COM_CheckParm("-game")) //if deathmatch, default to qw
else
{
strcpy(addons, "qwprogs.dat");
d1 = d2;
}
else //single player/coop is better done with nq.
{
strcpy(addons, "progs.dat");
}
//if progs cvar is left blank and a q2 map is loaded, the server will use the q2 game dll.
//if you do set a value here, q2 dll is not used.
//hexen2 - maplist contains a list of maps that we need to use an alternate progs.dat for.
d2 = COM_FDepthFile("maplist.txt", true);
if (d2 <= d1)//Use it if the maplist.txt file is within a more or equal important gamedir.
{
int j, maps;
char *f;
f = COM_LoadTempFile("maplist.txt", 0, NULL);
f = COM_Parse(f);
maps = atoi(com_token);
for (j = 0; j < maps; j++)
d1 = FS_FLocateFile("progs.dat", FSLF_DONTREFERENCE|FSLF_DEEPONFAILURE|FSLF_IGNOREBASEDEPTH, NULL);
d2 = FS_FLocateFile("qwprogs.dat", FSLF_DONTREFERENCE|FSLF_DEEPONFAILURE|FSLF_IGNOREBASEDEPTH, NULL);
//FIXME id1/progs.dat vs qw/qwprogs.dat - these should be considered to have the same priority.
if (d1 < d2) //progs.dat is closer to the gamedir
strcpy(addons, "progs.dat");
else if (d1 > d2) //qwprogs.dat is closest
{
strcpy(addons, "qwprogs.dat");
d1 = d2;
}
//both are an equal depth - same path.
else if (deathmatch.value && !COM_CheckParm("-game")) //if deathmatch, default to qw
{
strcpy(addons, "qwprogs.dat");
d1 = d2;
}
else //single player/coop is better done with nq.
{
strcpy(addons, "progs.dat");
}
//if progs cvar is left blank and a q2 map is loaded, the server will use the q2 game dll.
//if you do set a value here, q2 dll is not used.
//hexen2 - maplist contains a list of maps that we need to use an alternate progs.dat for.
d2 = COM_FDepthFile("maplist.txt", true);
if (d2 <= d1)//Use it if the maplist.txt file is within a more or equal important gamedir.
{
int j, maps;
char *f;
f = COM_LoadTempFile("maplist.txt", 0, NULL);
f = COM_Parse(f);
if (!Q_strcasecmp(svs.name, com_token))
maps = atoi(com_token);
for (j = 0; j < maps; j++)
{
f = COM_Parse(f);
strcpy(addons, com_token);
break;
if (!Q_strcasecmp(svs.name, com_token))
{
f = COM_Parse(f);
strcpy(addons, com_token);
break;
}
f = strchr(f, '\n'); //skip to the end of the line.
}
f = strchr(f, '\n'); //skip to the end of the line.
}
}
/*if pr_ssqc_progs cvar is set, override the default*/
if (*pr_ssqc_progs.string && strlen(pr_ssqc_progs.string)<64 && *pr_ssqc_progs.string != '*') //a * is a special case to not load a q2 dll.
{
Q_strncpyz(addons, pr_ssqc_progs.string, MAX_QPATH);
COM_DefaultExtension(addons, ".dat", sizeof(addons));
}
oldprnum= AddProgs(addons);
/*try to load qwprogs.dat if we didn't manage to load one yet*/
if (oldprnum < 0 && strcmp(addons, "qwprogs.dat"))
{
#ifndef SERVERONLY
if (SCR_UpdateScreen)
SCR_UpdateScreen();
#endif
oldprnum= AddProgs("qwprogs.dat");
}
/*try to load qwprogs.dat if we didn't manage to load one yet*/
if (oldprnum < 0 && strcmp(addons, "progs.dat"))
{
#ifndef SERVERONLY
if (SCR_UpdateScreen)
SCR_UpdateScreen();
#endif
oldprnum= AddProgs("progs.dat");
}
if (oldprnum < 0)
{
PR_LoadGlabalStruct(true);
if (cinematic) //making this fatal, because it sucks to sit through a cinematic only to find the game isn't playable after.
SV_Error("No gamecode available. Try using the downloads menu.\n");
Con_Printf(CON_ERROR"Running without gamecode\n");
}
if (oldprnum >= 0)
f = PR_FindFunction (svprogfuncs, "AddAddonProgs", oldprnum);
else
f = 0;
/* if (num)
{
//restore progs
for (i = 1; i < num; i++)
/*if pr_ssqc_progs cvar is set, override the default*/
if (*pr_ssqc_progs.string && strlen(pr_ssqc_progs.string)<64 && *pr_ssqc_progs.string != '*') //a * is a special case to not load a q2 dll.
{
if (f)
Q_strncpyz(addons, pr_ssqc_progs.string, MAX_QPATH);
COM_DefaultExtension(addons, ".dat", sizeof(addons));
}
oldprnum= AddProgs(addons);
/*try to load qwprogs.dat if we didn't manage to load one yet*/
if (oldprnum < 0 && strcmp(addons, "qwprogs.dat"))
{
#ifndef SERVERONLY
if (SCR_UpdateScreen)
SCR_UpdateScreen();
#endif
oldprnum= AddProgs("qwprogs.dat");
}
/*try to load qwprogs.dat if we didn't manage to load one yet*/
if (oldprnum < 0 && strcmp(addons, "progs.dat"))
{
#ifndef SERVERONLY
if (SCR_UpdateScreen)
SCR_UpdateScreen();
#endif
oldprnum= AddProgs("progs.dat");
}
if (oldprnum < 0)
{
PR_LoadGlabalStruct(true);
if (flags & INITPROGS_REQUIRE)
SV_Error("No gamecode available. Try using the downloads menu.\n");
Con_Printf(CON_ERROR"Running without gamecode\n");
}
if (oldprnum >= 0)
f = PR_FindFunction (svprogfuncs, "AddAddonProgs", oldprnum);
else
f = 0;
/* if (num)
{
//restore progs
for (i = 1; i < num; i++)
{
pr_globals = PR_globals(PR_CURRENT);
G_SETSTRING(OFS_PARM0, svs.progsnames[i]);
PR_ExecuteProgram (f);
if (f)
{
pr_globals = PR_globals(PR_CURRENT);
G_SETSTRING(OFS_PARM0, svs.progsnames[i]);
PR_ExecuteProgram (f);
}
else
{
prnum = AddProgs(svs.progsnames[i]);
f2 = PR_FindFunction ( "init", prnum);
if (f2)
{
pr_globals = PR_globals(PR_CURRENT);
G_PROG(OFS_PARM0) = oldprnum;
PR_ExecuteProgram(f2);
}
oldprnum=prnum;
}
}
}
*/
//additional (always) progs
as = NULL;
a = COM_LoadStackFile("mod.gam", addons, 2048, NULL);
if (a)
{
if (progstype == PROG_QW)
as = strstr(a, "extraqwprogs=");
else
as = strstr(a, "extraprogs=");
if (as)
{
prnum = AddProgs(svs.progsnames[i]);
f2 = PR_FindFunction ( "init", prnum);
for (a = as+13; *a; a++)
{
if (*a < ' ')
{
*a = '\0';
break;
}
}
a = (as+=13);
}
}
if (as)
{
while(*a)
{
if (*a == ';')
{
*a = '\0';
for (i = 0; i < svs.numprogs; i++) //don't add if already added
{
if (!strcmp(svs.progsnames[i], as))
break;
}
if (i == svs.numprogs)
{
if (f)
{
pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
G_INT(OFS_PARM0) = (int)PR_TempString(svprogfuncs, as);
PR_ExecuteProgram (svprogfuncs, f);
}
else
{
prnum = AddProgs(as);
if (prnum>=0)
{
f2 = PR_FindFunction (svprogfuncs, "init", prnum);
if (f2)
{
pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
G_PROG(OFS_PARM0) = oldprnum;
PR_ExecuteProgram(svprogfuncs, f2);
}
oldprnum=prnum;
}
}
}
*a = ';';
as = a+1;
}
a++;
}
}
if (COM_FDepthFile("fteadd.dat", true)!=FDEPTH_MISSING)
{
prnum = AddProgs("fteadd.dat");
if (prnum>=0)
{
f2 = PR_FindFunction (svprogfuncs, "init", prnum);
if (f2)
{
pr_globals = PR_globals(PR_CURRENT);
pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
G_PROG(OFS_PARM0) = oldprnum;
PR_ExecuteProgram(f2);
PR_ExecuteProgram(svprogfuncs, f2);
}
oldprnum=prnum;
}
}
}
*/
//additional (always) progs
as = NULL;
a = COM_LoadStackFile("mod.gam", addons, 2048, NULL);
prnum = 0;
if (a)
{
if (progstype == PROG_QW)
as = strstr(a, "extraqwprogs=");
else
as = strstr(a, "extraprogs=");
if (as)
switch (sv.world.worldmodel->fromgame) //spawn functions for - spawn funcs still come from the first progs found.
{
for (a = as+13; *a; a++)
{
if (*a < ' ')
{
*a = '\0';
break;
}
}
a = (as+=13);
}
}
if (as)
{
while(*a)
{
if (*a == ';')
{
*a = '\0';
for (i = 0; i < svs.numprogs; i++) //don't add if already added
{
if (!strcmp(svs.progsnames[i], as))
break;
}
if (i == svs.numprogs)
{
if (f)
{
pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
G_INT(OFS_PARM0) = (int)PR_TempString(svprogfuncs, as);
PR_ExecuteProgram (svprogfuncs, f);
}
else
{
prnum = AddProgs(as);
if (prnum>=0)
{
f2 = PR_FindFunction (svprogfuncs, "init", prnum);
case fg_quake2:
if (COM_FDepthFile("q2bsp.dat", true)!=FDEPTH_MISSING)
prnum = AddProgs("q2bsp.dat");
break;
case fg_quake3:
if (COM_FDepthFile("q3bsp.dat", true)!=FDEPTH_MISSING)
prnum = AddProgs("q3bsp.dat");
else if (COM_FDepthFile("q2bsp.dat", true)!=FDEPTH_MISSING) //fallback
prnum = AddProgs("q2bsp.dat");
break;
case fg_doom:
if (COM_FDepthFile("doombsp.dat", true)!=FDEPTH_MISSING)
prnum = AddProgs("doombsp.dat");
break;
case fg_halflife:
if (COM_FDepthFile("hlbsp.dat", true)!=FDEPTH_MISSING)
prnum = AddProgs("hlbsp.dat");
break;
if (f2)
{
pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
G_PROG(OFS_PARM0) = oldprnum;
PR_ExecuteProgram(svprogfuncs, f2);
}
oldprnum=prnum;
}
}
}
*a = ';';
as = a+1;
}
a++;
default:
break;
}
}
if (COM_FDepthFile("fteadd.dat", true)!=FDEPTH_MISSING)
{
prnum = AddProgs("fteadd.dat");
if (prnum>=0)
{
f2 = PR_FindFunction (svprogfuncs, "init", prnum);
@ -2119,95 +2167,96 @@ void Q_InitProgs(qboolean cinematic)
}
oldprnum=prnum;
}
}
prnum = 0;
switch (sv.world.worldmodel->fromgame) //spawn functions for - spawn funcs still come from the first progs found.
{
case fg_quake2:
if (COM_FDepthFile("q2bsp.dat", true)!=FDEPTH_MISSING)
prnum = AddProgs("q2bsp.dat");
break;
case fg_quake3:
if (COM_FDepthFile("q3bsp.dat", true)!=FDEPTH_MISSING)
prnum = AddProgs("q3bsp.dat");
else if (COM_FDepthFile("q2bsp.dat", true)!=FDEPTH_MISSING) //fallback
prnum = AddProgs("q2bsp.dat");
break;
case fg_doom:
if (COM_FDepthFile("doombsp.dat", true)!=FDEPTH_MISSING)
prnum = AddProgs("doombsp.dat");
break;
case fg_halflife:
if (COM_FDepthFile("hlbsp.dat", true)!=FDEPTH_MISSING)
prnum = AddProgs("hlbsp.dat");
break;
default:
break;
}
if (prnum>=0)
{
f2 = PR_FindFunction (svprogfuncs, "init", prnum);
if (f2)
//progs depended on by maps.
a = as = COM_LoadStackFile(va("maps/%s.inf", svs.name), addons, sizeof(addons), NULL);
if (a)
{
pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
G_PROG(OFS_PARM0) = oldprnum;
PR_ExecuteProgram(svprogfuncs, f2);
}
oldprnum=prnum;
}
//progs depended on by maps.
a = as = COM_LoadStackFile(va("maps/%s.inf", svs.name), addons, sizeof(addons), NULL);
if (a)
{
if (progstype == PROG_QW)
as = strstr(a, "qwprogs=");
else
as = strstr(a, "progs=");
if (as)
{
for (a = as+11; *a; a++)
{
if (*a < ' ')
if (progstype == PROG_QW)
as = strstr(a, "qwprogs=");
else
as = strstr(a, "progs=");
if (as)
{
*a = '\0';
break;
for (a = as+11; *a; a++)
{
if (*a < ' ')
{
*a = '\0';
break;
}
}
a = (as+=11);
}
}
a = (as+=11);
}
}
if (as)
{
while(*a)
if (as)
{
if (*a == ';')
while(*a)
{
if (*a == ';')
{
*a = '\0';
for (i = 0; i < svs.numprogs; i++) //don't add if already added
{
if (!strcmp(svs.progsnames[i], as))
break;
}
if (i == svs.numprogs)
{
if (f)
{
pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
G_INT(OFS_PARM0) = (int)PR_TempString(svprogfuncs, as);
PR_ExecuteProgram (svprogfuncs, f);
}
else
{
prnum = AddProgs(as);
if (prnum>=0)
{
f2 = PR_FindFunction (svprogfuncs, "init", prnum);
if (f2)
{
pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
G_PROG(OFS_PARM0) = oldprnum;
PR_ExecuteProgram(svprogfuncs, f2);
}
oldprnum=prnum;
}
}
}
*a = ';';
as = a+1;
}
a++;
}
}
//add any addons specified
for (i2 = 0; i2 < MAXADDONS; i2++)
{
if (*sv_addon[i2].string)
{
*a = '\0';
for (i = 0; i < svs.numprogs; i++) //don't add if already added
{
if (!strcmp(svs.progsnames[i], as))
if (!strcmp(svs.progsnames[i], sv_addon[i2].string))
break;
}
if (i == svs.numprogs)
if (i == svs.numprogs) //Not added yet. Add it.
{
if (f)
{
pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
G_INT(OFS_PARM0) = (int)PR_TempString(svprogfuncs, as);
G_INT(OFS_PARM0) = (int)PR_TempString(svprogfuncs, sv_addon[i2].string);
PR_ExecuteProgram (svprogfuncs, f);
}
else
{
prnum = AddProgs(as);
if (prnum>=0)
prnum = AddProgs(sv_addon[i2].string);
if (prnum >= 0)
{
f2 = PR_FindFunction (svprogfuncs, "init", prnum);
if (f2)
{
pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
@ -2216,48 +2265,8 @@ void Q_InitProgs(qboolean cinematic)
}
oldprnum=prnum;
}
}
}
*a = ';';
as = a+1;
}
a++;
}
}
//add any addons specified
for (i2 = 0; i2 < MAXADDONS; i2++)
{
if (*sv_addon[i2].string)
{
for (i = 0; i < svs.numprogs; i++) //don't add if already added
{
if (!strcmp(svs.progsnames[i], sv_addon[i2].string))
break;
}
if (i == svs.numprogs) //Not added yet. Add it.
{
if (f)
{
pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
G_INT(OFS_PARM0) = (int)PR_TempString(svprogfuncs, sv_addon[i2].string);
PR_ExecuteProgram (svprogfuncs, f);
}
else
{
prnum = AddProgs(sv_addon[i2].string);
if (prnum >= 0)
{
f2 = PR_FindFunction (svprogfuncs, "init", prnum);
if (f2)
{
pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
G_PROG(OFS_PARM0) = oldprnum;
PR_ExecuteProgram(svprogfuncs, f2);
}
oldprnum=prnum;
}
}
}
}
@ -11038,10 +11047,10 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"drawtextfield", PF_Fixme, 0, 0, 0, 0/*314*/, D("float(vector pos, vector size, float alignflags, string text)", "Draws a multi-line block of text, including word wrapping and alignment. alignflags bits are RTLB, typically 3. Returns the total number of lines.")},// (EXT_CSQC)
{"drawline", PF_Fixme, 0, 0, 0, 315, D("void(float width, vector pos1, vector pos2, vector rgb, float alpha, optional float drawflag)", "Draws a 2d line between the two 2d points.")},// (EXT_CSQC)
{"iscachedpic", PF_Fixme, 0, 0, 0, 316, D("float(string name)", "Checks to see if the image is currently loaded. Engines might lie, or cache between maps.")},// (EXT_CSQC)
{"precache_pic", PF_Fixme, 0, 0, 0, 317, D("string(string name, optional float trywad)", "Forces the engine to load the named image. If trywad is specified, the specified name must lack any path and extension.")},// (EXT_CSQC)
{"precache_pic", PF_Fixme, 0, 0, 0, 317, D("string(string name, optional float flags)", "Forces the engine to load the named image. Flags are a bitmask of the PRECACHE_PIC_* flags.")},// (EXT_CSQC)
{"r_uploadimage", PF_Fixme, 0, 0, 0, 0, D("void(string imagename, int width, int height, void *pixeldata, optional int datasize, optional int format)", "Updates a texture with the specified rgba data (uploading it to the gpu). Will be created if needed. If datasize is specified then the image is decoded (eg .ktx or .dds data) instead of being raw R8G8B8A data. You'll typically want shaderforname to also generate a shader to use the texture.")},
{"r_readimage", PF_Fixme, 0, 0, 0, 0, D("int*(string filename, __out int width, __out int height)", "Reads and decodes an image from disk, providing raw R8G8B8A8 pixel data. Should not be used for dds or ktx etc formats. Returns __NULL__ if the image could not be read for any reason. Use memfree to free the data once you're done with it.")},
{"drawgetimagesize",PF_Fixme, 0, 0, 0, 318, D("#define draw_getimagesize drawgetimagesize\nvector(string picname)", "Returns the dimensions of the named image. Images specified with .lmp should give the original .lmp's dimensions even if texture replacements use a different resolution.")},// (EXT_CSQC)
{"drawgetimagesize",PF_Fixme, 0, 0, 0, 318, D("#define draw_getimagesize drawgetimagesize\nvector(string picname)", "Returns the dimensions of the named image. Images specified with .lmp should give the original .lmp's dimensions even if texture replacements use a different resolution. WARNING: this function may be slow if used without or directly after its initial precache_pic.")},// (EXT_CSQC)
{"freepic", PF_Fixme, 0, 0, 0, 319, D("void(string name)", "Tells the engine that the image is no longer needed. The image will appear to be new the next time its needed.")},// (EXT_CSQC)
//320
{"drawcharacter", PF_Fixme, 0, 0, 0, 320, D("float(vector position, float character, vector size, vector rgb, float alpha, optional float drawflag)", "Draw the given quake character at the given position.\nIf flag&4, the function will consider the char to be a unicode char instead (or display as a ? if outside the 32-127 range).\nsize should normally be something like '8 8 0'.\nrgb should normally be '1 1 1'\nalpha normally 1.\nSoftware engines may assume the named defaults.\nNote that ALL text may be rescaled on the X axis due to variable width fonts. The X axis may even be ignored completely.")},// (EXT_CSQC, [EXT_CSQC_???])
@ -12636,6 +12645,10 @@ void PR_DumpPlatform_f(void)
{"STAT_USER", "const float", QW|NQ|CS, D("Custom user stats start here (lower values are reserved for engine use)."), 32},
#endif
{"PRECACHE_PIC_FROMWAD","const float", CS|MENU, D("Attempt to load it from the legacy gfx.wad file (usually its better to just use a gfx/ prefix instead)."), 1},
{"PRECACHE_PIC_DOWNLOAD","const float", CS|MENU, D("If no image could be loaded then attempt to download one from the server. This flag can cause the function to block until completion. (Slow!)"), 256},
{"PRECACHE_PIC_TEST", "const float", CS|MENU, D("The precache will block until the image is fully loaded, returning a null string on failure. (Slow!)"), 512},
{"VF_MIN", "const float", CS|MENU, D("The top-left of the 3d viewport in screenspace. The VF_ values are used via the setviewprop/getviewprop builtins."), VF_MIN},
{"VF_MIN_X", "const float", CS|MENU, NULL, VF_MIN_X},
{"VF_MIN_Y", "const float", CS|MENU, NULL, VF_MIN_Y},

View File

@ -29,7 +29,13 @@ void SVQ1_CvarChanged(cvar_t *var);
void Q_SetProgsParms(qboolean forcompiler);
void PR_Deinit(void); //server shutting down
void PR_LoadGlabalStruct(qboolean muted);
void Q_InitProgs(qboolean cinematic);
enum initprogs_e
{
INITPROGS_NORMAL = 0,
INITPROGS_EDITOR = 1<<0,
INITPROGS_REQUIRE = 1<<1,
};
void Q_InitProgs(enum initprogs_e flags);
void PR_SpawnInitialEntities(const char *file);
void PR_RegisterFields(void);
void PR_Init(void);

View File

@ -404,8 +404,9 @@ static int QDECL ShowMapList (const char *name, qofs_t flags, time_t mtime, void
"maps/%s.png"
};
size_t u;
char stripped[64];
char stripped[MAX_QPATH];
char completed[256];
char *ext = parm;
if (name[5] == 'b' && name[6] == '_') //skip box models
return true;
@ -423,35 +424,29 @@ static int QDECL ShowMapList (const char *name, qofs_t flags, time_t mtime, void
}
#endif
COM_StripExtension(name+5, stripped, sizeof(stripped));
name += 5; //skip the maps/ prefix
COM_StripExtension(name, stripped, sizeof(stripped));
for (u = 0; u < countof(levelshots); u++)
{
const char *ls = va(levelshots[u], stripped);
if (COM_FCheckExists(ls))
{
Con_Printf("^[\\map\\%s\\img\\%s\\w\\64\\h\\48^]", stripped, ls);
Con_Printf("^[[%s]%s\\map\\%s\\tipimg\\%s^]\n", stripped, completed, stripped, ls);
Con_Printf("^[\\map\\%s\\img\\%s\\w\\64\\h\\48^]", name, ls);
Con_Printf("^[[%s%s]%s\\map\\%s\\tipimg\\%s^]\n", stripped, ext, completed, name, ls);
return true;
}
}
Con_Printf("^[[%s]%s\\map\\%s^]\n", stripped, completed, stripped);
return true;
}
static int QDECL ShowMapListExt (const char *name, qofs_t flags, time_t mtime, void *parm, searchpathfuncs_t *spath)
{
if (name[5] == 'b' && name[6] == '_') //skip box models
return true;
Con_Printf("^[[%s]\\map\\%s^]\n", name+5, name+5);
Con_Printf("^[[%s%s]%s\\map\\%s^]\n", stripped, ext, completed, name);
return true;
}
static void SV_MapList_f(void)
{
COM_EnumerateFiles("maps/*.bsp", ShowMapList, NULL);
COM_EnumerateFiles("maps/*.bsp.gz", ShowMapListExt, NULL);
COM_EnumerateFiles("maps/*.map", ShowMapListExt, NULL);
COM_EnumerateFiles("maps/*.map.gz", ShowMapListExt, NULL);
COM_EnumerateFiles("maps/*.cm", ShowMapList, NULL);
COM_EnumerateFiles("maps/*.hmp", ShowMapList, NULL);
COM_EnumerateFiles("maps/*.bsp", ShowMapList, "");
COM_EnumerateFiles("maps/*.bsp.gz", ShowMapList, ".bsp.gz");
COM_EnumerateFiles("maps/*.map", ShowMapList, ".map");
COM_EnumerateFiles("maps/*.map.gz", ShowMapList, ".gz");
COM_EnumerateFiles("maps/*.cm", ShowMapList, ".cm");
COM_EnumerateFiles("maps/*.hmp", ShowMapList, ".hmp");
}
static int QDECL CompleteMapList (const char *name, qofs_t flags, time_t mtime, void *parm, searchpathfuncs_t *spath)
@ -547,6 +542,7 @@ void SV_Map_f (void)
#endif
qboolean waschangelevel = false;
qboolean mapeditor = false;
int i;
char *startspot;
@ -619,6 +615,7 @@ void SV_Map_f (void)
newunit = flushparms || (!strcmp(Cmd_Argv(0), "changelevel") && !startspot);
q2savetos0 = !strcmp(Cmd_Argv(0), "gamemap") && !isDedicated; //q2
#endif
mapeditor = !strcmp(Cmd_Argv(0), "mapedit");
sv.mapchangelocked = false;
@ -931,7 +928,7 @@ void SV_Map_f (void)
{
if (waschangelevel && !startspot)
startspot = "";
SV_SpawnServer (level, startspot, false, cinematic, 0);
SV_SpawnServer (level, startspot, mapeditor, cinematic, 0);
}
SCR_SetLoadingFile("server spawned");
@ -3246,6 +3243,7 @@ void SV_InitOperatorCommands (void)
Cmd_AddCommand ("killserver", SV_KillServer_f);
Cmd_AddCommandD ("precaches", SV_PrecacheList_f, "Displays a list of current server precaches.");
Cmd_AddCommandAD ("map", SV_Map_f, SV_Map_c, "Changes map. If a second argument is specified then that is normally the name of the initial start spot.");
Cmd_AddCommandAD ("mapedit", SV_Map_f, SV_Map_c, "Loads the named map without any gamecode active.");
#ifdef Q3SERVER
Cmd_AddCommandAD ("spmap", SV_Map_f, SV_Map_c, NULL);
#endif

View File

@ -120,8 +120,9 @@ extern int sv_nailmodel, sv_supernailmodel, sv_playermodel;
qboolean demonails;
#endif
static edict_t *csqcent[MAX_EDICTS];
static int csqcnuments;
static edict_t **csqcent/*[csqcmaxents]*/;
static size_t csqcmaxents;
static size_t csqcnuments;
qboolean SV_AddNailUpdate (edict_t *ent)
{
@ -263,6 +264,8 @@ static qboolean SV_AddCSQCUpdate (client_t *client, edict_t *ent)
if (!(client->csqcactive))
return false;
if (csqcnuments >= csqcmaxents)
Z_ReallocElements((void**)&csqcent, &csqcmaxents, csqcnuments + 1024, sizeof(*csqcent));
csqcent[csqcnuments++] = ent;
return true;

View File

@ -831,7 +831,7 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
{
extern cvar_t allow_download_refpackages;
func_t f;
const char *file;
const char *file, *csprogsname;
gametype_e newgametype;
@ -1075,8 +1075,12 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
//do we allow csprogs?
#ifdef PEXT_CSQC
fsz = 0;
if (*sv_csqc_progname.string)
file = COM_LoadTempFile(sv_csqc_progname.string, 0, &fsz);
if (noents)
csprogsname = "csaddon.dat";
else
csprogsname = sv_csqc_progname.string;
if (*csprogsname)
file = COM_LoadTempFile(csprogsname, 0, &fsz);
else
file = NULL;
if (file)
@ -1087,8 +1091,8 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
InfoBuf_SetValueForStarKey(&svs.info, "*csprogs", text);
sprintf(text, "0x%x", (unsigned int)fsz);
InfoBuf_SetValueForStarKey(&svs.info, "*csprogssize", text);
if (strcmp(sv_csqc_progname.string, "csprogs.dat"))
InfoBuf_SetValueForStarKey(&svs.info, "*csprogsname", sv_csqc_progname.string);
if (strcmp(csprogsname, "csprogs.dat"))
InfoBuf_SetValueForStarKey(&svs.info, "*csprogsname", csprogsname);
else
InfoBuf_SetValueForStarKey(&svs.info, "*csprogsname", "");
}
@ -1130,35 +1134,35 @@ MSV_OpenUserDatabase();
#endif
newgametype = svs.gametype;
#ifdef HLSERVER
if (SVHL_InitGame())
newgametype = GT_HALFLIFE;
else
#endif
#ifdef Q3SERVER
if (SVQ3_InitGame(false))
newgametype = GT_QUAKE3;
else
#endif
#ifdef Q2SERVER
if ((sv.world.worldmodel->fromgame == fg_quake2 || sv.world.worldmodel->fromgame == fg_quake3) && !*pr_ssqc_progs.string && SVQ2_InitGameProgs()) //these are the rules for running a q2 server
newgametype = GT_QUAKE2; //we loaded the dll
else
#endif
#ifdef VM_LUA
if (PR_LoadLua())
newgametype = GT_LUA;
else
#endif
#ifdef VM_Q1
if (PR_LoadQ1QVM())
newgametype = GT_Q1QVM;
else
#endif
if (noents)
{
newgametype = GT_PROGS; //let's just hope this loads.
Q_InitProgs(usecinematic);
Q_InitProgs(INITPROGS_EDITOR);
}
#ifdef HLSERVER
else if (SVHL_InitGame())
newgametype = GT_HALFLIFE;
#endif
#ifdef Q3SERVER
else if (SVQ3_InitGame(false))
newgametype = GT_QUAKE3;
#endif
#ifdef Q2SERVER
else if ((sv.world.worldmodel->fromgame == fg_quake2 || sv.world.worldmodel->fromgame == fg_quake3) && !*pr_ssqc_progs.string && SVQ2_InitGameProgs()) //these are the rules for running a q2 server
newgametype = GT_QUAKE2; //we loaded the dll
#endif
#ifdef VM_LUA
else if (PR_LoadLua())
newgametype = GT_LUA;
#endif
#ifdef VM_Q1
else if (PR_LoadQ1QVM())
newgametype = GT_Q1QVM;
#endif
else
{
newgametype = GT_PROGS; //let's just hope this loads.
Q_InitProgs(usecinematic?INITPROGS_REQUIRE:INITPROGS_NORMAL);
}
// if ((sv.worldmodel->fromgame == fg_quake2 || sv.worldmodel->fromgame == fg_quake3) && !*progs.string && SVQ2_InitGameProgs()) //full q2 dll decision in one if statement

View File

@ -86,7 +86,7 @@ extern cvar_t password;
#endif
cvar_t spectator_password = CVARF("spectator_password", "", CVAR_NOUNSAFEEXPAND); // password for entering as a sepctator
static cvar_t sv_dlURL = CVARFD(/*ioq3*/"sv_dlURL", "", CVAR_SERVERINFO|CVAR_ARCHIVE, "Provides clients with an external url from which they can obtain pk3s/packages from an external http server instead of having to download over udp.");
cvar_t sv_dlURL = CVARAFD(/*ioq3*/"sv_dlURL", "", /*dp*/"sv_curl_defaulturl", CVAR_SERVERINFO|CVAR_ARCHIVE, "Provides clients with an external url from which they can obtain pk3s/packages from an external http server instead of having to download over udp.");
cvar_t allow_download = CVARAD("allow_download", "1", /*q3*/"sv_allowDownload", "If 1, permits downloading. Set to 0 to unconditionally block *ALL* downloads from this server. You may wish to set sv_dlURL if you wish clients to still be able to download content.");
cvar_t allow_download_skins = CVARD("allow_download_skins", "1", "0 blocks downloading of any file in the skins/ directory");
cvar_t allow_download_models = CVARD("allow_download_models", "1", "0 blocks downloading of any file in the progs/ or models/ directory");
@ -167,7 +167,7 @@ cvar_t sv_masterport = CVAR("sv_masterport", "0");
cvar_t sv_reliable_sound = CVARFD("sv_reliable_sound", "0", 0, "Causes all sounds to be sent reliably, so they will not be missed due to packetloss. However, this will cause them to be delayed somewhat, and slightly bursty. This can be overriden using the 'rsnd' userinfo setting (either forced on or forced off). Note: this does not affect sounds attached to particle effects.");
cvar_t sv_gamespeed = CVARAF("sv_gamespeed", "1", "slowmo", 0);
cvar_t sv_csqcdebug = CVARD("sv_csqcdebug", "0", "Inject packet size information for data directed to csqc.");
cvar_t sv_csqc_progname = CVAR("sv_csqc_progname", "csprogs.dat");
cvar_t sv_csqc_progname = CVARAF("sv_csqc_progname", "csprogs.dat", /*dp*/"csqc_progname", 0);
cvar_t pausable = CVAR("pausable", "");
cvar_t sv_banproxies = CVARD("sv_banproxies", "0", "If enabled, anyone connecting via known proxy software will be refused entry. This should aid with blocking aimbots, but is only reliable for certain public proxies.");
cvar_t sv_specprint = CVARD("sv_specprint", "3", "Bitfield that controls which player events spectators see when tracking that player.\n&1: spectators will see centerprints.\n&2: spectators will see sprints (pickup messages etc).\n&4: spectators will receive console commands, this is potentially risky.\nIndividual spectators can use 'setinfo sp foo' to limit this setting.");
@ -3052,11 +3052,6 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info)
newcl->fteprotocolextensions &= ~PEXT_SPLITSCREEN;
newcl->controller = NULL;
#ifdef PEXT_CSQC
if (sv.csqcchecksum && !(newcl->fteprotocolextensions & PEXT_CSQC) && !ISDPCLIENT(newcl))
SV_PrintToClient(newcl, PRINT_HIGH, "This server is using CSQC - you are missing out due to your choice of outdated client / protocol!\n");
#endif
if (!redirect)
{
Sys_ServerActivity();

View File

@ -712,17 +712,21 @@ void SVNQ_New_f (void)
if (host_client->protocol == SCP_DARKPLACES6 || host_client->protocol == SCP_DARKPLACES7)
{
size_t sz;
char buf[1024];
size_t sz = 0;
char *f;
char *csprogsname = InfoBuf_ValueForKey(&svs.info, "*csprogsname");
if (!*csprogsname && *InfoBuf_ValueForKey(&svs.info, "*csprogs"))
csprogsname = "csprogs.dat";
MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
MSG_WriteString (&host_client->netchan.message, "cl_serverextension_download 1\n");
f = COM_LoadTempFile("csprogs.dat", 0, &sz);
f = *csprogsname?COM_LoadTempFile(csprogsname, 0, &sz):NULL;
if (f)
{
MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
MSG_WriteString (&host_client->netchan.message, va("csqc_progname %s\n", "csprogs.dat"));
MSG_WriteString (&host_client->netchan.message, va("csqc_progname %s\n", COM_QuotedString(csprogsname, buf, sizeof(buf), false)));
MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
MSG_WriteString (&host_client->netchan.message, va("csqc_progsize %u\n", (unsigned int)sz));
MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
@ -731,6 +735,11 @@ void SVNQ_New_f (void)
MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
MSG_WriteString (&host_client->netchan.message, "cmd enablecsqc\n");
}
else
{
MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
MSG_WriteString (&host_client->netchan.message, "csqc_progcrc \"\"\n");
}
}
else if (allow_download.value && (protext1||protext2))
{ //technically this is a DP extension, but is separate from actual protocols and shouldn't harm anything.
@ -1037,6 +1046,11 @@ void SV_SendClientPrespawnInfo(client_t *client)
{
char buffer[1024];
#ifdef PEXT_CSQC
if (sv.csqcchecksum && !(client->fteprotocolextensions & PEXT_CSQC) && !ISDPCLIENT(client))
SV_PrintToClient(client, PRINT_HIGH, "This server is using CSQC - you are missing out due to your choice of outdated client / protocol!\n");
#endif
while (client->netchan.message.cursize < maxsize)
{
if (client->prespawn_idx == 0)
@ -3013,6 +3027,58 @@ void SV_Voice_UnmuteAll_f(void)
}
#endif
qboolean SV_FindRemotePackage(const char *package, char *url, size_t urlsize)
{
//FIXME: interrogate the package manager first? it probably doesn't have source urls though. I guess that should be done clientside.
//basedir/gamedir/curl_urls.txt contains something like:
//maps_*.pk3 https://host/maps/
//* https://host/gamedir/
//or something.
extern cvar_t sv_dlURL;
vfsfile_t *f;
char line[512];
//filter out the gamedir, so different gamedirs can have different sets of urls.
//(useful for eg pakN.pak, if it were not blocked elsewhere)
char *sep = strchr(package, '/');
if (!sep || sep-package>=strlen(line))
return false;
memcpy(line, package, sep-package+1);
line[sep-package+1] = 0;
package = sep+1;
Q_strncatz(line, "curl_urls.txt", sizeof(line));
f = FS_OpenVFS(line, "rb", FS_ROOT); //this is for server admins to deal with. urls are too unreliable for paks.
if (f)
{
char pattern[256];
char *e;
while (VFS_GETS(f, line, sizeof(line)))
{
e = COM_ParseOut(line, pattern, sizeof(pattern));
if (*pattern && wildcmp(pattern, package))
{
COM_ParseOut(e, url, urlsize);
Q_strncatz(url, package, urlsize);
VFS_CLOSE(f);
return true;
}
}
VFS_CLOSE(f);
}
if (*sv_dlURL.string)
{ //a fallback, though the above mechanism allows for a wildcard for all.
Q_strncatz(sv_dlURL.string, package, urlsize);
Q_strncatz(url, package, urlsize);
return true;
}
return false;
}
//Use of this function is on name only.
//Be aware that the maps directory should be restricted based on weather the file was from a pack file
//this is to preserve copyright - please do not breach due to a bug.
@ -3204,7 +3270,14 @@ static int SV_LocateDownload(const char *name, flocation_t *loc, char **replacem
if (!Q_strncasecmp(name, "package/", 8))
{
vfsfile_t *f = FS_OpenVFS(name+8, "rb", FS_ROOT);
vfsfile_t *f;
if (redirectpaks && SV_FindRemotePackage(name+8, tmpname, sizeof(tmpname)))
{
*replacementname = tmpname;
return DLERR_REDIRECTFILE;
}
f = FS_OpenVFS(name+8, "rb", FS_ROOT);
if (f)
{
loc->len = VFS_GETLEN(f);
@ -6949,7 +7022,7 @@ size_t playertouchmax;
void SV_PreRunCmd(void)
{
size_t max = MAX_EDICTS;//(sv.world.num_edicts+7)&~7;
size_t max = (sv.world.num_edicts+512+7)&~7;
if (max > playertouchmax)
{
playertouchmax = max;
@ -7534,7 +7607,7 @@ if (sv_player->v->health > 0 && before && !after )
n = pmove.physents[pmove.touchindex[i]].info;
ent = EDICT_NUM_PB(svprogfuncs, n);
if (n >= playertouchmax || playertouch[n>>3]&(1<<(n&7)))
if (n >= playertouchmax || (playertouch[n>>3]&(1<<(n&7))))
continue;
playertouch[n>>3] |= 1 << (n&7);

View File

@ -4708,7 +4708,7 @@ static void VKBE_RT_Purge(void *ptr)
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)
void VKBE_RT_Gen(struct vk_rendertarg *targ, vk_image_t *colour, uint32_t width, uint32_t height, qboolean clear, unsigned int flags)
{
//sooooo much work...
VkImageCreateInfo colour_imginfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
@ -4717,16 +4717,27 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
struct vkbe_rtpurge *purge;
static VkClearValue clearvalues[3];
if (colour)
{ //override the width+height if we already have an image to draw to.
width = colour->width;
height = colour->height;
}
targ->restartinfo.clearValueCount = 3;
targ->depthcleared = true; //will be once its activated.
if (targ->width == width && targ->height == height && targ->q_colour.flags == flags && (!(targ->rpassflags&RP_MULTISAMPLE))==(targ->mscolour.image==VK_NULL_HANDLE))
{
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 ((colour && colour->image == targ->colour.image) || (!colour && !targ->externalimage))
{
if (width == 0 || height == 0)
targ->restartinfo.renderPass = VK_NULL_HANDLE; //illegal combination used for destruction.
else 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)
@ -4734,6 +4745,8 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
purge = VK_AtFrameEnd(VKBE_RT_Purge, NULL, sizeof(*purge));
purge->framebuffer = targ->framebuffer;
purge->colour = targ->colour;
if (targ->externalimage)
purge->colour.image = VK_NULL_HANDLE;
purge->mscolour = targ->mscolour;
purge->depth = targ->depth;
memset(&targ->colour, 0, sizeof(targ->colour));
@ -4742,6 +4755,7 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
targ->framebuffer = VK_NULL_HANDLE;
}
targ->externalimage = !!colour;
targ->q_colour.vkimage = &targ->colour;
targ->q_depth.vkimage = &targ->depth;
targ->q_colour.status = TEX_LOADED;
@ -4775,7 +4789,10 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
colour_imginfo.queueFamilyIndexCount = 0;
colour_imginfo.pQueueFamilyIndices = NULL;
colour_imginfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VkAssert(vkCreateImage(vk.device, &colour_imginfo, vkallocationcb, &targ->colour.image));
if (targ->externalimage)
targ->colour.image = colour->image;
else
VkAssert(vkCreateImage(vk.device, &colour_imginfo, vkallocationcb, &targ->colour.image));
depth_imginfo = colour_imginfo;
depth_imginfo.format = vk.depthformat;
@ -4789,7 +4806,10 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
}
VkAssert(vkCreateImage(vk.device, &depth_imginfo, vkallocationcb, &targ->depth.image));
VK_AllocateBindImageMemory(&targ->colour, true);
if (targ->externalimage) //an external image is assumed to already have memory bound. don't allocate it elsewhere.
memset(&targ->colour.mem, 0, sizeof(targ->colour.mem));
else
VK_AllocateBindImageMemory(&targ->colour, true);
VK_AllocateBindImageMemory(&targ->depth, true);
{
@ -4907,6 +4927,9 @@ void VKBE_RT_Gen_Cube(struct vk_rendertarg_cube *targ, uint32_t size, qboolean c
uint32_t f;
static VkClearValue clearvalues[2];
if (targ->size == size && !clear)
return; //no work to do.
for (f = 0; f < 6; f++)
{
if (clear)
@ -5195,7 +5218,7 @@ static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
r_refdef.vrect.y = 0;
r_refdef.vrect.width = max(1, vid.fbvwidth*bs->portalfboscale);
r_refdef.vrect.height = max(1, vid.fbvheight*bs->portalfboscale);
VKBE_RT_Gen(&shaderstate.rt_reflection, r_refdef.vrect.width, r_refdef.vrect.height, false, RT_IMAGEFLAGS);
VKBE_RT_Gen(&shaderstate.rt_reflection, NULL, r_refdef.vrect.width, r_refdef.vrect.height, false, RT_IMAGEFLAGS);
VKBE_RT_Begin(&shaderstate.rt_reflection);
R_DrawPortal(batch, cl.worldmodel->batches, NULL, 1);
VKBE_RT_End(&shaderstate.rt_reflection);
@ -5214,7 +5237,7 @@ static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
r_refdef.vrect.y = 0;
r_refdef.vrect.width = vid.fbvwidth/2;
r_refdef.vrect.height = vid.fbvheight/2;
VKBE_RT_Gen(&shaderstate.rt_refraction, r_refdef.vrect.width, r_refdef.vrect.height, false, RT_IMAGEFLAGS);
VKBE_RT_Gen(&shaderstate.rt_refraction, NULL, r_refdef.vrect.width, r_refdef.vrect.height, false, RT_IMAGEFLAGS);
VKBE_RT_Begin(&shaderstate.rt_refraction);
R_DrawPortal(batch, cl.worldmodel->batches, NULL, ((bs->flags & SHADER_HASREFRACTDEPTH)?3:2)); //fixme
VKBE_RT_End(&shaderstate.rt_refraction);

View File

@ -5,6 +5,8 @@
#include "shader.h"
#include "renderque.h" //is anything still using this?
#include "vr.h"
extern qboolean vid_isfullscreen;
cvar_t vk_stagingbuffers = CVARFD ("vk_stagingbuffers", "", CVAR_RENDERERLATCH, "Configures which dynamic buffers are copied into gpu memory for rendering, instead of reading from shared memory. Empty for default settings.\nAccepted chars are u(niform), e(lements), v(ertex), 0(none).");
@ -2217,7 +2219,7 @@ static void VK_Shutdown_PostProc(void)
if (vk.device)
{
for (i = 0; i < countof(postproc); i++)
VKBE_RT_Gen(&postproc[i], 0, 0, true, RT_IMAGEFLAGS);
VKBE_RT_Gen(&postproc[i], NULL, 0, 0, true, RT_IMAGEFLAGS);
VK_R_BloomShutdown();
}
@ -2622,6 +2624,52 @@ static qboolean VK_R_RenderScene_Cubemap(struct vk_rendertarg *fb)
return true;
}
void VK_R_RenderEye(texid_t image, vec4_t fovoverride, vec3_t axisorg[4])
{
struct vk_rendertarg *rt;
VK_SetupViewPortProjection(false);
rt = &postproc[postproc_buf++%countof(postproc)];
VKBE_RT_Gen(rt, image?image->vkimage:NULL, 320, 200, false, RT_IMAGEFLAGS);
VKBE_RT_Begin(rt);
if (!vk.rendertarg->depthcleared)
{
VkClearAttachment clr;
VkClearRect rect;
clr.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
clr.clearValue.depthStencil.depth = 1;
clr.clearValue.depthStencil.stencil = 0;
clr.colorAttachment = 1;
rect.rect.offset.x = r_refdef.pxrect.x;
rect.rect.offset.y = r_refdef.pxrect.y;
rect.rect.extent.width = r_refdef.pxrect.width;
rect.rect.extent.height = r_refdef.pxrect.height;
rect.layerCount = 1;
rect.baseArrayLayer = 0;
vkCmdClearAttachments(vk.rendertarg->cbuf, 1, &clr, 1, &rect);
vk.rendertarg->depthcleared = true;
}
VKBE_SelectEntity(&r_worldentity);
R_SetFrustum (r_refdef.m_projection_std, r_refdef.m_view);
RQ_BeginFrame();
if (!(r_refdef.flags & RDF_NOWORLDMODEL))
{
if (cl.worldmodel)
P_DrawParticles ();
}
Surf_DrawWorld();
RQ_RenderBatchClear();
vk.rendertarg->depthcleared = false;
VKBE_RT_End(rt);
}
void VK_R_RenderView (void)
{
extern unsigned int r_viewcontents;
@ -2641,6 +2689,12 @@ void VK_R_RenderView (void)
Surf_SetupFrame();
if (vid.vr && vid.vr->Render(VK_R_RenderEye))
{
VK_Set2D ();
return;
}
//check if we can do underwater warp
if (cls.protocol != CP_QUAKE2) //quake2 tells us directly
{
@ -2743,7 +2797,7 @@ void VK_R_RenderView (void)
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);
VKBE_RT_Gen(rt, NULL, r_refdef.pxrect.width, r_refdef.pxrect.height, false, (r_renderscale.value < 0)?RT_IMAGEFLAGS-IF_LINEAR+IF_NEAREST:RT_IMAGEFLAGS);
}
else
rt = rtscreen;
@ -2838,7 +2892,7 @@ void VK_R_RenderView (void)
{
rt = &postproc[postproc_buf++];
rt->rpassflags = 0;
VKBE_RT_Gen(rt, 320, 200, false, RT_IMAGEFLAGS);
VKBE_RT_Gen(rt, NULL, 320, 200, false, RT_IMAGEFLAGS);
}
else
rt = rtscreen;
@ -2860,7 +2914,7 @@ void VK_R_RenderView (void)
{
rt = &postproc[postproc_buf++];
rt->rpassflags = 0;
VKBE_RT_Gen(rt, 320, 200, false, RT_IMAGEFLAGS);
VKBE_RT_Gen(rt, NULL, 320, 200, false, RT_IMAGEFLAGS);
}
else
rt = rtscreen;
@ -2879,7 +2933,7 @@ void VK_R_RenderView (void)
{
rt = &postproc[postproc_buf++];
rt->rpassflags = 0;
VKBE_RT_Gen(rt, 320, 200, false, RT_IMAGEFLAGS);
VKBE_RT_Gen(rt, NULL, 320, 200, false, RT_IMAGEFLAGS);
}
else
rt = rtscreen;
@ -2899,7 +2953,7 @@ void VK_R_RenderView (void)
{
rt = &postproc[postproc_buf++];
rt->rpassflags = 0;
VKBE_RT_Gen(rt, 320, 200, false, RT_IMAGEFLAGS);
VKBE_RT_Gen(rt, NULL, 320, 200, false, RT_IMAGEFLAGS);
}
else
rt = rtscreen;
@ -4274,6 +4328,47 @@ void VK_CheckTextureFormats(void)
sh_config.hw_astc = 2; //the core vulkan formats refer to the ldr profile. hdr is a separate extension, which is still not properly specified..
}
//creates a vulkan instance with the additional extensions, and hands a copy of the instance to the caller.
qboolean VK_CreateInstance(vrsetup_t *info, char *vrexts, void *result)
{
VkInstanceCreateInfo inst_info = *(VkInstanceCreateInfo*)info->userctx;
VkResult err;
const char *ext[64];
unsigned int numext = inst_info.enabledExtensionCount;
memcpy(ext, inst_info.ppEnabledExtensionNames, numext*sizeof(*ext));
while (vrexts && numext < countof(ext))
{
ext[numext++] = vrexts;
vrexts = strchr(vrexts, ' ');
if (!vrexts)
break;
*vrexts++ = 0;
}
err = vkCreateInstance(&inst_info, vkallocationcb, &vk.instance);
switch(err)
{
case VK_ERROR_INCOMPATIBLE_DRIVER:
Con_Printf("VK_ERROR_INCOMPATIBLE_DRIVER: please install an appropriate vulkan driver\n");
return false;
case VK_ERROR_EXTENSION_NOT_PRESENT:
Con_Printf("VK_ERROR_EXTENSION_NOT_PRESENT: something on a system level is probably misconfigured\n");
return false;
case VK_ERROR_LAYER_NOT_PRESENT:
Con_Printf("VK_ERROR_LAYER_NOT_PRESENT: requested layer is not known/usable\n");
return false;
default:
Con_Printf("Unknown vulkan instance creation error: %x\n", err);
return false;
case VK_SUCCESS:
break;
}
if (result)
*(VkInstance*)result = vk.instance;
return true;
}
//initialise the vulkan instance, context, device, etc.
qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*createSurface)(void), void (*dopresent)(struct vkframe *theframe))
{
@ -4285,6 +4380,9 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
const char *extensions[8];
uint32_t extensions_count = 0;
qboolean okay;
vrsetup_t vrsetup = {sizeof(vrsetup)};
//device extensions that want to enable
//initialised in reverse order, so superseeded should name later extensions.
struct
@ -4312,9 +4410,6 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
for (e = 0; e < countof(knowndevexts); e++)
*knowndevexts[e].flag = false;
#ifdef MULTITHREAD
vk.allowsubmissionthread = true;
#endif
vk.neednewswapchain = true;
vk.triplebuffer = info->triplebuffer;
vk.vsync = info->wait;
@ -4326,7 +4421,7 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
#ifdef VK_NO_PROTOTYPES
if (!vkGetInstanceProcAddr)
{
Con_Printf("vkGetInstanceProcAddr is null\n");
Con_Printf(CON_ERROR"vkGetInstanceProcAddr is null\n");
return false;
}
#define VKFunc(n) vk##n = (PFN_vk##n)vkGetInstanceProcAddr(VK_NULL_HANDLE, "vk"#n);
@ -4395,7 +4490,7 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
if (sysextnames && (!vk.khr_swapchain || !surfext))
{
Con_Printf("Vulkan instance lacks driver support for %s\n", sysextnames[0]);
Con_Printf(CON_ERROR"Vulkan instance lacks driver support for %s\n", sysextnames[0]);
return false;
}
}
@ -4418,24 +4513,33 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
inst_info.enabledExtensionCount = extensions_count;
inst_info.ppEnabledExtensionNames = extensions;
err = vkCreateInstance(&inst_info, vkallocationcb, &vk.instance);
switch(err)
vrsetup.vrplatform = VR_VULKAN;
vrsetup.userctx = &inst_info;
vrsetup.createinstance = VK_CreateInstance;
if (info->vr)
{
case VK_ERROR_INCOMPATIBLE_DRIVER:
Con_Printf("VK_ERROR_INCOMPATIBLE_DRIVER: please install an appropriate vulkan driver\n");
return false;
case VK_ERROR_EXTENSION_NOT_PRESENT:
Con_Printf("VK_ERROR_EXTENSION_NOT_PRESENT: something on a system level is probably misconfigured\n");
return false;
case VK_ERROR_LAYER_NOT_PRESENT:
Con_Printf("VK_ERROR_LAYER_NOT_PRESENT: requested layer is not known/usable\n");
return false;
default:
Con_Printf("Unknown vulkan instance creation error: %x\n", err);
return false;
case VK_SUCCESS:
break;
okay = info->vr->Prepare(&vrsetup);
if (!okay)
{
info->vr->Shutdown();
info->vr = NULL;
}
}
else
okay = false;
if (!okay)
okay = vrsetup.createinstance(&vrsetup, NULL, NULL);
if (!okay)
{
if (info->vr)
info->vr->Shutdown();
return false;
}
vid.vr = info->vr;
#ifdef MULTITHREAD
vk.allowsubmissionthread = !vid.vr;
#endif
//third set of functions...
#ifdef VK_NO_PROTOTYPES
@ -4510,7 +4614,7 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
vkEnumeratePhysicalDevices(vk.instance, &gpucount, NULL);
if (!gpucount)
{
Con_Printf("vulkan: no devices known!\n");
Con_Printf(CON_ERROR"vulkan: no devices known!\n");
return false;
}
devs = malloc(sizeof(VkPhysicalDevice)*gpucount);
@ -4564,7 +4668,12 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
pri = 4;
break;
}
if (wantdev >= 0)
if (vrsetup.vk.physicaldevice != VK_NULL_HANDLE)
{ //if we're using vr, use the gpu our vr context requires.
if (devs[i] == vrsetup.vk.physicaldevice)
pri = 0;
}
else if (wantdev >= 0)
{
if (wantdev == i)
pri = 0;
@ -4586,7 +4695,7 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
if (!vk.gpu)
{
Con_Printf("vulkan: unable to pick a usable device\n");
Con_Printf(CON_ERROR"vulkan: unable to pick a usable device\n");
return false;
}
}
@ -4708,7 +4817,7 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
if (vk.queuefam[0] == ~0u || vk.queuefam[1] == ~0u)
{
free(queueprops);
Con_Printf("unable to find suitable queues\n");
Con_Printf(CON_ERROR"vulkan: unable to find suitable queues\n");
return false;
}
}
@ -4859,7 +4968,7 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
switch(err)
{
case VK_ERROR_INCOMPATIBLE_DRIVER:
Con_Printf("VK_ERROR_INCOMPATIBLE_DRIVER: please install an appropriate vulkan driver\n");
Con_Printf(CON_ERROR"VK_ERROR_INCOMPATIBLE_DRIVER: please install an appropriate vulkan driver\n");
return false;
case VK_ERROR_EXTENSION_NOT_PRESENT:
case VK_ERROR_FEATURE_NOT_PRESENT:
@ -4867,10 +4976,10 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
case VK_ERROR_DEVICE_LOST:
case VK_ERROR_OUT_OF_HOST_MEMORY:
case VK_ERROR_OUT_OF_DEVICE_MEMORY:
Con_Printf("%s: something on a system level is probably misconfigured\n", VK_VKErrorToString(err));
Con_Printf(CON_ERROR"%s: something on a system level is probably misconfigured\n", VK_VKErrorToString(err));
return false;
default:
Con_Printf("Unknown vulkan device creation error: %x\n", err);
Con_Printf(CON_ERROR"Unknown vulkan device creation error: %x\n", err);
return false;
case VK_SUCCESS:
break;
@ -4887,6 +4996,19 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
vkGetDeviceQueue(vk.device, vk.queuefam[0], vk.queuenum[0], &vk.queue_render);
vkGetDeviceQueue(vk.device, vk.queuefam[1], vk.queuenum[1], &vk.queue_present);
vrsetup.vk.instance = vk.instance;
vrsetup.vk.device = vk.device;
vrsetup.vk.physicaldevice = vk.gpu;
vrsetup.vk.queuefamily = vk.queuefam[1];
vrsetup.vk.queueindex = vk.queuenum[1];
if (vid.vr)
{
if (!vid.vr->Init(&vrsetup, info))
{
vid.vr->Shutdown();
vid.vr = NULL;
}
}
vkGetPhysicalDeviceMemoryProperties(vk.gpu, &vk.memory_properties);
@ -4980,7 +5102,7 @@ void VK_Shutdown(void)
VK_DestroySwapChain();
for (i = 0; i < countof(postproc); i++)
VKBE_RT_Gen(&postproc[i], 0, 0, false, RT_IMAGEFLAGS);
VKBE_RT_Gen(&postproc[i], NULL, 0, 0, false, RT_IMAGEFLAGS);
VKBE_RT_Gen_Cube(&vk_rt_cubemap, 0, false);
VK_R_BloomShutdown();

View File

@ -236,7 +236,6 @@ enum dynbuf_e
};
struct vk_rendertarg
{
VkCommandBuffer cbuf; //cbuf allocated for this render target.
VkFramebuffer framebuffer;
vk_image_t colour, depth, mscolour;
@ -252,6 +251,7 @@ struct vk_rendertarg
VkRenderPassBeginInfo restartinfo;
VkSemaphore presentsemaphore;
qboolean firstuse;
qboolean externalimage;
struct vk_rendertarg *prevtarg;
};
@ -483,7 +483,7 @@ void VKBE_BeginShadowmapFace(void);
void VKBE_DoneShadows(void);
void VKBE_RT_Gen_Cube(struct vk_rendertarg_cube *targ, uint32_t size, qboolean clear);
void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qboolean clear, unsigned int flags);
void VKBE_RT_Gen(struct vk_rendertarg *targ, vk_image_t *colour, uint32_t width, uint32_t height, qboolean clear, unsigned int flags);
void VKBE_RT_Begin(struct vk_rendertarg *targ);
void VKBE_RT_End(struct vk_rendertarg *targ);
void VKBE_RT_Destroy(struct vk_rendertarg *targ);

View File

@ -103,6 +103,7 @@ clean: ezscript-clean qi-clean hud-clean irc-clean
help:
@-echo make a subdirectory
######################################
#small script to download+install avformat for windows cross compiles.
#linux users are expected to have the library installed locally already. If your version is too old or missing, run the following command to install it (to /usr/local), then delete the gz and directory.
#wget http://ffmpeg.org/releases/ffmpeg-1.2.tar.gz && cd tar xvfz ffmpeg-1.2.tar.gz && cd ffmpeg-1.2/ && ./configure --disable-yasm --enable-shared && make && sudo make install
@ -189,7 +190,9 @@ $(PLUG_PREFIX)ffmpeg$(PLUG_NATIVE_EXT): $(AV_DEP) $(FFMPEG_ZIP)
$(PLUG_PREFIX)ffmpeg$(PLUG_NATIVE_EXT): $(AVPLUG_OBJS)
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -s -o $@ -shared $(PLUG_CFLAGS) $(AV_CFLAGS) $(AVPLUG_OBJS) $(PLUG_DEFFILE) $(PLUG_LDFLAGS) $(AV_LDFLAGS)
######################################
######################################
#small script for ode
#FIXME: ode fails to compile under cygwin
#FIXME: race condition if you try compiling debug+release at the same time, as this makefile is invoked twice by the engine's one
@ -212,7 +215,9 @@ ODE_FILES=../engine/common/com_phys_ode.c ../engine/common/mathlib.c plugin.c $(
$(PLUG_PREFIX)ode$(PLUG_NATIVE_EXT): $(ODE_FILES)
$(CC) -flto -s $(BASE_CFLAGS) $(CFLAGS) -Os -DFTEPLUGIN -DODE_STATIC -o $@ -shared $(PLUG_CFLAGS) -I$(ODE_BASE)ode-$(ODE_VER)/include $(ODE_FILES) $(PLUG_DEFFILE) $(PLUG_LDFLAGS) -static-libgcc `$(CC) -print-file-name=libstdc++.a` -lpthread
#NATIVE_PLUGINS+=ode
######################################
######################################
ifneq ($(CMAKERULES),)
BULLET_CFLAGS+=-static-libstdc++
PLUG_CMAKE+= -DCMAKE_TOOLCHAIN_FILE="$(CMAKERULES)"
@ -255,23 +260,9 @@ $(BULLET_LIB): $(OUT_DIR)/../bullet3-$(BULLET_VER).tar.gz $(CMAKERULES)
$(PLUG_PREFIX)bullet$(PLUG_NATIVE_EXT): bullet/bulletplug.cpp plugin.c $(BULLET_LIBS)
$(CXX) $(BASE_CXXFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS) $(BULLET_CFLAGS)
#NATIVE_PLUGINS+=bullet
######################################
-include Makefile.private
$(PLUG_PREFIX)mpq$(PLUG_NATIVE_EXT): mpq/fs_mpq.c mpq/blast.c plugin.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Impq $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS_ZLIB) $(PLUG_LDFLAGS)
NATIVE_PLUGINS+=mpq
$(PLUG_PREFIX)xmpp$(PLUG_NATIVE_EXT): jabber/jabberclient.c jabber/jingle.c jabber/sift.c jabber/xml.c plugin.c ../engine/common/sha1.c emailnot/md5.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Ijabber $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS) $(LIBRESOLV)
NATIVE_PLUGINS+=xmpp
$(PLUG_PREFIX)qi$(PLUG_NATIVE_EXT): qi/qi.c jabber/xml.c plugin.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Ijabber $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
NATIVE_PLUGINS+=qi
######################################
#Regarding CEF Versions: Cef 2526 is reportedly the most recent _WORKING_ version of libcef. Later versions have screwed webgl etc, and are just generally unstable.
#However, that's now impossible to get hold of since the old cefbuilds server went down. New builds are hosted by spotify and they're all randomly broken, so we might as well just use whatever seems fairly recent.
@ -314,18 +305,49 @@ else
$(PLUG_PREFIX)cef$(PLUG_NATIVE_EXT):
echo cef plugin not supported on this arch
endif
######################################
#for custom/private plugins...
-include Makefile.private
#small plugins with simpler build rules...
$(PLUG_PREFIX)mpq$(PLUG_NATIVE_EXT): mpq/fs_mpq.c mpq/blast.c plugin.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Impq $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS_ZLIB) $(PLUG_LDFLAGS)
NATIVE_PLUGINS+=mpq
$(PLUG_PREFIX)xmpp$(PLUG_NATIVE_EXT): jabber/jabberclient.c jabber/jingle.c jabber/sift.c jabber/xml.c plugin.c ../engine/common/sha1.c emailnot/md5.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Ijabber $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS) $(LIBRESOLV)
NATIVE_PLUGINS+=xmpp
$(PLUG_PREFIX)qi$(PLUG_NATIVE_EXT): qi/qi.c jabber/xml.c plugin.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Ijabber $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
NATIVE_PLUGINS+=qi
$(PLUG_PREFIX)irc$(PLUG_NATIVE_EXT): irc/ircclient.c plugin.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Iirc $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
NATIVE_PLUGINS+=irc
#OpenXR plugin...
$(PLUG_PREFIX)openxr$(PLUG_NATIVE_EXT): openxr.c plugin.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS) -DXR_NO_PROTOTYPES `pkg-config --cflags openxr` -DGLQUAKE -DVKQUAKE -DD3D11QUAKE
#ifeq ($(shell pkg-config --exists openxr && echo 1),1)
#NATIVE_PLUGINS+=openxr
#endif
#for compat with ezquake
$(PLUG_PREFIX)ezhud$(PLUG_NATIVE_EXT): ezhud/ezquakeisms.c ezhud/hud.c ezhud/hud_common.c ezhud/hud_editor.c plugin.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Iezhud $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
NATIVE_PLUGINS+=ezhud
#not really relevant now that gltf was made an internal plugin
$(PLUG_PREFIX)models$(PLUG_NATIVE_EXT): models/gltf.c models/exportiqm.c models/models.c plugin.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Imodels $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
NATIVE_PLUGINS+=models
#NATIVE_PLUGINS+=models
all: $(foreach FOO,$(NATIVE_PLUGINS), $(PLUG_PREFIX)$(FOO)$(PLUG_NATIVE_EXT))

View File

@ -2,18 +2,41 @@
#include "../plugin.h"
#include "../engine.h"
static plugfsfuncs_t *fsfuncs;
static plugsubconsolefuncs_t *confuncs;
static plugclientfuncs_t *clientfuncs;
#pragma GCC diagnostic ignored "-Wstrict-prototypes" //not my bug.
//libcef defs
#include "include/cef_version.h"
#include "include/capi/cef_app_capi.h"
#include "include/capi/cef_client_capi.h"
#include "include/capi/cef_parser_capi.h"
#include "include/capi/cef_request_context_handler_capi.h"
//#include "include/capi/cef_url_capi.h"
#include "assert.h"
#if defined(_DEBUG) && defined(_MSC_VER)
#include <crtdbg.h>
#endif
#ifndef _WIN32
#include <unistd.h>
#include <sys/stat.h>
#endif
#define EXPECTED_COMMIT_NUMBER 2179 //last version of libcef we tried building against...
#if EXPECTED_COMMIT_NUMBER != EXPECTED_COMMIT_NUMBER
#warning "libcef version different from expected. expect problems with libcef's unstable API."
#endif
#define cef_addref(ptr) (ptr)->base.add_ref(&(ptr)->base)
#define cef_release(ptr) (((ptr)->base.release)(&(ptr)->base))
#ifndef LIBCEF_STATIC
#define LIBCEF_DYNAMIC
#endif
#ifdef LIBCEF_DYNAMIC
//avoid conflicts with cef headers
#define cef_api_hash pcef_api_hash
#define cef_version_info pcef_version_info
#define cef_initialize pcef_initialize
#define cef_do_message_loop_work pcef_do_message_loop_work
@ -44,17 +67,12 @@
#define cef_string_list_size pcef_string_list_size
#define cef_string_list_value pcef_string_list_value
#define cef_addref(ptr) (ptr)->base.add_ref(&(ptr)->base)
#define cef_release(ptr) (((ptr)->base.release)(&(ptr)->base))
static const char* (*cef_api_hash)(int entry);
static int (*cef_version_info)(int entry);
static int (*cef_initialize)(const struct _cef_main_args_t* args, const cef_settings_t* settings, cef_app_t* application, void* windows_sandbox_info);
static void (*cef_do_message_loop_work)(void);
static void (*cef_shutdown)(void);
static int (*cef_execute_process)(const cef_main_args_t* args, cef_app_t* application, void* windows_sandbox_info);
static cef_browser_t* (*cef_browser_host_create_browser_sync)(const cef_window_info_t* windowInfo, cef_client_t* client, const cef_string_t* url, const cef_browser_settings_t* settings, cef_request_context_t* request_context);
static cef_browser_t* (*cef_browser_host_create_browser_sync)(const cef_window_info_t* windowInfo, cef_client_t* client, const cef_string_t* url, const cef_browser_settings_t* settings, cef_dictionary_value_t* extra_info, cef_request_context_t* request_context);
static int (*cef_string_utf8_to_utf16)(const char* src, size_t src_len, cef_string_utf16_t* output);
static int (*cef_string_utf16_to_utf8)(const char16* src, size_t src_len, cef_string_utf8_t* output);
static void (*cef_string_utf16_clear)(cef_string_utf16_t* str);
@ -79,16 +97,6 @@ static void (*cef_string_multimap_free)(cef_string_multimap_t map);
static size_t (*cef_string_list_size)(cef_string_list_t list);
static int (*cef_string_list_value)(cef_string_list_t list, size_t index, cef_string_t* value);
#ifndef CEF_VERSION //old builds lack this
#define CEF_VERSION "cef"STRINGIFY(CEF_VERSION_MAJOR)"."STRINGIFY(CEF_REVISION)"."STRINGIFY(CHROME_VERSION_BUILD)
#endif
#ifndef CEF_COMMIT_NUMBER
#define CEF_COMMIT_NUMBER CEF_REVISION
#endif
#ifdef _WIN32
//we can't use pSys_LoadLibrary, because plugin builtins do not work unless the engine's plugin system is fully initialised, which doesn't happen in the 'light weight' sub processes, so we'll just roll our own (consistent) version.
dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs)
@ -169,16 +177,13 @@ dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs)
return (dllhandle_t*)lib;
}
#endif
#endif
#define Cvar_Register(v) ((v)->handle = pCvar_Register((v)->name, (v)->string, (v)->flags, (v)->group))
#define Cvar_Update(v) ((v)->modificationcount = pCvar_Update((v)->handle, &(v)->modificationcount, (v)->string, &(v)->value))
vmcvar_t cef_incognito = {"cef_incognito", "0", "browser settings", 0};
vmcvar_t cef_allowplugins = {"cef_allowplugins", "0", "browser settings", 0};
vmcvar_t cef_allowcvars = {"cef_allowcvars", "0", "browser settings", 0};
vmcvar_t cef_devtools = {"cef_devtools", "0", "browser settings", 0};
static cvar_t *cef_incognito;
static cvar_t *cef_allowplugins;
static cvar_t *cef_allowcvars;
static cvar_t *cef_devtools;
static char plugname[MAX_OSPATH];
static char *newconsole;
@ -317,14 +322,10 @@ static int browser_release(browser_t *br)
return false;
}
#if CEF_COMMIT_NUMBER >= 1658 //not sure what number it is.
#define cef_base_t cef_base_ref_counted_t
#endif
#define browser_subs(sub) \
static void CEF_CALLBACK browser_##sub##_addref(cef_base_t* self) {browser_t *br = (browser_t*)((char*)self - offsetof(browser_t, sub.base)); browser_addref(br);}; \
static int CEF_CALLBACK browser_##sub##_release(cef_base_t* self) {browser_t *br = (browser_t*)((char*)self - offsetof(browser_t, sub.base)); return browser_release(br);}; \
static int CEF_CALLBACK browser_##sub##_hasoneref(cef_base_t* self) {browser_t *br = (browser_t*)((char*)self - offsetof(browser_t, sub.base)); return br->refcount == 1;};
static void CEF_CALLBACK browser_##sub##_addref(cef_base_ref_counted_t* self) {browser_t *br = (browser_t*)((char*)self - offsetof(browser_t, sub.base)); browser_addref(br);}; \
static int CEF_CALLBACK browser_##sub##_release(cef_base_ref_counted_t* self) {browser_t *br = (browser_t*)((char*)self - offsetof(browser_t, sub.base)); return browser_release(br);}; \
static int CEF_CALLBACK browser_##sub##_hasoneref(cef_base_ref_counted_t* self) {browser_t *br = (browser_t*)((char*)self - offsetof(browser_t, sub.base)); return br->refcount == 1;};
browser_subs(client);
browser_subs(render_handler);
browser_subs(display_handler);
@ -371,8 +372,7 @@ static qboolean browser_handle_query(const char *req, char *buffer, size_t buffe
return false;
else if (!strncmp(req, "getcvar_", 8))
{
Cvar_Update(&cef_allowcvars);
if (cef_allowcvars.value && pCvar_GetString(req+8, buffer, buffersize))
if (cef_allowcvars->value && cvarfuncs->GetString(req+8, buffer, buffersize))
return true;
}
else if (!strncmp(req, "setcvar_", 8))
@ -383,10 +383,9 @@ static qboolean browser_handle_query(const char *req, char *buffer, size_t buffe
else
eq = req+strlen(req);
Cvar_Update(&cef_allowcvars);
if (cef_allowcvars.value)
if (cef_allowcvars->value)
{
pCvar_SetString(req+8, eq);
cvarfuncs->SetString(req+8, eq);
*buffer = 0;
return true;
}
@ -396,7 +395,7 @@ static qboolean browser_handle_query(const char *req, char *buffer, size_t buffe
//FIXME: should be more than just a one-off.
unsigned int stats[256], i, m;
char *e = buffer;
m = pCL_GetStats(0, stats, countof(stats));
m = clientfuncs->GetStats(0, stats, countof(stats));
if (!m)
{
m = 0;
@ -423,7 +422,7 @@ static qboolean browser_handle_query(const char *req, char *buffer, size_t buffe
char *e = buffer;
int players[MAX_SPLITS];
int tracks[MAX_SPLITS];
int seats = pGetLocalPlayerNumbers(0, MAX_SPLITS, players, tracks);
int seats = clientfuncs->GetLocalPlayerNumbers(0, MAX_SPLITS, players, tracks);
*e++ = '[';
for (i = 0; i < seats; i++)
{
@ -440,7 +439,7 @@ static qboolean browser_handle_query(const char *req, char *buffer, size_t buffe
{
char serverinfo[4096];
char *e = buffer;
pGetServerInfo(serverinfo, sizeof(serverinfo));
clientfuncs->GetServerInfo(serverinfo, sizeof(serverinfo));
e = Info_JSONify(serverinfo, e, buffer + buffersize - e-1);
if (e == buffer) e++;
*buffer = '{';
@ -458,8 +457,7 @@ static qboolean browser_handle_query(const char *req, char *buffer, size_t buffe
*e++ = '[';
for (i = 0; ; i++)
{
if (!pGetPlayerInfo(i, &info))
break;
clientfuncs->GetPlayerInfo(i, &info);
if (buffer + buffersize - e-1 < 100)
break;
@ -468,7 +466,7 @@ static qboolean browser_handle_query(const char *req, char *buffer, size_t buffe
*e++ = ',';
*e++ = '{';
//splurge the specific info
sprintf(e, "\"frags\":%i,\"ping\":%i,\"pl\":%i,\"start\":%i,\"userid\":%i", info.frags, info.ping, info.pl, info.starttime, info.userid);
sprintf(e, "\"frags\":%i,\"ping\":%i,\"pl\":%i,\"active\":%i,\"userid\":%i", info.frags, info.ping, info.pl, info.activetime, info.userid);
e += strlen(e);
//splurge the generic info (colours, name, team)
e = Info_JSONify(info.userinfo, e, buffer + buffersize - e-1);
@ -483,7 +481,7 @@ static qboolean browser_handle_query(const char *req, char *buffer, size_t buffe
return false;
}
static int CEF_CALLBACK browser_on_process_message_received(cef_client_t* self, cef_browser_t* browser, cef_process_id_t source_process, cef_process_message_t* message)
static int CEF_CALLBACK browser_on_process_message_received(cef_client_t* self, cef_browser_t* browser, cef_frame_t* frame, cef_process_id_t source_process, cef_process_message_t* message)
{
int handled = false;
// browser_t *br = (browser_t*)((char*)self - offsetof(browser_t, request_handler));
@ -523,7 +521,7 @@ static int CEF_CALLBACK browser_on_process_message_received(cef_client_t* self,
cef_string_utf8_clear(&queryname);
if (cmdunusable)
cef_string_userfree_free(cmdunusable);
browser->send_process_message(browser, source_process, reply);
frame->send_process_message(frame, source_process, reply);
handled = true;
}
cef_release(message);
@ -536,7 +534,7 @@ static int CEF_CALLBACK browser_on_process_message_received(cef_client_t* self,
}
//render_handler methods
static int CEF_CALLBACK browser_get_view_rect(cef_render_handler_t *self, cef_browser_t *browser, cef_rect_t *rect)
static void CEF_CALLBACK browser_get_view_rect(cef_render_handler_t *self, cef_browser_t *browser, cef_rect_t *rect)
{
browser_t *br = (browser_t*)((char*)self - offsetof(browser_t, render_handler));
@ -545,7 +543,6 @@ static int CEF_CALLBACK browser_get_view_rect(cef_render_handler_t *self, cef_br
rect->width = br->desiredwidth;
rect->height = br->desiredheight;
cef_release(browser);
return true;
}
static void CEF_CALLBACK browser_on_paint(cef_render_handler_t *self, cef_browser_t *browser, cef_paint_element_type_t type, size_t dirtyRectsCount, cef_rect_t const* dirtyRects, const void* buffer, int width, int height)
{
@ -639,7 +636,7 @@ static void CEF_CALLBACK browser_on_before_context_menu(struct _cef_context_menu
//display_handler methods
//redirect console.log messages to quake's console, but only display them if we've got developer set.
static int CEF_CALLBACK browser_on_console_message(cef_display_handler_t* self, cef_browser_t* browser, const cef_string_t* message, const cef_string_t* source, int line)
static int CEF_CALLBACK browser_on_console_message(cef_display_handler_t* self, cef_browser_t* browser, cef_log_severity_t level, const cef_string_t* message, const cef_string_t* source, int line)
{
cef_string_utf8_t u8_source = {NULL};
cef_string_utf8_t u8_message = {NULL};
@ -664,7 +661,7 @@ static void CEF_CALLBACK browser_on_title_change(cef_display_handler_t* self, ce
cef_string_utf8_copy(br->currenturl.str, br->currenturl.length, &br->currenttitle);
if (br->consolename)
pCon_SetConsoleString(br->consolename, "title", br->currenttitle.str?br->currenttitle.str:"");
confuncs->SetConsoleString(br->consolename, "title", br->currenttitle.str?br->currenttitle.str:"");
cef_release(browser);
}
@ -683,7 +680,7 @@ static void CEF_CALLBACK browser_on_favicon_urlchange(cef_display_handler_t* sel
cef_string_clear(&str);
if (br->consolename)
pCon_SetConsoleString(br->consolename, "icon", br->currenticon.str?br->currenticon.str:"");
confuncs->SetConsoleString(br->consolename, "icon", br->currenticon.str?br->currenticon.str:"");
cef_release(browser);
}
@ -693,7 +690,7 @@ static void CEF_CALLBACK browser_on_fullscreenmode_change(cef_display_handler_t*
br->fullscreen = fullscreen;
if (br->consolename)
pCon_SetConsoleFloat(br->consolename, "fullscreen", br->fullscreen);
confuncs->SetConsoleFloat(br->consolename, "fullscreen", br->fullscreen);
cef_release(browser);
}
@ -707,7 +704,7 @@ static void CEF_CALLBACK browser_on_address_change(cef_display_handler_t* self,
{
cef_string_utf8_clear(&br->currenticon);
if (br->consolename)
pCon_SetConsoleString(br->consolename, "icon", br->currenticon.str?br->currenticon.str:"");
confuncs->SetConsoleString(br->consolename, "icon", br->currenticon.str?br->currenticon.str:"");
}
//FIXME: should probably make sure its the root frame
@ -722,7 +719,7 @@ static int CEF_CALLBACK browser_on_tooltip(cef_display_handler_t* self, cef_brow
{
cef_string_utf8_t u8_text = {NULL};
cef_string_to_utf8(text->str, text->length, &u8_text);
pCon_SetConsoleString(br->consolename, "tooltip", u8_text.str?u8_text.str:"");
confuncs->SetConsoleString(br->consolename, "tooltip", u8_text.str?u8_text.str:"");
cef_string_utf8_clear(&u8_text);
}
cef_release(browser);
@ -736,7 +733,7 @@ static void CEF_CALLBACK browser_on_status_message(cef_display_handler_t* self,
cef_string_utf8_t u8_value = {NULL};
if (value)
cef_string_to_utf8(value->str, value->length, &u8_value);
pCon_SetConsoleString(br->consolename, "footer", u8_value.str?u8_value.str:"");
confuncs->SetConsoleString(br->consolename, "footer", u8_value.str?u8_value.str:"");
cef_string_utf8_clear(&u8_value);
}
@ -744,7 +741,9 @@ static void CEF_CALLBACK browser_on_status_message(cef_display_handler_t* self,
}
//request_handler methods
static int CEF_CALLBACK browser_on_before_browse(cef_request_handler_t* self, cef_browser_t* browser, cef_frame_t* frame, cef_request_t* request, int is_redirect)
static int CEF_CALLBACK browser_on_before_browse(cef_request_handler_t* self, cef_browser_t* browser, cef_frame_t* frame, cef_request_t* request, int user_gesture, int is_redirect)
{
// browser_t *br = (browser_t*)((char*)self - offsetof(browser_t, request_handler));
@ -752,7 +751,7 @@ static int CEF_CALLBACK browser_on_before_browse(cef_request_handler_t* self, ce
cef_release(frame);
cef_release(request);
return false;
return false; //false = allow navigation, true = block
}
static void CEF_CALLBACK browser_on_render_process_terminated(cef_request_handler_t* self, cef_browser_t* browser, cef_termination_status_t status)
{
@ -795,7 +794,6 @@ browser_subs(context_menu_handler);
nb->client.get_drag_handler = NULL;
nb->client.get_find_handler = NULL;
nb->client.get_focus_handler = NULL;
nb->client.get_geolocation_handler = NULL;
nb->client.get_jsdialog_handler = NULL;
nb->client.get_keyboard_handler = NULL;
nb->client.get_life_span_handler = browser_get_life_span_handler;
@ -828,15 +826,15 @@ browser_subs(context_menu_handler);
nb->request_handler.on_before_browse = browser_on_before_browse;
nb->request_handler.on_open_urlfrom_tab = NULL;
nb->request_handler.on_before_resource_load = NULL;
nb->request_handler.get_resource_handler = NULL;
nb->request_handler.on_resource_redirect = NULL;
nb->request_handler.on_resource_response = NULL;
nb->request_handler.get_resource_response_filter = NULL;
nb->request_handler.on_resource_load_complete = NULL;
// nb->request_handler.on_before_resource_load = NULL;
// nb->request_handler.get_resource_handler = NULL;
// nb->request_handler.on_resource_redirect = NULL;
// nb->request_handler.on_resource_response = NULL;
// nb->request_handler.get_resource_response_filter = NULL;
// nb->request_handler.on_resource_load_complete = NULL;
nb->request_handler.get_auth_credentials = NULL;
nb->request_handler.on_quota_request = NULL;
nb->request_handler.on_protocol_execution = NULL; //FIXME: should implement.
// nb->request_handler.on_protocol_execution = NULL; //FIXME: should implement.
nb->request_handler.on_certificate_error = NULL;
// nb->request_handler.on_select_client_certificate = NULL; //we have no such certs
nb->request_handler.on_plugin_crashed = NULL;
@ -877,11 +875,7 @@ browser_subs(context_menu_handler);
static cef_request_context_t *request_context;
static cef_request_context_handler_t request_context_handler;
//request_context_handler methods
static int CEF_CALLBACK request_context_handler_on_before_plugin_load(cef_request_context_handler_t* self, const cef_string_t* mime_type, const cef_string_t* plugin_url,
#if CEF_COMMIT_NUMBER >= 1658
int is_main_frame,
#endif
const cef_string_t* top_origin_url, cef_web_plugin_info_t* plugin_info, cef_plugin_policy_t* plugin_policy)
static int CEF_CALLBACK request_context_handler_on_before_plugin_load(cef_request_context_handler_t* self, const cef_string_t* mime_type, const cef_string_t* plugin_url, int is_main_frame, const cef_string_t* top_origin_url, cef_web_plugin_info_t* plugin_info, cef_plugin_policy_t* plugin_policy)
{
// Con_DPrintf("%s (%s), \"%s\" \"%s\" \"%s\" \"%s\"\n", policy_url.ToString().c_str(), url.ToString().c_str(),
// info->GetName().ToString().c_str(), info->GetPath().ToString().c_str(), info->GetVersion().ToString().c_str(), info->GetDescription().ToString().c_str());
@ -890,8 +884,7 @@ static int CEF_CALLBACK request_context_handler_on_before_plugin_load(cef_reques
cef_release(plugin_info);
Cvar_Update(&cef_allowplugins);
if (!cef_allowplugins.value)
if (!cef_allowplugins->value)
{
*plugin_policy = PLUGIN_POLICY_DISABLE;
// Con_Printf("Blocking plugin: %s (%s)\n", info->GetName().ToString().c_str(), url.ToString().c_str());
@ -921,21 +914,16 @@ static cef_render_process_handler_t* CEF_CALLBACK app_get_render_process_handler
static void CEF_CALLBACK app_on_register_custom_schemes(struct _cef_app_t* self, cef_scheme_registrar_t* registrar)
{
cef_string_t fte = makecefstring("fte");
registrar->add_custom_scheme(registrar, &fte
, /*is_standard*/true
, /*is_local*/false
, /*is_display_isolated*/true
#if CEF_COMMIT_NUMBER >= 1658 //not sure what number it is.
, /*is_secure*/true
, /*is_cors_enabled*/true //display_isolated means that we shouldn't be getting requests from http anyway, so we don't need CORS protection.
, /*is_csp_bypassing*/false
#endif
registrar->add_custom_scheme(registrar, &fte, CEF_SCHEME_OPTION_NONE
|CEF_SCHEME_OPTION_STANDARD
/*|CEF_SCHEME_OPTION_LOCAL*/
|CEF_SCHEME_OPTION_DISPLAY_ISOLATED
|CEF_SCHEME_OPTION_SECURE
|CEF_SCHEME_OPTION_CORS_ENABLED
/*|CEF_SCHEME_OPTION_CSP_BYPASSING*/
/*|CEF_SCHEME_OPTION_FETCH_ENABLED*/
);
cef_string_clear(&fte);
#ifndef cef_base_t
cef_release(registrar);
#endif
}
static void CEF_CALLBACK browser_process_handler_on_context_initialized(cef_browser_process_handler_t* self)
@ -992,12 +980,12 @@ typedef struct
int64 queryid;
atomic_uint32_t refcount;
} queryresponse_t;
static void CEF_CALLBACK queryresponse_addref(cef_base_t* self)
static void CEF_CALLBACK queryresponse_addref(cef_base_ref_counted_t* self)
{
queryresponse_t *qr = (queryresponse_t*)((char*)self - offsetof(queryresponse_t, task.base));
atomic_fetch_add(&qr->refcount, 1);
}
static int CEF_CALLBACK queryresponse_release(cef_base_t* self)
static int CEF_CALLBACK queryresponse_release(cef_base_ref_counted_t* self)
{
queryresponse_t *qr = (queryresponse_t*)((char*)self - offsetof(queryresponse_t, task.base));
if (atomic_fetch_sub(&qr->refcount, 1) == 1)
@ -1113,7 +1101,7 @@ static int CEF_CALLBACK fsfunc_execute(cef_v8handler_t* self, const cef_string_t
args->set_int(args, 3, (q->queryid>>32) & 0xffffffff);
cef_release(args);
browser->send_process_message(browser, PID_BROWSER, msg);
frame->send_process_message(frame, PID_BROWSER, msg);
if (setting)
cef_string_userfree_free(setting);
@ -1129,7 +1117,7 @@ static int CEF_CALLBACK fsfunc_execute(cef_v8handler_t* self, const cef_string_t
return 1;
}
static int CEF_CALLBACK render_process_handler_on_process_message_received(cef_render_process_handler_t* self,cef_browser_t* browser, cef_process_id_t source_process,cef_process_message_t* message)
static int CEF_CALLBACK render_process_handler_on_process_message_received(cef_render_process_handler_t* self,cef_browser_t* browser, cef_frame_t* frame, cef_process_id_t source_process, cef_process_message_t* message)
{
int handled = false;
// browser_t *br = (browser_t*)((char*)self - offsetof(browser_t, request_handler));
@ -1174,12 +1162,12 @@ typedef struct
unsigned int resultcode;
char *responseheaders;
} fteresource_t;
static void CEF_CALLBACK resource_handler_addref(cef_base_t* self)
static void CEF_CALLBACK resource_handler_addref(cef_base_ref_counted_t* self)
{
fteresource_t *rh = (fteresource_t*)((char*)self - offsetof(fteresource_t, rh.base));
atomic_fetch_add(&rh->refcount, 1);
}
static int CEF_CALLBACK resource_handler_release(cef_base_t* self)
static int CEF_CALLBACK resource_handler_release(cef_base_ref_counted_t* self)
{
fteresource_t *rh = (fteresource_t*)((char*)self - offsetof(fteresource_t, rh.base));
if (atomic_fetch_sub(&rh->refcount, 1) == 1)
@ -1279,7 +1267,7 @@ static int CEF_CALLBACK resource_handler_process_request(cef_resource_handler_t*
//(also blocks any fancy http:// parsing that an engine might do)
if (!strncmp(u8_url.str, "fte://data/", 11))
{
pVFS_Open(u8_url.str+6, &rh->fh, "rb");
rh->fh = fsfuncs->OpenVFS(u8_url.str+6, "rb", FS_GAME);
if (rh->fh)
{
cef_string_userfree_t mt = cef_get_mime_type(&ext);
@ -1319,14 +1307,12 @@ static int CEF_CALLBACK resource_handler_process_request(cef_resource_handler_t*
rh->resultcode = 404;
if (!BUILTINISVALID(PR_GetVMInstance))
progs = NULL;
else if (!strncmp(u8_url.str, "fte://ssqc/", 11))
progs = pPR_GetVMInstance(0); //WARNING: goes direct rather than via the server.
if (!strncmp(u8_url.str, "fte://ssqc/", 11))
progs = plugfuncs->GetEngineInterface("SSQCVM", sizeof(*progs)); //WARNING: goes direct rather than via the server, so basically single-player only.
else if (!strncmp(u8_url.str, "fte://csqc/", 11))
progs = pPR_GetVMInstance(1);
progs = plugfuncs->GetEngineInterface("CSQCVM", sizeof(*progs));
else if (!strncmp(u8_url.str, "fte://menu/", 11))
progs = pPR_GetVMInstance(2);
progs = plugfuncs->GetEngineInterface("MenuQCVM", sizeof(*progs));
else
progs = NULL;
@ -1535,8 +1521,6 @@ static cef_resource_handler_t* CEF_CALLBACK scheme_handler_factory_create(cef_sc
rh->rh.process_request = resource_handler_process_request;
rh->rh.get_response_headers = resource_handler_get_response_headers;
rh->rh.read_response = resource_handler_read_response;
rh->rh.can_get_cookie = NULL;
rh->rh.can_set_cookie = NULL;
rh->rh.cancel = resource_handler_cancel;
cef_addref(&rh->rh);
@ -1580,8 +1564,7 @@ cef_request_context_t *Cef_GetRequestContext(void)
cef_request_context_t *ret = NULL;
qboolean incog;
Cvar_Update(&cef_incognito);
incog = cef_incognito.value;
incog = cef_incognito->value;
if (!incog)
ret = request_context;
@ -1590,7 +1573,7 @@ cef_request_context_t *Cef_GetRequestContext(void)
{
cef_request_context_settings_t csettings = {sizeof(csettings)};
csettings.persist_user_preferences = !incog;
if (!incog && pFS_NativePath("cefcache", FS_ROOT, utf8, sizeof(utf8)))
if (!incog && fsfuncs->NativePath("cefcache", FS_ROOT, utf8, sizeof(utf8)))
cef_string_from_utf8(utf8, strlen(utf8), &csettings.cache_path); //should be empty for incognito.
ret = cef_request_context_create_context(&csettings, &request_context_handler);
cef_string_clear(&csettings.cache_path);
@ -1644,16 +1627,24 @@ static void *Cef_Create(const char *name, struct mediacallbacks_s *callbacks)
//const char *ua = "FTEBrowser";
//cef_string_from_utf8(ua, strlen(ua), &settings.user_agent);
if (pFS_NativePath("cefcache", FS_ROOT, utf8, sizeof(utf8)))
if (fsfuncs->NativePath("cefcache", FS_ROOT, utf8, sizeof(utf8)))
cef_string_from_utf8(utf8, strlen(utf8), &settings.cache_path);
if (pFS_NativePath("cef_debug.log", FS_ROOT, utf8, sizeof(utf8)))
if (fsfuncs->NativePath("cef_debug.log", FS_ROOT, utf8, sizeof(utf8)))
cef_string_from_utf8(utf8, strlen(utf8), &settings.log_file);
if (pFS_NativePath("", FS_BINARYPATH, utf8, sizeof(utf8)))
if (fsfuncs->NativePath("", FS_BINARYPATH, utf8, sizeof(utf8)))
cef_string_from_utf8(utf8, strlen(utf8), &settings.resources_dir_path);
if (pFS_NativePath("locales", FS_BINARYPATH, utf8, sizeof(utf8)))
if (fsfuncs->NativePath("locales", FS_BINARYPATH, utf8, sizeof(utf8)))
{
struct stat statbuf;
if (stat(utf8, &statbuf) < 0)
{
Con_Printf("%s not found\n", utf8);
return NULL;
}
cef_string_from_utf8(utf8, strlen(utf8), &settings.locales_dir_path);
}
#ifdef _WIN32
{
@ -1696,14 +1687,9 @@ static void *Cef_Create(const char *name, struct mediacallbacks_s *callbacks)
if (!cefwasinitialised)
return NULL;
Cvar_Update(&cef_allowplugins);
//tbh, web browser's are so horribly insecure that it seems pointless to even try disabling stuff that might be useful
browserSettings.windowless_frame_rate = 60;
browserSettings.javascript_close_windows = STATE_DISABLED;
#if CEF_COMMIT_NUMBER < 1658
browserSettings.javascript_open_windows = STATE_DISABLED;
#endif
browserSettings.javascript_access_clipboard = STATE_DISABLED;
// browserSettings.universal_access_from_file_urls = STATE_DISABLED;
// browserSettings.file_access_from_file_urls = STATE_DISABLED;
@ -1713,9 +1699,6 @@ static void *Cef_Create(const char *name, struct mediacallbacks_s *callbacks)
window_info.windowless_rendering_enabled = true;
memset(&window_info.parent_window, 0, sizeof(window_info.parent_window));
#if CEF_COMMIT_NUMBER < 1658
window_info.transparent_painting_enabled = true;
#endif
newbrowser = browser_create();
if (!newbrowser)
@ -1726,7 +1709,7 @@ static void *Cef_Create(const char *name, struct mediacallbacks_s *callbacks)
cef_string_from_utf8(name, strlen(name), &url);
cef_addref(&newbrowser->client);
newbrowser->thebrowser = pcef_browser_host_create_browser_sync(&window_info, &newbrowser->client, &url, &browserSettings, Cef_GetRequestContext());
newbrowser->thebrowser = cef_browser_host_create_browser_sync(&window_info, &newbrowser->client, &url, &browserSettings, NULL, Cef_GetRequestContext());
cef_string_to_utf8(url.str, url.length, &newbrowser->currenturl);
cef_string_clear(&url);
if (!newbrowser->thebrowser)
@ -1735,8 +1718,7 @@ static void *Cef_Create(const char *name, struct mediacallbacks_s *callbacks)
return NULL; //cef fucked up.
}
Cvar_Update(&cef_devtools);
if (cef_devtools.value)
if (cef_devtools->value)
{
cef_browser_host_t *host = newbrowser->thebrowser->get_host(newbrowser->thebrowser);
browser_t *devtools = browser_create();
@ -1759,11 +1741,7 @@ static void *Cef_Create(const char *name, struct mediacallbacks_s *callbacks)
window_info.windowless_rendering_enabled = false;
cef_addref(&devtools->client);
host->show_dev_tools(host, &window_info, &devtools->client, &browserSettings
#if CEF_COMMIT_NUMBER >= 1373 //not sure about the actual revision
, NULL
#endif
);
host->show_dev_tools(host, &window_info, &devtools->client, &browserSettings, NULL);
cef_release(host);
browser_release(devtools); //cef should continue to hold a reference to it while its visible, but its otherwise out of engine now.
@ -1910,7 +1888,7 @@ static void VARGS Cef_Key (void *ctx, int code, int unicode, int event)
if (browser->keystate[code])
kev.native_key_code |= 1<<30;
if (event)
kev.native_key_code |= 1<<31;
kev.native_key_code |= 1u<<31;
if (event)
browser->keystate[code] = 0;
@ -1938,7 +1916,7 @@ static void VARGS Cef_Key (void *ctx, int code, int unicode, int event)
if (browser->keystate[code])
kev.native_key_code |= 1<<30;
if (event)
kev.native_key_code |= 1<<31;
kev.native_key_code |= 1u<<31;
kev.is_system_key = 0;
kev.character = unicode;
@ -2024,7 +2002,7 @@ static void VARGS Cef_ChangeStream (void *ctx, const char *streamname)
cef_string_clear(&thescript);
cef_string_clear(&url);
}
else if (!strncmp(streamname, "raw:", 4))
/*else if (!strncmp(streamname, "raw:", 4))
{
cef_string_t thehtml = {NULL};
cef_string_t url = {NULL};
@ -2034,7 +2012,7 @@ static void VARGS Cef_ChangeStream (void *ctx, const char *streamname)
frame->load_string(frame, &thehtml, &url);
cef_string_clear(&thehtml);
cef_string_clear(&url);
}
}*/
else if (*streamname && strcmp(streamname, "http:") && strcmp(streamname, "https:"))
{
cef_string_t url = {NULL};
@ -2139,25 +2117,31 @@ static qintptr_t Cef_Shutdown(qintptr_t *args)
}
#ifndef _WIN32
int argc=0;
char *argv[64];
char commandline[8192];
static void SetupArgv(void)
static int argc=0;
static char *argv[64];
static char commandline[8192];
static void SetupArgv(cef_main_args_t *a)
{
if (argc)
return;
int i;
FILE *f = fopen("/proc/self/cmdline", "r");
char *e = commandline+fread(commandline, 1, sizeof(commandline), f);
fclose(f);
char *s = commandline;
while(s < e)
FILE *f;
if (!argc)
{
argv[argc++] = s;
while(*s)
s++;
s++;
f = fopen("/proc/self/cmdline", "r");
if (f)
{
char *s = commandline;
char *e = commandline+fread(commandline, 1, sizeof(commandline), f);
fclose(f);
while(s < e)
{
argv[argc++] = s;
while(*s)
s++;
s++;
}
}
}
a->argc = argc;
a->argv = argv;
}
#endif
@ -2167,16 +2151,16 @@ static qboolean Cef_Init(qboolean engineprocess)
#ifdef _WIN32
cef_main_args_t args = {GetModuleHandle(NULL)};
#else
SetupArgv();
cef_main_args_t args = {argc, argv};
cef_main_args_t args;
SetupArgv(&args);
#endif
{
int result;
#ifdef LIBCEF_DYNAMIC
dllfunction_t ceffuncs[] =
{
{(void **)&cef_api_hash, "cef_api_hash"},
{(void **)&cef_version_info, "cef_version_info"},
{(void **)&cef_initialize, "cef_initialize"},
{(void **)&cef_do_message_loop_work, "cef_do_message_loop_work"},
@ -2191,7 +2175,6 @@ static qboolean Cef_Init(qboolean engineprocess)
{(void **)&cef_string_utf8_set, "cef_string_utf8_set"},
{(void **)&cef_string_userfree_utf16_free, "cef_string_userfree_utf16_free"},
{(void **)&cef_register_scheme_handler_factory, "cef_register_scheme_handler_factory"},
{(void **)&cef_get_mime_type, "cef_get_mime_type"},
{(void **)&cef_v8value_create_function, "cef_v8value_create_function"},
{(void **)&cef_v8value_create_string, "cef_v8value_create_string"},
{(void **)&cef_process_message_create, "cef_process_message_create"},
@ -2214,11 +2197,20 @@ static qboolean Cef_Init(qboolean engineprocess)
Con_Printf("Unable to load libcef (version "CEF_VERSION")\n");
return false;
}
#endif
if (engineprocess)
{
Con_Printf("libcef %i.%i: chrome %i.%i (%i)\n", cef_version_info(0), cef_version_info(1), cef_version_info(2), cef_version_info(3), cef_version_info(4));
if (strcmp(cef_api_hash(0), CEF_API_HASH_PLATFORM))
if (cef_version_info(0) != CEF_VERSION_MAJOR||
cef_version_info(1) != CEF_VERSION_MINOR||
cef_version_info(2) != CEF_VERSION_PATCH||
cef_version_info(3) != CEF_COMMIT_NUMBER||
cef_version_info(4) != CHROME_VERSION_MAJOR||
cef_version_info(5) != CHROME_VERSION_MINOR||
cef_version_info(6) != CHROME_VERSION_BUILD||
cef_version_info(7) != CHROME_VERSION_PATCH)
{ //the libcef api hash can be used to see if there's an api change that might break stuff.
//refuse to load it if the api changed.
Con_Printf("libcef outdated. Please install libcef version "CEF_VERSION"\n");
@ -2247,10 +2239,10 @@ int NATIVEEXPORT CefSubprocessInit(void)
static qintptr_t Cef_ExecuteCommand(qintptr_t *args)
{
char cmd[256];
pCmd_Argv(0, cmd, sizeof(cmd));
cmdfuncs->Argv(0, cmd, sizeof(cmd));
if (!strcmp(cmd, "cef"))
{
if (BUILTINISVALID(Con_SetConsoleFloat))
if (confuncs)
{
static int sequence;
char f[128];
@ -2258,18 +2250,18 @@ static qintptr_t Cef_ExecuteCommand(qintptr_t *args)
Q_snprintf(f, sizeof(f), "libcef:%i", ++sequence);
newconsole = f;
strcpy(videomap, "cef:");
pCmd_Argv(1, videomap+4, sizeof(videomap)-4);
cmdfuncs->Argv(1, videomap+4, sizeof(videomap)-4);
if (!videomap[4])
strcpy(videomap, "cef:http://fte.triptohell.info");
pCon_SetConsoleString(f, "title", videomap+4);
pCon_SetConsoleFloat(f, "iswindow", true);
pCon_SetConsoleFloat(f, "forceutf8", true);
pCon_SetConsoleFloat(f, "wnd_w", 640+16);
pCon_SetConsoleFloat(f, "wnd_h", 480+16+8);
pCon_SetConsoleString(f, "backvideomap", videomap);
pCon_SetConsoleFloat(f, "linebuffered", 2);
pCon_SetActive(f);
confuncs->SetConsoleString(f, "title", videomap+4);
confuncs->SetConsoleFloat(f, "iswindow", true);
confuncs->SetConsoleFloat(f, "forceutf8", true);
confuncs->SetConsoleFloat(f, "wnd_w", 640+16);
confuncs->SetConsoleFloat(f, "wnd_h", 480+16+8);
confuncs->SetConsoleString(f, "backvideomap", videomap);
confuncs->SetConsoleFloat(f, "linebuffered", 2);
confuncs->SetActive(f);
newconsole = NULL;
}
@ -2278,27 +2270,18 @@ static qintptr_t Cef_ExecuteCommand(qintptr_t *args)
return false;
}
qintptr_t Plug_Init(qintptr_t *args)
qboolean Plug_Init(void)
{
CHECKBUILTIN(Plug_GetPluginName);
CHECKBUILTIN(FS_NativePath);
if (!BUILTINISVALID(Plug_GetPluginName) || !BUILTINISVALID(FS_NativePath))
fsfuncs = (plugfsfuncs_t*)plugfuncs->GetEngineInterface(plugfsfuncs_name, sizeof(*fsfuncs)); //for fte://data/ scheme
confuncs = (plugsubconsolefuncs_t*)plugfuncs->GetEngineInterface(plugsubconsolefuncs_name, sizeof(*confuncs)); //for cef command etc.
clientfuncs = (plugclientfuncs_t*)plugfuncs->GetEngineInterface(plugclientfuncs_name, sizeof(*clientfuncs)); //for weird people trying to use xml requests to query game status (for hud stuff)
if (!fsfuncs || !confuncs || !clientfuncs
|| !plugfuncs->ExportFunction("Tick", Cef_Tick)
|| !plugfuncs->ExportFunction("Shutdown", Cef_Shutdown))
{
Con_Printf("CEF plugin failed: Engine too old\n");
Con_Printf("CEF plugin failed: Required engine feature missing.\n");
return false;
}
pPlug_GetPluginName(-1, plugname, sizeof(plugname));
if (!Plug_Export("Tick", Cef_Tick))
{
Con_Printf("CEF plugin failed: Engine doesn't support Tick feature\n");
return false;
}
if (!Plug_Export("Shutdown", Cef_Shutdown))
{
Con_Printf("CEF plugin failed: Engine doesn't support Shutdown feature\n");
return false;
}
decoderfuncs.structsize = sizeof(media_decoder_funcs_t);
decoderfuncs.drivername = "cef";
@ -2313,19 +2296,19 @@ qintptr_t Plug_Init(qintptr_t *args)
decoderfuncs.changestream = Cef_ChangeStream;
decoderfuncs.getproperty = Cef_GetProperty;
if (!pPlug_ExportNative("Media_VideoDecoder", &decoderfuncs))
if (!plugfuncs->ExportInterface("Media_VideoDecoder", &decoderfuncs, sizeof(decoderfuncs)))
{
Con_Printf("CEF plugin failed: Engine doesn't support media decoder plugins\n");
return false;
}
if (Plug_Export("ExecuteCommand", Cef_ExecuteCommand))
pCmd_AddCommand("cef");
if (plugfuncs->ExportFunction("ExecuteCommand", Cef_ExecuteCommand))
cmdfuncs->AddCommand("cef");
Cvar_Register(&cef_incognito);
Cvar_Register(&cef_allowplugins);
Cvar_Register(&cef_allowcvars);
Cvar_Register(&cef_devtools);
cef_incognito = cvarfuncs->GetNVFDG("cef_incognito", "0", 0, NULL, "browser settings");
cef_allowplugins = cvarfuncs->GetNVFDG("cef_allowplugins", "0", 0, NULL, "browser settings");
cef_allowcvars = cvarfuncs->GetNVFDG("cef_allowcvars", "0", 0, NULL, "browser settings");
cef_devtools = cvarfuncs->GetNVFDG("cef_devtools", "0", 0, NULL, "browser settings");
return true;
}

1609
plugins/openxr.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -182,7 +182,8 @@ struct wstats_s;
#define F(t, n, args) t (QDECL *n) args
typedef void dllhandle_t;
struct dllfunction_s;
typedef struct //core stuff
{
//Basic builtins:
@ -193,6 +194,9 @@ typedef struct //core stuff
F(void, Print, (const char *message)); //print on (main) console.
F(void, Error, (const char *message)); //abort the entire engine.
F(quintptr_t,GetMilliseconds, (void));
F(dllhandle_t*,LoadDLL, (const char *modulename, struct dllfunction_s *funcs));
F(void*, GetDLLSymbol, (dllhandle_t *handle, const char *symbolname));
F(void, CloseDLL, (dllhandle_t *handle)); //not guarenteed to actually do anything, of course.
#define plugcorefuncs_name "Core"
} plugcorefuncs_t;

View File

@ -111,7 +111,7 @@ class mitem_servers : mitem
maxsv = slider.val + maxy;
float sort = gethostcachevalue(SLIST_SORTFIELD);
string colkey;
string colkey = __NULL__;
#define COLUMN(width, sortname, title, draw) if (autocvar_sb_show##sortname) {if (ui.mousepos[0] > pos_x && ui.mousepos[1] < pos_y+8) colkey = #sortname; pos_x += width+8;}
COLUMNS
#undef COLUMN

View File

@ -138,7 +138,7 @@ class menu_updates : mitem_exmenu
{
if (key == "info")
{
string text, tmp;
string text=__NULL__, tmp;
tmp = getpackagemanagerinfo(grid.grid_kactive, GPMI_VERSION); text = strcat(text, "^aVersion:^a ", tmp?:"Unspecified");
tmp = getpackagemanagerinfo(grid.grid_kactive, GPMI_AUTHOR); text = strcat(text, "\n^aAuthor:^a ", tmp?:"Unknown");
tmp = getpackagemanagerinfo(grid.grid_kactive, GPMI_LICENSE); text = strcat(text, "\n^aLicense:^a ", tmp?:"Unknown");

View File

@ -623,7 +623,7 @@ void() mitem_frame::item_resized =
void(vector pos) mitem_frame::item_draw =
{
local vector omin = ui.drawrectmin, omax = ui.drawrectmax;
local mitem ch;
local mitem ch = __NULL__;
local vector clientpos;
local vector clientsize;