From c6c3d3f4e0d3056f9e6b2f17e3ddb4063e2d3905 Mon Sep 17 00:00:00 2001 From: Spoike Date: Sun, 30 Sep 2012 05:52:03 +0000 Subject: [PATCH] Trimmed some dead files. Quick hack preliminary d3d11 renderer. I'm not likely to touch this again for quite some time. Sys_Error works properly on android, with an error message shown. Should be less of a stab in the dark if you get errors. Seg faults are still instantly fatal. Not much I can reliably do about those - most of the juicy ones will likely occur within the gl drivers (even if its my fault) and java will still call in to it. Stereoscopic (quad-buffered) rendering is in the gl renderer. You'll likely need a quatro to use it despite it being a gl 1.0 feature. No idea about ati. See r_stereo_method for non-quad-buffered alternatives. Tweaked networking to not overflow so much. Needs testing against other qw clients. Fixed an issue with surface numbers > 32k on limit-breaking maps. Fixed a preparse issue resulting in QW clients dying with the ne_ruins map's progs. Support for the DP-variant of BSP2. The depricated RMQ variant is still supported. QTV proxy now uses ipv6 hybrid sockets where possible. Preliminary pext support. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4105 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/Makefile | 23 +- engine/client/cl_cam.c | 2 - engine/client/cl_demo.c | 2 +- engine/client/cl_ents.c | 26 +- engine/client/cl_input.c | 2 +- engine/client/cl_main.c | 31 +- engine/client/cl_parse.c | 42 +- engine/client/cl_tent.c | 4 +- engine/client/cl_ui.c | 2 +- engine/client/client.h | 1 + engine/client/image.c | 18 +- engine/client/in_macos.c | 192 +- engine/client/m_mp3.c | 6 +- engine/client/m_multi.c | 2 +- engine/client/merged.h | 6 +- engine/client/mymad.c | 246 -- engine/client/p_script.c | 8 +- engine/client/pr_csqc.c | 68 +- engine/client/pr_skelobj.c | 125 +- engine/client/r_2d.c | 11 +- engine/client/r_partset.c | 2 +- engine/client/r_surf.c | 653 +--- engine/client/render.h | 30 +- engine/client/renderer.c | 100 +- engine/client/renderque.c | 7 + engine/client/sbar.c | 27 +- engine/client/skin.c | 22 +- engine/client/snd_dma.c | 7 +- engine/client/snd_mix.c | 1 + engine/client/snd_sndio.c | 210 ++ engine/client/sound.h | 23 +- engine/client/sys_droid.c | 77 +- engine/client/sys_win.c | 38 +- engine/client/vid.h | 3 +- engine/client/view.c | 2 +- engine/client/winquake.rc | 2 +- engine/common/bothdefs.h | 21 +- engine/common/bspfile.h | 29 +- engine/common/com_mesh.c | 51 +- engine/common/com_phys_ode.c | 57 +- engine/common/common.c | 17 +- engine/common/gl_q2bsp.c | 298 +- engine/common/mathlib.h | 6 +- engine/common/net.h | 1 + engine/common/net_wins.c | 13 +- engine/common/netinc.h | 2 +- engine/common/pr_bgcmd.c | 81 +- engine/common/pr_common.h | 9 +- engine/common/protocol.h | 5 +- engine/common/unzip.c | 1 - engine/d3d/d3d11_backend.c | 2777 +++++++++++++++++ engine/d3d/d3d11_image.c | 542 ++++ engine/d3d/d3d11_shader.c | 341 ++ engine/d3d/d3d_backend.c | 74 +- engine/d3d/d3d_image.c | 10 +- engine/d3d/d3d_shader.c | 66 +- engine/d3d/vid_d3d.c | 74 +- engine/d3d/vid_d3d11.c | 1311 ++++++++ engine/dotnet2005/ftequake.vcproj | 408 +-- engine/dotnet2010/ftequake.sln | 4 +- engine/dotnet2010/ftequake.vcxproj | 775 +---- engine/dotnet2010/npfte.vcxproj | 2 + engine/droid/AndroidManifest.xml | 3 +- .../droid/src/com/fteqw/FTEDroidActivity.java | 69 +- .../droid/src/com/fteqw/FTEDroidEngine.java | 35 +- engine/gl/gl_alias.c | 27 +- engine/gl/gl_backend.c | 114 +- engine/gl/gl_bloom.c | 4 +- engine/gl/gl_draw.c | 13 +- engine/gl/gl_font.c | 6 +- engine/gl/gl_heightmap.c | 103 +- engine/gl/gl_model.c | 166 +- engine/gl/gl_model.h | 5 +- engine/gl/gl_ngraph.c | 2 +- engine/gl/gl_rlight.c | 2 + engine/gl/gl_rmain.c | 141 +- engine/gl/gl_rmisc.c | 2 +- engine/gl/gl_rsurf.c | 18 +- engine/gl/gl_shader.c | 308 +- engine/gl/gl_shadow.c | 137 +- engine/gl/gl_vidcommon.c | 26 +- engine/gl/gl_vidnt.c | 59 +- engine/gl/r_bishaders.h | 9 +- engine/gl/shader.h | 99 +- engine/qclib/initlib.c | 2 +- engine/qclib/pr_edict.c | 2 +- engine/qclib/progslib.h | 2 +- engine/server/net_preparse.c | 12 +- engine/server/pr_cmds.c | 97 +- engine/server/savegame.c | 27 +- engine/server/server.h | 2 +- engine/server/sv_ents.c | 6 +- engine/server/sv_init.c | 3 +- engine/server/sv_main.c | 22 +- engine/server/sv_phys.c | 1 + engine/server/sv_send.c | 27 +- engine/server/sv_user.c | 28 +- engine/sndcodec/g711.c | 288 -- engine/sndcodec/g721.c | 178 -- engine/sndcodec/g723_24.c | 163 - engine/sndcodec/g723_40.c | 183 -- engine/sndcodec/g72x.c | 573 ---- engine/sndcodec/g72x.h | 118 - engine/sndcodec/snd_vc.c | 404 --- engine/sndcodec/snd_voicecodecs.c | 189 -- engine/sndcodec/voicechat.h | 9 - engine/sw/sw.h | 32 +- engine/sw/sw_backend.c | 12 +- engine/sw/sw_image.c | 8 +- engine/sw/sw_rast.c | 125 +- fteqtv/control.c | 8 +- fteqtv/dotnet2005/qtvprox.vcproj | 4 + fteqtv/msg.c | 29 +- fteqtv/netchan.c | 4 - fteqtv/parse.c | 152 +- fteqtv/protocol.h | 48 + fteqtv/qtv.h | 6 +- fteqtv/qw.c | 44 +- fteqtv/rcon.c | 59 +- fteqtv/source.c | 51 +- specs/modmaking.txt | 4 +- specs/particles.txt | 6 +- 122 files changed, 7941 insertions(+), 5331 deletions(-) delete mode 100644 engine/client/mymad.c create mode 100644 engine/client/snd_sndio.c create mode 100644 engine/d3d/d3d11_backend.c create mode 100644 engine/d3d/d3d11_image.c create mode 100644 engine/d3d/d3d11_shader.c create mode 100644 engine/d3d/vid_d3d11.c delete mode 100644 engine/sndcodec/g711.c delete mode 100644 engine/sndcodec/g721.c delete mode 100644 engine/sndcodec/g723_24.c delete mode 100644 engine/sndcodec/g723_40.c delete mode 100644 engine/sndcodec/g72x.c delete mode 100644 engine/sndcodec/g72x.h delete mode 100644 engine/sndcodec/snd_vc.c delete mode 100644 engine/sndcodec/snd_voicecodecs.c delete mode 100644 engine/sndcodec/voicechat.h diff --git a/engine/Makefile b/engine/Makefile index 89f7aaab3..fc1d846a4 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -44,6 +44,13 @@ ifeq ($(FTE_TARGET),win64) CC=amd64-mingw32msvc-gcc -m64 WINDRES=amd64-mingw32msvc-windres STRIP=amd64-mingw32msvc-strip +# BITS=64 + endif + ifneq ($(shell which x86_64-w64-mingw32-gcc 2> /dev/null),) + #yup, the alternative exists (this matches the one debian has) + CC=x86_64-w64-mingw32-gcc -m64 + WINDRES=x86_64-w64-mingw32-windres + STRIP=x86_64-w64-mingw32-strip # BITS=64 endif endif @@ -217,6 +224,7 @@ ifeq ($(FTE_TARGET),) #user didn't specify prefered target endif ifneq ($(shell $(CC) -v 2>&1 | grep cygwin),) FTE_TARGET=cygwin + ANDROID_SCRIPT=android.bat endif ifeq ($(FTE_TARGET),) #still not set @@ -257,7 +265,6 @@ HTTP_DIR=$(BASE_DIR)/http #LIBS_DIR=$(BASE_DIR)/libs LIBS_DIR?=. PROGS_DIR=$(BASE_DIR)/qclib -SNDCODEC_DIR=$(BASE_DIR)/sndcodec NACL_DIR=$(BASE_DIR)/nacl BOTLIB_DIR=$(BASE_DIR)/botlib @@ -347,7 +354,7 @@ PROFILE_CFLAGS=-pg DX7SDK=-I./libs/dxsdk7/include/ GLCFLAGS=-DGLQUAKE -D3DCFLAGS=-DD3DQUAKE +D3DCFLAGS=-DD3D9QUAKE NPFTECFLAGS=-DNPFTE SPEEX_OBJS = \ @@ -461,14 +468,17 @@ GLQUAKE_OBJS = \ gl_rsurf.o \ gl_screen.o \ gl_bloom.o \ - gl_vidcommon.o \ - gl_hlmdl.o + gl_vidcommon.o D3DQUAKE_OBJS = \ d3d_backend.o \ d3d_image.o \ d3d_shader.o \ - vid_d3d.o + vid_d3d.o \ + d3d11_backend.o \ + d3d11_image.o \ + d3d11_shader.o \ + vid_d3d11.o D3DGL_OBJS = \ gl_font.o \ @@ -477,6 +487,7 @@ D3DGL_OBJS = \ gl_shader.o \ gl_shadow.o \ gl_rlight.o \ + gl_hlmdl.o \ gl_warp.o \ ltface.o \ r_surf.o \ @@ -1031,7 +1042,7 @@ ifneq ($(OUT_DIR),) endif -VPATH = $(BASE_DIR) : $(CLIENT_DIR) : $(GL_DIR) : $(COMMON_DIR) : $(SERVER_DIR) : $(HTTP_DIR) : $(BASE_DIR)/irc : $(BASE_DIR)/email : $(QUX_DIR) : $(PROGS_DIR) : $(NACL_DIR) : $(SNDCODEC_DIR) : $(D3D_DIR) : $(BOTLIB_DIR) +VPATH = $(BASE_DIR) : $(CLIENT_DIR) : $(GL_DIR) : $(COMMON_DIR) : $(SERVER_DIR) : $(HTTP_DIR) : $(BASE_DIR)/irc : $(BASE_DIR)/email : $(QUX_DIR) : $(PROGS_DIR) : $(NACL_DIR) : $(D3D_DIR) : $(BOTLIB_DIR) ifneq ($(findstring -DSPEEX_STATIC, $(CFLAGS)),) #add these to statically link libspeex diff --git a/engine/client/cl_cam.c b/engine/client/cl_cam.c index 7dad8c849..f25362fa7 100644 --- a/engine/client/cl_cam.c +++ b/engine/client/cl_cam.c @@ -25,8 +25,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Player moves as a spectator, but the camera tracks and enemy player */ -#include - #include "quakedef.h" #include "winquake.h" diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index 49507b329..08046c410 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -1317,7 +1317,7 @@ void CL_Record_f (void) { if (!cl.playerview[0].stats[i]) continue; - MSG_WriteByte (&buf, svc_updatestatlong); + MSG_WriteByte (&buf, svcqw_updatestatlong); MSG_WriteByte (&buf, i); MSG_WriteLong (&buf, cl.playerview[0].stats[i]); if (buf.cursize > MAX_QWMSGLEN/2) diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 00d85ca1b..4b6fa7b4c 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -92,13 +92,11 @@ qboolean CL_FilterModelindex(int modelindex, int frame) void CL_FreeDlights(void) { -#if defined(GLQUAKE) || defined(D3DQUAKE) #ifdef RTLIGHTS int i; for (i = 0; i < rtlights_max; i++) if (cl_dlights[i].worldshadowmesh) SH_FreeShadowMesh(cl_dlights[i].worldshadowmesh); -#endif #endif rtlights_max = cl_maxdlights = 0; @@ -115,7 +113,6 @@ void CL_InitDlights(void) static void CL_ClearDlight(dlight_t *dl, int key) { void *sm; - texid_t st; sm = dl->worldshadowmesh; memset (dl, 0, sizeof(*dl)); dl->rebuildcache = true; @@ -2254,8 +2251,6 @@ void CL_LinkStaticEntities(void *pvs) ent->framestate.g[FS_REG].frametime[0] = cl.time; ent->framestate.g[FS_REG].frametime[1] = cl.time; - ent->shaderRGBAf[3] = 0.7; - // emit particles for statics (we don't need to cheat check statics) if (clmodel->particleeffect >= 0 && gl_part_flame.ival) { @@ -4020,6 +4015,27 @@ void CL_LinkViewModel(void) plstate = &cl.frames[parsecountmod].playerstate[plnum]; CLQ1_AddPowerupShell(V_AddEntity(&ent), true, plstate?plstate->effects:0); + + if (alpha < 1 && qrenderer == QR_OPENGL) + { + ent.forcedshader = R_RegisterShader("viewmodeldepthmask", + "{\n" + "noshadows\n" + "surfaceparm nodlight\n" + "{\n" + "map $whiteimage\n" + "maskcolor\n" + "depthwrite\n" + "}\n" + "}\n" + ); + ent.shaderRGBAf[3] = 1; + ent.flags &= ~Q2RF_TRANSLUCENT; + V_AddEntity(&ent); + ent.forcedshader = NULL; + ent.shaderRGBAf[3] = alpha; + ent.flags |= Q2RF_TRANSLUCENT; + } } //====================================================================== diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index b13317197..640474199 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -646,7 +646,7 @@ void CL_ClampPitch (int pnum) } #endif #if 1 - if (1) + if (0) { float surfm[16], invsurfm[16]; float viewm[16]; diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 2acb5778d..44f9f1c17 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -19,7 +19,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // cl_main.c -- client main loop -#include #include "quakedef.h" #include "winquake.h" #include @@ -263,6 +262,26 @@ char soundlist_name[] = { 's'^0xff, 'o'^0xff, 'u'^0xff, 'n'^0xff, 'd'^0xff, 'l'^0xff, 'i'^0xff, 's'^0xff, 't'^0xff, ' '^0xff, '%'^0xff, 'i'^0xff, ' '^0xff, '%'^0xff, 'i'^0xff, 0 }; +void CL_UpdateWindowTitle(void) +{ + if (VID_SetWindowCaption) + { + switch (cls.state) + { + default: +#ifndef CLIENTONLY + if (sv.state) + VID_SetWindowCaption(va("%s %s: %s", DISTRIBUTION, fs_gamename.string, sv.name)); + else +#endif + VID_SetWindowCaption(va("%s %s: %s", DISTRIBUTION, fs_gamename.string, cls.servername)); + break; + case ca_disconnected: + VID_SetWindowCaption(va("%s %s: disconnected", DISTRIBUTION, fs_gamename.string)); + break; + } + } +} void CL_MakeActive(char *gamename) { @@ -274,8 +293,7 @@ void CL_MakeActive(char *gamename) } cls.state = ca_active; S_Purge(true); - if (VID_SetWindowCaption) - VID_SetWindowCaption(va("FTE %s: %s", gamename, cls.servername)); + CL_UpdateWindowTitle(); SCR_EndLoadingPlaque(); @@ -1033,6 +1051,8 @@ void CL_ClearState (void) #define SV_UnspawnServer() #endif + CL_UpdateWindowTitle(); + CL_AllowIndependantSendCmd(false); //model stuff could be a problem. S_StopAllSounds (true); @@ -1151,9 +1171,6 @@ void CL_Disconnect (void) Cvar_ApplyLatches(CVAR_SERVEROVERRIDE); - if (VID_SetWindowCaption) - VID_SetWindowCaption(FULLENGINENAME": disconnected"); - // stop sounds (especially looping!) S_StopAllSounds (true); #ifdef VM_CG @@ -4004,8 +4021,6 @@ void Host_Shutdown(void) //disconnect server/client/etc CL_Disconnect_f(); - //Kill renderer - R_ShutdownRenderer(); #ifdef VM_UI UI_Stop(); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 44f17c984..02cab5f64 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -35,12 +35,12 @@ int cl_dp_csqc_progscrc; int cl_dp_serverextension_download; -char *svc_strings[] = +char *svc_qwstrings[] = { "svc_bad", "svc_nop", "svc_disconnect", - "svc_updatestat", + "svcqw_updatestatbyte", "svc_version", // [long] server version "svc_setview", // [short] entity number "svc_sound", // @@ -170,7 +170,7 @@ char *svc_nqstrings[] = "nqsvc_bad", "nqsvc_nop", "nqsvc_disconnect", - "nqsvc_updatestat", + "nqsvc_updatestatlong", "nqsvc_version", // [long] server version "nqsvc_setview", // [short] entity number "nqsvc_sound", // @@ -2696,7 +2696,7 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. netprim.coordsize = 3; if (fl & RMQFL_FLOATCOORD) netprim.coordsize = 4; - if (fl & ~(RMQFL_SHORTANGLE|RMQFL_FLOATANGLE|RMQFL_24BITCOORD|RMQFL_FLOATCOORD)) + if (fl & ~(RMQFL_SHORTANGLE|RMQFL_FLOATANGLE|RMQFL_24BITCOORD|RMQFL_FLOATCOORD|RMQFL_EDICTSCALE)) Con_Printf("WARNING: Server is using unsupported RMQ extensions\n"); } else if (protover == DP5_PROTOCOL_VERSION) @@ -3519,17 +3519,23 @@ void CL_ParseStatic (int version) CLFTE_ParseBaseline(&es, false); else CLQW_ParseDelta(&nullentitystate, &es, MSG_ReadShort(), true); - es.number+=MAX_EDICTS; - for (i = 0; i < cl.num_statics; i++) - if (cl_static_entities[i].ent.keynum == es.number) - { - pe->DelinkTrailstate (&cl_static_entities[i].emit); - break; - } + if (!es.number) + i = cl.num_statics++; + else + { + es.number+=MAX_EDICTS; - if (i == cl.num_statics) - cl.num_statics++; + for (i = 0; i < cl.num_statics; i++) + if (cl_static_entities[i].ent.keynum == es.number) + { + pe->DelinkTrailstate (&cl_static_entities[i].emit); + break; + } + + if (i == cl.num_statics) + cl.num_statics++; + } } if (i == cl_max_static_entities) @@ -5184,7 +5190,7 @@ void CLQW_ParseServerMessage (void) if (cmd == svcfte_choosesplitclient) { - SHOWNET(svc_strings[cmd]); + SHOWNET(svc_qwstrings[cmd]); destsplit = MSG_ReadByte() % MAX_SPLITS; cmd = MSG_ReadByte(); @@ -5199,7 +5205,7 @@ void CLQW_ParseServerMessage (void) break; } - SHOWNET(svc_strings[cmd]); + SHOWNET(svc_qwstrings[cmd]); // other commands switch (cmd) @@ -5449,13 +5455,13 @@ void CLQW_ParseServerMessage (void) cl.playerview[destsplit].stats[STAT_SECRETS]++; break; - case svc_updatestat: + case svcqw_updatestatbyte: i = MSG_ReadByte (); j = MSG_ReadByte (); CL_SetStatInt (destsplit, i, j); CL_SetStatFloat (destsplit, i, j); break; - case svc_updatestatlong: + case svcqw_updatestatlong: i = MSG_ReadByte (); j = MSG_ReadLong (); //make qbyte if nq compatability? CL_SetStatInt (destsplit, i, j); @@ -6265,7 +6271,7 @@ void CLNQ_ParseServerMessage (void) cl_lightstyle[i].length = Q_strlen(cl_lightstyle[i].map); break; - case svc_updatestat: + case svcnq_updatestatlong: i = MSG_ReadByte (); j = MSG_ReadLong (); CL_SetStatInt (0, i, j); diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index f42527c2d..9cc623b59 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -1587,7 +1587,7 @@ void CL_ParseTEnt (void) dir[1] = MSG_ReadCoord(); dir[2] = MSG_ReadCoord(); - cnt = MSG_ReadShort(); //count + cnt = (unsigned short)MSG_ReadShort(); //count colour = MSG_ReadByte (); //colour P_RunParticleWeather(pos, pos2, dir, cnt, colour, "rain"); @@ -1612,7 +1612,7 @@ void CL_ParseTEnt (void) dir[1] = MSG_ReadCoord(); dir[2] = MSG_ReadCoord(); - cnt = MSG_ReadShort(); //count + cnt = (unsigned short)MSG_ReadShort(); //count colour = MSG_ReadByte (); //colour P_RunParticleWeather(pos, pos2, dir, cnt, colour, "snow"); diff --git a/engine/client/cl_ui.c b/engine/client/cl_ui.c index c1c58cbdf..d48d2218c 100644 --- a/engine/client/cl_ui.c +++ b/engine/client/cl_ui.c @@ -1533,7 +1533,7 @@ void UI_Stop (void) void UI_Start (void) { int apiversion; - if (qrenderer != QR_OPENGL && qrenderer != QR_DIRECT3D) + if (qrenderer == QR_NONE) return; uivm = VM_Create(NULL, "vm/ui", UI_SystemCallsNative, UI_SystemCallsVM); diff --git a/engine/client/client.h b/engine/client/client.h index ecc027205..e98441355 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -867,6 +867,7 @@ extern kbutton_t in_speed; extern float in_sensitivityscale; void CL_MakeActive(char *gamename); +void CL_UpdateWindowTitle(void); void CL_InitInput (void); void CL_SendCmd (double frametime, qboolean mainloop); diff --git a/engine/client/image.c b/engine/client/image.c index 7086a8f42..deafd3680 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -641,18 +641,22 @@ return NULL; #define PNG_ALLOCATED #endif +#define png_const_infop png_infop +#define png_const_structp png_structp +#define png_const_bytep png_bytep + void (PNGAPI *qpng_error) PNGARG((png_structp png_ptr, png_const_charp error_message)) PSTATIC(png_error); void (PNGAPI *qpng_read_end) PNGARG((png_structp png_ptr, png_infop info_ptr)) PSTATIC(png_read_end); void (PNGAPI *qpng_read_image) PNGARG((png_structp png_ptr, png_bytepp image)) PSTATIC(png_read_image); -png_byte (PNGAPI *qpng_get_bit_depth) PNGARG((png_structp png_ptr, png_infop info_ptr)) PSTATIC(png_get_bit_depth); -png_byte (PNGAPI *qpng_get_channels) PNGARG((png_structp png_ptr, png_infop info_ptr)) PSTATIC(png_get_channels); -png_size_t (PNGAPI *qpng_get_rowbytes) PNGARG((png_structp png_ptr, png_infop info_ptr)) PSTATIC(png_get_rowbytes); +png_byte (PNGAPI *qpng_get_bit_depth) PNGARG((png_const_structp png_ptr, const png_const_infop info_ptr)) PSTATIC(png_get_bit_depth); +png_byte (PNGAPI *qpng_get_channels) PNGARG((png_const_structp png_ptr, png_const_infop info_ptr)) PSTATIC(png_get_channels); +png_size_t (PNGAPI *qpng_get_rowbytes) PNGARG((png_const_structp png_ptr, png_const_infop info_ptr)) PSTATIC(png_get_rowbytes); void (PNGAPI *qpng_read_update_info) PNGARG((png_structp png_ptr, png_infop info_ptr)) PSTATIC(png_read_update_info); void (PNGAPI *qpng_set_strip_16) PNGARG((png_structp png_ptr)) PSTATIC(png_set_strip_16); void (PNGAPI *qpng_set_expand) PNGARG((png_structp png_ptr)) PSTATIC(png_set_expand); void (PNGAPI *qpng_set_gray_to_rgb) PNGARG((png_structp png_ptr)) PSTATIC(png_set_gray_to_rgb); void (PNGAPI *qpng_set_tRNS_to_alpha) PNGARG((png_structp png_ptr)) PSTATIC(png_set_tRNS_to_alpha); -png_uint_32 (PNGAPI *qpng_get_valid) PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 flag)) PSTATIC(png_get_valid); +png_uint_32 (PNGAPI *qpng_get_valid) PNGARG((png_const_structp png_ptr, png_const_infop info_ptr, png_uint_32 flag)) PSTATIC(png_get_valid); void (PNGAPI *qpng_set_expand_gray_1_2_4_to_8) PNGARG((png_structp png_ptr)) PSTATIC(png_set_expand_gray_1_2_4_to_8); void (PNGAPI *qpng_set_filler) PNGARG((png_structp png_ptr, png_uint_32 filler, int flags)) PSTATIC(png_set_filler); void (PNGAPI *qpng_set_palette_to_rgb) PNGARG((png_structp png_ptr)) PSTATIC(png_set_palette_to_rgb); @@ -664,7 +668,7 @@ void (PNGAPI *qpng_set_read_fn) PNGARG((png_structp png_ptr, png_voidp io_ptr, p void (PNGAPI *qpng_destroy_read_struct) PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)) PSTATIC(png_destroy_read_struct); png_infop (PNGAPI *qpng_create_info_struct) PNGARG((png_structp png_ptr)) PSTATIC(png_create_info_struct); png_structp (PNGAPI *qpng_create_read_struct) PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn)) PSTATIC(png_create_read_struct); -int (PNGAPI *qpng_sig_cmp) PNGARG((png_bytep sig, png_size_t start, png_size_t num_to_check)) PSTATIC(png_sig_cmp); +int (PNGAPI *qpng_sig_cmp) PNGARG((png_const_bytep sig, png_size_t start, png_size_t num_to_check)) PSTATIC(png_sig_cmp); void (PNGAPI *qpng_write_end) PNGARG((png_structp png_ptr, png_infop info_ptr)) PSTATIC(png_write_end); void (PNGAPI *qpng_write_image) PNGARG((png_structp png_ptr, png_bytepp image)) PSTATIC(png_write_image); @@ -2230,7 +2234,7 @@ texid_tf GL_LoadTextureDDS(char *iname, unsigned char *buffer, int filesize) if (!qglCompressedTexImage2DARB) return r_nulltex; - texnum = GL_AllocNewTexture(iname, fmtheader.dwWidth, fmtheader.dwHeight); + texnum = GL_AllocNewTexture(iname, fmtheader.dwWidth, fmtheader.dwHeight, 0); GL_MTBind(0, GL_TEXTURE_2D, texnum); datasize = fmtheader.dwPitchOrLinearSize; @@ -2393,7 +2397,7 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags) int j; char *suf[] = { - "rt", "lf", "ft", "bk", "up", "dn", + "rt", "lf", "ft", "bk", "up", "dn", //FIXME: This is inverted and thus wrong "px", "nx", "py", "ny", "pz", "nz", "posx", "negx", "posy", "negy", "posz", "negz" }; diff --git a/engine/client/in_macos.c b/engine/client/in_macos.c index 683f232f7..24264a53f 100644 --- a/engine/client/in_macos.c +++ b/engine/client/in_macos.c @@ -1,57 +1,57 @@ -/* - - Copyright (C) 2001-2002 A Nourai - Copyright (C) 2006 Jacek Piszczek (Mac OSX port) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - See the included (GNU.txt) GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "quakedef.h" - -float mouse_x,mouse_y; -float old_mouse_x,old_mouse_y; - -cvar_t m_filter = SCVARF("m_filter", "1", CVAR_ARCHIVE); - -void IN_Init (void) -{ - Cvar_Register (&m_filter, "input values"); -} - -void IN_ReInit(void) -{ -} - -void IN_Shutdown (void) -{ -} - -void IN_Commands (void) -{ -} -// oportunity for devices to stick commands on the script buffer - -void IN_ModeChanged (void) -{ -} -// called whenever screen dimensions change - -void IN_Move (float *movements, int pnum) -{ - float tx, ty, filterfrac; +/* + + Copyright (C) 2001-2002 A Nourai + Copyright (C) 2006 Jacek Piszczek (Mac OSX port) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the included (GNU.txt) GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "quakedef.h" + +float mouse_x,mouse_y; +float old_mouse_x,old_mouse_y; + +cvar_t m_filter = SCVARF("m_filter", "1", CVAR_ARCHIVE); + +void IN_Init (void) +{ + Cvar_Register (&m_filter, "input values"); +} + +void IN_ReInit(void) +{ +} + +void IN_Shutdown (void) +{ +} + +void IN_Commands (void) +{ +} +// oportunity for devices to stick commands on the script buffer + +void IN_ModeChanged (void) +{ +} +// called whenever screen dimensions change + +void IN_Move (float *movements, int pnum) +{ + float tx, ty, filterfrac; #ifdef PEXT_CSQC if (CSQC_MouseMove(mouse_x, mouse_y, 0)) @@ -60,45 +60,45 @@ void IN_Move (float *movements, int pnum) mouse_y = 0; } #endif - - tx = mouse_x; - ty = mouse_y; - - if (m_filter.value) - { - filterfrac = bound(0, m_filter.value, 1) / 2.0; - mouse_x = (tx * (1 - filterfrac) + old_mouse_x * filterfrac); - mouse_y = (ty * (1 - filterfrac) + old_mouse_y * filterfrac); - } - - old_mouse_x = tx; - old_mouse_y = ty; - - mouse_x *= sensitivity.value; - mouse_y *= sensitivity.value; - - if ((in_strafe.state[pnum] & 1) || (lookstrafe.value && in_mlook.state[pnum])) - { - movements[1] += m_side.value * mouse_x; - } - else - { - cl.playerview[pnum].viewanglechange[YAW] -= m_yaw.value * mouse_x; - } - - if (in_mlook.state[pnum]) - V_StopPitchDrift(pnum); - - if (in_mlook.state[pnum] && !(in_strafe.state[pnum] & 1)) - { - cl.playerview[pnum].viewanglechange[PITCH] += m_pitch.value * mouse_y; - } - else - { - movements[0] -= m_forward.value * mouse_y; - } - - mouse_x = mouse_y = 0.0; -} -// add additional movement on top of the keyboard move cmd - + + tx = mouse_x; + ty = mouse_y; + + if (m_filter.value) + { + filterfrac = bound(0, m_filter.value, 1) / 2.0; + mouse_x = (tx * (1 - filterfrac) + old_mouse_x * filterfrac); + mouse_y = (ty * (1 - filterfrac) + old_mouse_y * filterfrac); + } + + old_mouse_x = tx; + old_mouse_y = ty; + + mouse_x *= sensitivity.value; + mouse_y *= sensitivity.value; + + if ((in_strafe.state[pnum] & 1) || (lookstrafe.value && in_mlook.state[pnum])) + { + movements[1] += m_side.value * mouse_x; + } + else + { + cl.playerview[pnum].viewanglechange[YAW] -= m_yaw.value * mouse_x; + } + + if (in_mlook.state[pnum]) + V_StopPitchDrift(pnum); + + if (in_mlook.state[pnum] && !(in_strafe.state[pnum] & 1)) + { + cl.playerview[pnum].viewanglechange[PITCH] += m_pitch.value * mouse_y; + } + else + { + movements[0] -= m_forward.value * mouse_y; + } + + mouse_x = mouse_y = 0.0; +} +// add additional movement on top of the keyboard move cmd + diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index eee39ece6..f559b9993 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -2193,7 +2193,7 @@ texid_tf Media_UpdateForShader(cin_t *cin) if (!cin->outunchanged) { if (!TEXVALID(cin->texture)) - TEXASSIGN(cin->texture, R_AllocNewTexture("***cin***", cin->outwidth, cin->outheight)); + TEXASSIGN(cin->texture, R_AllocNewTexture("***cin***", cin->outwidth, cin->outheight, IF_NOMIPMAP|IF_NOALPHA)); R_Upload(cin->texture, "cin", cin->outtype, cin->outdata, cin->outpalette, cin->outwidth, cin->outheight, IF_NOMIPMAP|IF_NOALPHA|IF_NOGAMMA); } @@ -3064,7 +3064,7 @@ void TTS_SayUnicodeString(wchar_t *stringtosay) NULL, CLSCTX_SERVER, &IID_ISpVoice, - &sp); + (void*)&sp); if (sp) { @@ -3512,7 +3512,7 @@ void STT_Init_f(void) return; } - if (SUCCEEDED(CoCreateInstance(&CLSID_SpSharedRecoContext, NULL, CLSCTX_SERVER, &IID_SpRecoContext, &stt_recctx))) + if (SUCCEEDED(CoCreateInstance(&CLSID_SpSharedRecoContext, NULL, CLSCTX_SERVER, &IID_SpRecoContext, (void*)&stt_recctx))) { ULONGLONG ev = (((ULONGLONG)1) << 38) | (((ULONGLONG)1) << 30) | (((ULONGLONG)1) << 33); if (SUCCEEDED(stt_recctx->lpVtbl->SetNotifyWindowMessage(stt_recctx, mainwindow, WM_USER, 0, 0))) diff --git a/engine/client/m_multi.c b/engine/client/m_multi.c index f845ce25c..20750d5a9 100644 --- a/engine/client/m_multi.c +++ b/engine/client/m_multi.c @@ -931,4 +931,4 @@ void M_Menu_Network_f (void) }; menu = M_Options_Title(&y, 0); MC_AddBulk(menu, bulk, 16, 200, y); -} \ No newline at end of file +} diff --git a/engine/client/merged.h b/engine/client/merged.h index 8f4f848db..137e4d25f 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -219,10 +219,10 @@ typedef enum backendmode_e BEM_DEPTHDARK, //a quick depth pass. textures used only for alpha test. additive textures still shown as normal. BEM_CREPUSCULAR, //sky is special, everything else completely black BEM_DEPTHNORM, //all opaque stuff drawn using 'depthnorm' shader + BEM_FOG, //drawing a fog volume BEM_LIGHT, //we have a valid light BEM_SMAPLIGHTSPOT, //we have a spot light using a shadowmap - BEM_SMAPLIGHT, //we have a light using a shadowmap - BEM_FOG //drawing a fog volume + BEM_SMAPLIGHT //we have a light using a shadowmap } backendmode_t; typedef struct rendererinfo_s { @@ -238,7 +238,7 @@ typedef struct rendererinfo_s { texid_tf (*IMG_LoadTexture8Pal32) (char *identifier, int width, int height, qbyte *data, qbyte *palette32, unsigned int flags); texid_tf (*IMG_LoadCompressed) (char *name); texid_tf (*IMG_FindTexture) (char *identifier, unsigned int flags); - texid_tf (*IMG_AllocNewTexture) (char *identifier, int w, int h); + texid_tf (*IMG_AllocNewTexture) (char *identifier, int w, int h, unsigned int flags); void (*IMG_Upload) (texid_t tex, char *name, uploadfmt_t fmt, void *data, void *palette, int width, int height, unsigned int flags); void (*IMG_DestroyTexture) (texid_t tex); diff --git a/engine/client/mymad.c b/engine/client/mymad.c deleted file mode 100644 index 7f14ed532..000000000 --- a/engine/client/mymad.c +++ /dev/null @@ -1,246 +0,0 @@ -#ifdef USE_MADLIB - -#define HAVE_CONFIG_H -#define ASO_ZEROCHECK -#ifndef _MBCS -#define _MBCS -#endif - - -# ifdef HAVE_CONFIG_H -# include "libmad/mad.h" -//# include "config.h" -# endif - -//# include "global.h" - -# ifdef HAVE_SYS_TYPES_H -# include -# endif - -# ifdef HAVE_SYS_WAIT_H -# include -# endif - -# ifdef HAVE_UNISTD_H -# include -# endif - -# ifdef HAVE_FCNTL_H -# include -# endif - -# include - -# ifdef HAVE_ERRNO_H -# include -# endif - -# include "libmad/stream.h" -# include "libmad/frame.h" -# include "libmad/synth.h" -# include "libmad/decoder.h" - - - - - - - - - -static -enum mad_flow error_default(void *data, struct mad_stream *stream, - struct mad_frame *frame) -{ - int *bad_last_frame = data; - - switch (stream->error) { - case MAD_ERROR_BADCRC: - if (*bad_last_frame) - mad_frame_mute(frame); - else - *bad_last_frame = 1; - - return MAD_FLOW_IGNORE; - - default: - return MAD_FLOW_CONTINUE; - } -} - - - - -int mymad_reset(struct mad_decoder *decoder) -{ -// enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *); -// void *error_data; - int bad_last_frame = 0; - struct mad_stream *stream; - struct mad_frame *frame; - struct mad_synth *synth; - int result = 0; - - if (decoder->input_func == 0) - return 0; - - decoder->sync = malloc(sizeof(*decoder->sync)); - if (decoder->sync == 0) - return 0; - - stream = &decoder->sync->stream; - frame = &decoder->sync->frame; - synth = &decoder->sync->synth; - - mad_stream_init(stream); - mad_frame_init(frame); - mad_synth_init(synth); - - mad_stream_options(stream, decoder->options); - - return 1; -} - -int mymad_run(struct mad_decoder *decoder) -{ - enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *); - void *error_data; - int bad_last_frame = 0; - struct mad_stream *stream; - struct mad_frame *frame; - struct mad_synth *synth; - - stream = &decoder->sync->stream; - frame = &decoder->sync->frame; - synth = &decoder->sync->synth; - - if (decoder->error_func) { - error_func = decoder->error_func; - error_data = decoder->cb_data; - } - else { - error_func = error_default; - error_data = &bad_last_frame; - } - - if (stream->next_frame >= stream->bufend) - switch (decoder->input_func(decoder->cb_data, stream)) { - case MAD_FLOW_STOP: - goto done; - case MAD_FLOW_BREAK: - goto fail; - case MAD_FLOW_IGNORE: - return 1; - case MAD_FLOW_CONTINUE: - break; - } - -for(;;) -{ - if (decoder->header_func) { - if (mad_header_decode(&frame->header, stream) == -1) { - if (!MAD_RECOVERABLE(stream->error)) - break; - - switch (error_func(error_data, stream, frame)) { - case MAD_FLOW_STOP: - goto done; - case MAD_FLOW_BREAK: - goto fail; - case MAD_FLOW_IGNORE: - case MAD_FLOW_CONTINUE: - default: - return 1; - } - } - - switch (decoder->header_func(decoder->cb_data, &frame->header)) { - case MAD_FLOW_STOP: - goto done; - case MAD_FLOW_BREAK: - goto fail; - case MAD_FLOW_IGNORE: - return 1; - case MAD_FLOW_CONTINUE: - break; - } - } - - if (mad_frame_decode(frame, stream) == -1) { - if (!MAD_RECOVERABLE(stream->error)) - break; - - switch (error_func(error_data, stream, frame)) { - case MAD_FLOW_STOP: - goto done; - case MAD_FLOW_BREAK: - goto fail; - case MAD_FLOW_IGNORE: - break; - case MAD_FLOW_CONTINUE: - default: - return 1; - } - } - else - bad_last_frame = 0; - - if (decoder->filter_func) { - switch (decoder->filter_func(decoder->cb_data, stream, frame)) { - case MAD_FLOW_STOP: - goto done; - case MAD_FLOW_BREAK: - goto fail; - case MAD_FLOW_IGNORE: - return 1; - case MAD_FLOW_CONTINUE: - break; - } - } - - mad_synth_frame(synth, frame); - - if (decoder->output_func) { - switch (decoder->output_func(decoder->cb_data, - &frame->header, &synth->pcm)) { - case MAD_FLOW_STOP: - goto done; - case MAD_FLOW_BREAK: - goto fail; - case MAD_FLOW_IGNORE: - case MAD_FLOW_CONTINUE: - break; - } - } - return 1; - } - - return 0; - -fail: - return 0; - -done: - return 0; -} - -void mymad_finish(struct mad_decoder *decoder) -{ - struct mad_stream *stream; - struct mad_frame *frame; - struct mad_synth *synth; - - stream = &decoder->sync->stream; - frame = &decoder->sync->frame; - synth = &decoder->sync->synth; - - mad_synth_finish(synth); - mad_frame_finish(frame); - mad_stream_finish(stream); - - free(decoder->sync); -} - - -#endif diff --git a/engine/client/p_script.c b/engine/client/p_script.c index 581b8e9e6..d70296069 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -5357,7 +5357,13 @@ static void PScript_DrawParticleTypes (void) { p->die = -1; VectorNormalize(p->vel); - P_RunParticleEffectType(stop, p->vel, type->clipcount/part_type[type->cliptype].count, type->cliptype); + if (type->clipbounce) + { + VectorScale(normal, type->clipbounce, normal); + P_RunParticleEffectType(stop, normal, type->clipcount/part_type[type->cliptype].count, type->cliptype); + } + else + P_RunParticleEffectType(stop, p->vel, type->clipcount/part_type[type->cliptype].count, type->cliptype); continue; } } diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 5c46f415e..48aab5844 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -1401,12 +1401,6 @@ static void QCBUILTIN PF_R_RenderScene(progfuncs_t *prinst, struct globalvars_s GL_Set2D (false); } #endif -#ifdef D3DQUAKE - if (qrenderer == QR_DIRECT3D) - { - D3D9_Set2D (); - } -#endif vid.recalc_refdef = 1; @@ -3329,40 +3323,6 @@ static void QCBUILTIN PF_rotatevectorsbytag (progfuncs_t *prinst, struct globalv VectorCopy(srcorg, retorg); } -static void QCBUILTIN PF_frameforname (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int modelindex = G_FLOAT(OFS_PARM0); - char *str = PF_VarString(prinst, 1, pr_globals); - model_t *mod = CSQC_GetModelForIndex(modelindex); - - if (mod && Mod_FrameForName) - G_FLOAT(OFS_RETURN) = Mod_FrameForName(mod, str); - else - G_FLOAT(OFS_RETURN) = -1; -} -static void QCBUILTIN PF_frameduration (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int modelindex = G_FLOAT(OFS_PARM0); - int frameno = G_FLOAT(OFS_PARM1); - model_t *mod = CSQC_GetModelForIndex(modelindex); - - if (mod && Mod_GetFrameDuration) - G_FLOAT(OFS_RETURN) = Mod_GetFrameDuration(mod, frameno); - else - G_FLOAT(OFS_RETURN) = 0; -} -static void QCBUILTIN PF_skinforname (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int modelindex = G_FLOAT(OFS_PARM0); - char *str = PF_VarString(prinst, 1, pr_globals); - model_t *mod = CSQC_GetModelForIndex(modelindex); - - - if (mod && Mod_SkinForName) - G_FLOAT(OFS_RETURN) = Mod_SkinForName(mod, str); - else - G_FLOAT(OFS_RETURN) = -1; -} static void QCBUILTIN PF_shaderforname (progfuncs_t *prinst, struct globalvars_s *pr_globals) { char *str = PR_GetStringOfs(prinst, OFS_PARM0); @@ -4343,11 +4303,8 @@ static struct { {"skel_ragupdate", PF_skel_ragedit, 281},// (FTE_QC_RAGDOLL) {"skel_mmap", PF_skel_mmap, 282},// (FTE_QC_RAGDOLL) {"skel_set_bone_world", PF_skel_set_bone_world, 283}, - - {"memalloc", PF_memalloc, 384}, - {"memfree", PF_memfree, 385}, - {"memcpy", PF_memcpy, 386}, - {"memset", PF_memset, 387}, + {"frametoname", PF_frametoname, 284},//string(float modidx, float framenum) frametoname + {"skintoname", PF_skintoname, 285},//string(float modidx, float skin) skintoname //300 {"clearscene", PF_R_ClearScene, 300}, // #300 void() clearscene (EXT_CSQC) @@ -4457,6 +4414,11 @@ static struct { {"dynamiclight_set", PF_R_DynamicLight_Set, 373}, {"particleeffectquery", PF_cs_particleeffectquery, 374}, + {"memalloc", PF_memalloc, 384}, + {"memfree", PF_memfree, 385}, + {"memcpy", PF_memcpy, 386}, + {"memset", PF_memset, 387}, + //400 {"copyentity", PF_cs_copyentity, 400}, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY) {"setcolors", PF_NoCSQC, 401}, // #401 void(entity cl, float colours) setcolors (DP_SV_SETCOLOR) (don't implement) @@ -4653,6 +4615,9 @@ static struct { {"sprintf", PF_sprintf, 627}, + {"getsurfacenumtriangles",PF_getsurfacenumtriangles,628}, + {"getsurfacetriangle", PF_getsurfacetriangle, 629}, + {NULL} }; @@ -4831,6 +4796,8 @@ void CSQC_Shutdown(void) { if (csqcprogs) { + skel_reset(csqcprogs); + search_close_progs(csqcprogs, false); PR_fclose_progs(csqcprogs); @@ -4990,9 +4957,12 @@ qboolean CSQC_Init (qboolean anycsqc, unsigned int checksum) csprogs_checksum = checksum; csqc_usinglistener = false; + csqc_singlecheats = cls.demoplayback; + if (atoi(Info_ValueForKey(cl.serverinfo, "*cheats"))) + csqc_singlecheats = true; #ifndef CLIENTONLY - if ((sv.state == ss_active && sv.allocated_client_slots == 1) || atoi(Info_ValueForKey(cl.serverinfo, "*cheats"))) + else if (sv.state == ss_active && sv.allocated_client_slots == 1) csqc_singlecheats = true; #endif @@ -5017,7 +4987,6 @@ qboolean CSQC_Init (qboolean anycsqc, unsigned int checksum) } csqc_deprecated_warned = false; - skel_reset(csqcprogs); memset(cl.model_csqcname, 0, sizeof(cl.model_csqcname)); memset(cl.model_csqcprecache, 0, sizeof(cl.model_csqcprecache)); @@ -5099,11 +5068,6 @@ qboolean CSQC_Init (qboolean anycsqc, unsigned int checksum) if (loaded) Con_Printf(CON_WARNING "Running outdated or unknown csprogs.dat version\n"); } - if (setjmp(csqc_abort)) - { - CSQC_Shutdown(); - return false; - } if (csqc_singlecheats) { diff --git a/engine/client/pr_skelobj.c b/engine/client/pr_skelobj.c index 15b282e1b..5cbd26d2e 100644 --- a/engine/client/pr_skelobj.c +++ b/engine/client/pr_skelobj.c @@ -60,9 +60,11 @@ enum }; typedef struct { - int jointo; /*multiple of 12*/ + int ownerent; /*multiple of 12*/ int flags; - vec3_t vel; + + float moment[12]; + float matrix[12]; } body_t; #endif @@ -236,6 +238,7 @@ doll_t *rag_loaddoll(model_t *mod, char *fname) void skel_integrate(progfuncs_t *prinst, skelobject_t *sko, skelobject_t *skelobjsrc, float ft, float mmat[12]) { +#if 0 trace_t t; vec3_t npos, opos, wnpos, wopos; vec3_t move; @@ -336,7 +339,7 @@ void skel_integrate(progfuncs_t *prinst, skelobject_t *sko, skelobject_t *skelob /*FIXME*/ } } - +#endif /*debugging*/ #if 0 /*draw points*/ @@ -355,12 +358,20 @@ void skel_integrate(progfuncs_t *prinst, skelobject_t *sko, skelobject_t *skelob /*destroys all skeletons*/ void skel_reset(progfuncs_t *prinst) { - while (numskelobjectsused > 0) + int i; + + for (i = 0; i < numskelobjectsused; i++) { - numskelobjectsused--; - skelobjects[numskelobjectsused].numbones = 0; - skelobjects[numskelobjectsused].inuse = false; + if (skelobjects[i].world = prinst->parms->user) + { + skelobjects[i].numbones = 0; + skelobjects[i].inuse = false; + skelobjects[i].bonematrix = NULL; + } } + + while (numskelobjectsused && !skelobjects[numskelobjectsused-1].inuse) + numskelobjectsused--; } /*deletes any skeletons marked for deletion*/ @@ -391,24 +402,26 @@ skelobject_t *skel_get(progfuncs_t *prinst, int skelidx, int bonecount) for (skelidx = 0; skelidx < numskelobjectsused; skelidx++) { - if (!skelobjects[skelidx].inuse && skelobjects[skelidx].numbones == bonecount) + if (!skelobjects[skelidx].inuse && skelobjects[skelidx].numbones == bonecount && skelobjects[skelidx].world == prinst->parms->user) return &skelobjects[skelidx]; } - for (skelidx = 0; skelidx <= numskelobjectsused; skelidx++) + for (skelidx = 0; skelidx <= MAX_SKEL_OBJECTS; skelidx++) { - if (!skelobjects[skelidx].inuse && !skelobjects[skelidx].numbones) + if (!skelobjects[skelidx].inuse && + (!skelobjects[skelidx].numbones || skelobjects[skelidx].numbones == bonecount) && + (!skelobjects[skelidx].world || skelobjects[skelidx].world == prinst->parms->user)) { - skelobjects[skelidx].numbones = bonecount; - /*so bone matrix list can be mmapped some day*/ - skelobjects[skelidx].bonematrix = (float*)PR_AddString(prinst, "", sizeof(float)*12*bonecount); - skelobjects[skelidx].world = prinst->parms->user; - if (skelidx <= numskelobjectsused) + if (!skelobjects[skelidx].numbones) { - numskelobjectsused = skelidx + 1; - skelobjects[skelidx].model = NULL; - skelobjects[skelidx].inuse = 1; + skelobjects[skelidx].numbones = bonecount; + skelobjects[skelidx].bonematrix = (float*)PR_AddString(prinst, "", sizeof(float)*12*bonecount); } + skelobjects[skelidx].world = prinst->parms->user; + if (numskelobjectsused == skelidx) + numskelobjectsused = skelidx + 1; + skelobjects[skelidx].model = NULL; + skelobjects[skelidx].inuse = 1; return &skelobjects[skelidx]; } } @@ -493,8 +506,8 @@ void QCBUILTIN PF_skel_ragedit(progfuncs_t *prinst, struct globalvars_s *pr_glob sko->numbodies = doll->numbodies; sko->body = malloc(sko->numbodies * sizeof(*sko->body)); memset(sko->body, 0, sko->numbodies * sizeof(*sko->body)); - for (i = 0; i < sko->numbodies; i++) - sko->body[i].jointo = doll->body[i].bone * 12; +// for (i = 0; i < sko->numbodies; i++) +// sko->body[i].jointo = doll->body[i].bone * 12; } psko = skel_get(prinst, parentskel, 0); @@ -1057,5 +1070,77 @@ void QCBUILTIN PF_gettagindex (progfuncs_t *prinst, struct globalvars_s *pr_glob else G_FLOAT(OFS_RETURN) = 0; } + +const char *Mod_FrameNameForNum(model_t *model, int num); +const char *Mod_SkinNameForNum(model_t *model, int num); + +//string(float modidx, float framenum) frametoname +void QCBUILTIN PF_frametoname (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + world_t *w = prinst->parms->user; + unsigned int modelindex = G_FLOAT(OFS_PARM0); + unsigned int skinnum = G_FLOAT(OFS_PARM1); + model_t *mod = w->Get_CModel(w, modelindex); + const char *n = Mod_FrameNameForNum(mod, skinnum); + + if (n) + RETURN_TSTRING(n); + else + G_INT(OFS_RETURN) = 0; //null string (which is also empty in qc) +} + +//string(float modidx, float skinnum) skintoname +void QCBUILTIN PF_skintoname (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + world_t *w = prinst->parms->user; + unsigned int modelindex = G_FLOAT(OFS_PARM0); + unsigned int skinnum = G_FLOAT(OFS_PARM1); + model_t *mod = w->Get_CModel(w, modelindex); + const char *n = Mod_SkinNameForNum(mod, skinnum); + + if (n) + RETURN_TSTRING(n); + else + G_INT(OFS_RETURN) = 0; //null string (which is also empty in qc) +} + +void QCBUILTIN PF_frameforname (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + world_t *w = prinst->parms->user; + unsigned int modelindex = G_FLOAT(OFS_PARM0); + char *str = PF_VarString(prinst, 1, pr_globals); + model_t *mod = w->Get_CModel(w, modelindex); + + if (mod && Mod_FrameForName) + G_FLOAT(OFS_RETURN) = Mod_FrameForName(mod, str); + else + G_FLOAT(OFS_RETURN) = -1; +} +void QCBUILTIN PF_frameduration (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + world_t *w = prinst->parms->user; + unsigned int modelindex = G_FLOAT(OFS_PARM0); + unsigned int framenum = G_FLOAT(OFS_PARM1); + model_t *mod = w->Get_CModel(w, modelindex); + + if (mod && Mod_GetFrameDuration) + G_FLOAT(OFS_RETURN) = Mod_GetFrameDuration(mod, framenum); + else + G_FLOAT(OFS_RETURN) = 0; +} +void QCBUILTIN PF_skinforname (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ +#ifndef SERVERONLY + world_t *w = prinst->parms->user; + unsigned int modelindex = G_FLOAT(OFS_PARM0); + char *str = PF_VarString(prinst, 1, pr_globals); + model_t *mod = w->Get_CModel(w, modelindex); + + if (mod && Mod_SkinForName) + G_FLOAT(OFS_RETURN) = Mod_SkinForName(mod, str); + else +#endif + G_FLOAT(OFS_RETURN) = -1; +} #endif diff --git a/engine/client/r_2d.c b/engine/client/r_2d.c index 3d87663df..00ed735db 100644 --- a/engine/client/r_2d.c +++ b/engine/client/r_2d.c @@ -109,6 +109,13 @@ void R2D_Shutdown(void) cl_maxstrisvert = 0; cl_numstris = 0; cl_maxstris = 0; + + if (font_conchar) + Font_Free(font_conchar); + font_conchar = NULL; + if (font_tiny) + Font_Free(font_tiny); + font_tiny = NULL; } /* @@ -446,7 +453,7 @@ void R2D_TransPicTranslate (int x, int y, int width, int height, qbyte *pic, qby if (!TEXVALID(translate_texture)) { - translate_texture = R_AllocNewTexture("***translatedpic***", 64, 64); + translate_texture = R_AllocNewTexture("***translatedpic***", 64, 64, 0); translate_shader = R_RegisterShader("translatedpic", "{\n" "if $nofixed\n" "[\n" @@ -979,7 +986,7 @@ void R2D_Crosshair_Update(void) c = c % (sizeof(crosshair_pixels) / (CS_HEIGHT*sizeof(*crosshair_pixels))); if (!TEXVALID(ch_int_texture)) - ch_int_texture = R_AllocNewTexture("***crosshair***", CS_WIDTH, CS_HEIGHT); + ch_int_texture = R_AllocNewTexture("***crosshair***", CS_WIDTH, CS_HEIGHT, 0); shader_crosshair->defaulttextures.base = ch_int_texture; Q_memset(crossdata, 0, sizeof(crossdata)); diff --git a/engine/client/r_partset.c b/engine/client/r_partset.c index 56d74489e..28a13ea48 100644 --- a/engine/client/r_partset.c +++ b/engine/client/r_partset.c @@ -1322,7 +1322,7 @@ char *particle_set_high = "step 5\n" "scale 30\n" "alpha 0.2\n" -"die 1.5\n" +"die 0.75\n" //diesubrand 10.25 "randomvel 0.2\n" "rgb 5 5 5\n" diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index cf6cb273d..3dc710fe1 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -587,7 +587,10 @@ static void Surf_BuildDeluxMap (msurface_t *surf, qbyte *dest) vec_t *bnorm; vec3_t temp; - int stride = LMBLOCK_WIDTH*3; + int stride = LMBLOCK_WIDTH*lightmap_bytes; + + if (!dest) + return; smax = (surf->extents[0]>>4)+1; tmax = (surf->extents[1]>>4)+1; @@ -670,7 +673,7 @@ store: // bound, invert, and shift - stride -= smax*3; + stride -= smax*lightmap_bytes; bnorm = blocknormals[0]; for (i=0 ; ilightmaptexturenums[0]<0) @@ -1219,10 +1222,11 @@ dynamic: if ((theRect->h + theRect->t) < (fa->light_t[0] + tmax)) theRect->h = (fa->light_t[0]-theRect->t)+tmax; - if (r_deluxemapping.ival) + if (lm->hasdeluxe) { - lm->deluxmodified = true; - theRect = &lm->deluxrectchange; + dlm = lightmap[fa->lightmaptexturenums[0]+1]; + dlm->modified = true; + theRect = &dlm->rectchange; if (fa->light_t[0] < theRect->t) { if (theRect->h) theRect->h += theRect->t - fa->light_t[0]; @@ -1239,8 +1243,8 @@ dynamic: if ((theRect->h + theRect->t) < (fa->light_t[0] + tmax)) theRect->h = (fa->light_t[0]-theRect->t)+tmax; - luxbase = lm->deluxmaps; - luxbase += fa->light_t[0] * lm->width * 3 + fa->light_s[0] * 3; + luxbase = dlm->lightmaps; + luxbase += fa->light_t[0] * dlm->width * lightmap_bytes + fa->light_s[0] * lightmap_bytes; } else luxbase = NULL; @@ -1262,7 +1266,7 @@ void Surf_RenderAmbientLightmaps (msurface_t *fa, int ambient) stmap *stainbase; glRect_t *theRect; int smax, tmax; - lightmapinfo_t *lm; + lightmapinfo_t *lm, *dlm; if (!fa->mesh) return; @@ -1306,10 +1310,11 @@ dynamic: if ((theRect->h + theRect->t) < (fa->light_t[0] + tmax)) theRect->h = (fa->light_t[0]-theRect->t)+tmax; - if (r_deluxemapping.ival) + if (lm->hasdeluxe) { - lm->deluxmodified = true; - theRect = &lm->deluxrectchange; + dlm = lightmap[fa->lightmaptexturenums[0]+1]; + lm->modified = true; + theRect = &lm->rectchange; if (fa->light_t[0] < theRect->t) { if (theRect->h) @@ -1328,8 +1333,8 @@ dynamic: if ((theRect->h + theRect->t) < (fa->light_t[0] + tmax)) theRect->h = (fa->light_t[0]-theRect->t)+tmax; - luxbase = lm->deluxmaps; - luxbase += fa->light_t[0] * lm->width * 3 + fa->light_s[0] * 3; + luxbase = dlm->lightmaps; + luxbase += fa->light_t[0] * dlm->width * lightmap_bytes + fa->light_s[0] * lightmap_bytes; } else luxbase = NULL; @@ -2231,7 +2236,7 @@ void Surf_DrawWorld (void) #ifdef MAP_PROC if (cl.worldmodel->fromgame == fg_doom3) { - vis = D3_CalcVis(cl.worldmodel, r_refdef.vieworg); + vis = D3_CalcVis(cl.worldmodel, r_origin); } else #endif @@ -2258,7 +2263,7 @@ void Surf_DrawWorld (void) { vis = R_MarkLeaves_Q1 (); if (!(r_novis.ival & 2)) - VectorCopy (r_refdef.vieworg, modelorg); + VectorCopy (r_origin, modelorg); if (r_refdef.useperspective) Surf_RecursiveWorldNode (cl.worldmodel->nodes, 0x1f); @@ -2286,207 +2291,6 @@ void Surf_DrawWorld (void) } } -/* -============================================================================= - - LIGHTMAP ALLOCATION - -============================================================================= -*/ -#if 0//def TERRAIN -// returns a texture number and the position inside it -int Surf_LM_AllocBlock (int w, int h, int *x, int *y, shader_t *shader) -{ - int i, j; - int best, best2; - int texnum; - - for (texnum=0 ; ; texnum++) - { - if (texnum == numlightmaps) //allocate 4 more lightmap slots. not much memory usage, but we don't want any caps here. - { - lightmap = BZ_Realloc(lightmap, sizeof(*lightmap)*(numlightmaps+4)); - lightmap[numlightmaps+0] = NULL; - lightmap[numlightmaps+1] = NULL; - lightmap[numlightmaps+2] = NULL; - lightmap[numlightmaps+3] = NULL; - -// lightmap_textures = BZ_Realloc(lightmap_textures, sizeof(*lightmap_textures)*(numlightmaps+4)); -// memset(lightmap_textures+numlightmaps, 0, sizeof(*lightmap_textures)*(4)); - -// deluxmap_textures = BZ_Realloc(deluxmap_textures, sizeof(*deluxmap_textures)*(numlightmaps+4)); -// memset(deluxmap_textures+numlightmaps, 0, sizeof(*deluxmap_textures)*(4)); - numlightmaps+=4; - } - if (!lightmap[texnum]) - { - lightmap[texnum] = Z_Malloc(sizeof(*lightmap[texnum])); - lightmap[texnum]->modified = true; -// lightmap[texnum]->shader = shader; - lightmap[texnum]->external = true; - // reset stainmap since it now starts at 255 - memset(lightmap[texnum]->stainmaps, 255, LMBLOCK_WIDTH*LMBLOCK_HEIGHT*3*sizeof(stmap)); - - //clear out the deluxmaps incase there is none on the map. - for (j = 0; j < LMBLOCK_WIDTH*LMBLOCK_HEIGHT*3; j+=3) - { - lightmap[texnum]->deluxmaps[j+0] = 128; - lightmap[texnum]->deluxmaps[j+1] = 128; - lightmap[texnum]->deluxmaps[j+2] = 255; - } - } - - /*not required, but using one lightmap per texture can result in better texture unit switching*/ -// if (lightmap[texnum]->shader != shader) -// continue; - - if (lightmap[texnum]->external) - { - TEXASSIGN(lightmap[texnum]->lightmap_texture, R_AllocNewTexture("***lightmap***", LMBLOCK_WIDTH, LMBLOCK_HEIGHT)); - TEXASSIGN(lightmap[texnum]->deluxmap_texture, R_AllocNewTexture("***deluxmap***", LMBLOCK_WIDTH, LMBLOCK_HEIGHT)); - lightmap[texnum]->external = false; - } - - best = LMBLOCK_HEIGHT; - - for (i = 0; i <= LMBLOCK_WIDTH - w; i++) - { - best2 = 0; - - for (j=0; j < w; j++) - { - if (lightmap[texnum]->allocated[i+j] >= best) - break; - if (lightmap[texnum]->allocated[i+j] > best2) - best2 = lightmap[texnum]->allocated[i+j]; - } - if (j == w) - { // this is a valid spot - *x = i; - *y = best = best2; - } - } - - if (best + h > LMBLOCK_HEIGHT) - continue; - - for (i=0; i < w; i++) - lightmap[texnum]->allocated[*x + i] = best + h; - - return texnum; - } - - Sys_Error ("AllocBlock: full"); - return 0; -} -#endif - -#if 0 - -//quake3 maps have their lightmaps in gl style already. -//rather than forgetting that and redoing it, let's just keep the data. -static int Surf_LM_FillBlock (int texnum, int w, int h, int x, int y) -{ - int i, l; - while (texnum >= numlightmaps) //allocate 4 more lightmap slots. not much memory usage, but we don't want any caps here. - { - lightmap = BZ_Realloc(lightmap, sizeof(*lightmap)*(numlightmaps+4)); - lightmap[numlightmaps+0] = NULL; - lightmap[numlightmaps+1] = NULL; - lightmap[numlightmaps+2] = NULL; - lightmap[numlightmaps+3] = NULL; - - lightmap_textures = BZ_Realloc(lightmap_textures, sizeof(*lightmap_textures)*(numlightmaps+4)); - memset(lightmap_textures+numlightmaps, 0, sizeof(*lightmap_textures)*(4)); - - deluxmap_textures = BZ_Realloc(deluxmap_textures, sizeof(*deluxmap_textures)*(numlightmaps+4)); - memset(deluxmap_textures+numlightmaps, 0, sizeof(*deluxmap_textures)*(4)); - numlightmaps+=4; - } - for (i = texnum; i >= 0; i--) - { - if (!lightmap[i]) - { - lightmap[i] = BZ_Malloc(sizeof(*lightmap[i])); - lightmap[i]->modified = true; - lightmap[i]->external = true; - for (l=0 ; lallocated[l] = LMBLOCK_HEIGHT; - } - lightmap[i]->rectchange.l = 0; - lightmap[i]->rectchange.t = 0; - lightmap[i]->rectchange.w = LMBLOCK_WIDTH; - lightmap[i]->rectchange.h = LMBLOCK_HEIGHT; - - //clear out the deluxmaps incase there is none on the map. - for (l = 0; l < LMBLOCK_WIDTH*LMBLOCK_HEIGHT*3; l+=3) - { - lightmap[i]->deluxmaps[l+0] = 0; - lightmap[i]->deluxmaps[l+1] = 0; - lightmap[i]->deluxmaps[l+2] = 255; - } - - if (cl.worldmodel->lightdata) - { - if (lightmap[i]->external) - { - TEXASSIGN(lightmap_textures[i], R_AllocNewTexture("***lightmap***", LMBLOCK_WIDTH, LMBLOCK_HEIGHT)); - TEXASSIGN(deluxmap_textures[i], R_AllocNewTexture("***deluxmap***", LMBLOCK_WIDTH, LMBLOCK_HEIGHT)); - lightmap[i]->external = false; - } - if (lightmap_bytes == 4) - { - int j; - if (lightmap_bgra) - { - for (j = 0; j < LMBLOCK_WIDTH*LMBLOCK_HEIGHT; j++) - { - lightmap[i]->lightmaps[(j<<2)+0] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_WIDTH*LMBLOCK_HEIGHT*i))[2]; - lightmap[i]->lightmaps[(j<<2)+1] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_WIDTH*LMBLOCK_HEIGHT*i))[1]; - lightmap[i]->lightmaps[(j<<2)+2] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_WIDTH*LMBLOCK_HEIGHT*i))[0]; - lightmap[i]->lightmaps[(j<<2)+3] = 255; - } - } - else - { - for (j = 0; j < LMBLOCK_WIDTH*LMBLOCK_HEIGHT; j++) - { - lightmap[i]->lightmaps[(j<<2)+0] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_WIDTH*LMBLOCK_HEIGHT*i))[0]; - lightmap[i]->lightmaps[(j<<2)+1] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_WIDTH*LMBLOCK_HEIGHT*i))[1]; - lightmap[i]->lightmaps[(j<<2)+2] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_WIDTH*LMBLOCK_HEIGHT*i))[2]; - lightmap[i]->lightmaps[(j<<2)+3] = 255; - } - } - } - else - { - /*BUG: assumes RGB. if its BGR then wrong colours, but whys that going to happen*/ - memcpy(lightmap[i]->lightmaps, cl.worldmodel->lightdata+3*LMBLOCK_WIDTH*LMBLOCK_HEIGHT*i, LMBLOCK_WIDTH*LMBLOCK_HEIGHT*3); - } - } - else - { - char basename[MAX_QPATH]; - //maybe someone screwed with my lightmap... - memset(lightmap[i]->lightmaps, 255, LMBLOCK_WIDTH*LMBLOCK_HEIGHT*3); - - COM_StripExtension(cl.worldmodel->name, basename, sizeof(basename)); - if (!lightmap[i]->external) - R_DestroyTexture(lightmap_textures[i]); - lightmap[i]->external = true; - lightmap_textures[i] = R_LoadHiResTexture(va("%s/lm_%04i", basename, i), NULL, IF_NOALPHA|IF_NOGAMMA); - lightmap[i]->modified = false; - } - - } - else - break; - } - return texnum; -} -#endif - unsigned int Surf_CalcMemSize(msurface_t *surf) { if (surf->mesh) @@ -2501,169 +2305,6 @@ unsigned int Surf_CalcMemSize(msurface_t *surf) (sizeof(vecV_t)+sizeof(vec2_t)*2+sizeof(vec3_t)*3+sizeof(vec4_t))*surf->numedges; } -#if 0 -/* -================ -BuildSurfaceDisplayList -FIXME: this is probably misplaced -lightmaps are already built by the time this is called -================ -*/ -void Surf_BuildSurfaceDisplayList (model_t *model, msurface_t *fa, void **mem) -{ - int i, lindex, lnumverts; - medge_t *pedges, *r_pedge; - int vertpage; - float *vec; - float s, t, d; - mesh_t *mesh; - -// reconstruct the polygon - pedges = model->edges; - lnumverts = fa->numedges; - vertpage = 0; - - if (!lnumverts) - { - fa->mesh = &nullmesh; - return; - } - - fa->mesh = mesh = *mem; - mesh->xyz_array = (vecV_t*)(mesh + 1); - mesh->normals_array = (vec3_t*)(mesh->xyz_array + lnumverts); - mesh->snormals_array = (vec3_t*)(mesh->normals_array + lnumverts); - mesh->tnormals_array = (vec3_t*)(mesh->snormals_array + lnumverts); - mesh->st_array = (vec2_t*)(mesh->tnormals_array + lnumverts); - mesh->lmst_array = (vec2_t*)(mesh->st_array + lnumverts); - mesh->colors4f_array = (vec4_t*)(mesh->lmst_array + lnumverts); - mesh->indexes = (index_t*)(mesh->colors4f_array + lnumverts); - *mem = (void*)(mesh->indexes + (lnumverts-2)*3); - - mesh->numindexes = (lnumverts-2)*3; - mesh->numvertexes = lnumverts; - mesh->istrifan = true; - - for (i=0 ; iindexes[i*3] = 0; - mesh->indexes[i*3+1] = i+1; - mesh->indexes[i*3+2] = i+2; - } - - for (i=0 ; isurfedges[fa->firstedge + i]; - - if (lindex > 0) - { - r_pedge = &pedges[lindex]; - vec = model->vertexes[r_pedge->v[0]].position; - } - else - { - r_pedge = &pedges[-lindex]; - vec = model->vertexes[r_pedge->v[1]].position; - } - - s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; - t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; - - VectorCopy (vec, mesh->xyz_array[i]); - mesh->st_array[i][0] = s/fa->texinfo->texture->width; - mesh->st_array[i][1] = t/fa->texinfo->texture->height; - - s -= fa->texturemins[0]; - s += fa->light_s*16; - s += 8; - s /= LMBLOCK_WIDTH*16; - - t -= fa->texturemins[1]; - t += fa->light_t*16; - t += 8; - t /= LMBLOCK_HEIGHT*16; - - mesh->lmst_array[i][0] = s; - mesh->lmst_array[i][1] = t; - - if (fa->flags & SURF_PLANEBACK) - VectorNegate(fa->plane->normal, mesh->normals_array[i]); - else - VectorCopy(fa->plane->normal, mesh->normals_array[i]); - VectorNegate(fa->texinfo->vecs[0], mesh->snormals_array[i]); - VectorNegate(fa->texinfo->vecs[1], mesh->tnormals_array[i]); - d = -DotProduct(mesh->normals_array[i], mesh->snormals_array[i]); - VectorMA(mesh->snormals_array[i], d, mesh->normals_array[i], mesh->snormals_array[i]); - d = -DotProduct(mesh->normals_array[i], mesh->tnormals_array[i]); - VectorMA(mesh->tnormals_array[i], d, mesh->normals_array[i], mesh->tnormals_array[i]); - VectorNormalize(mesh->snormals_array[i]); - VectorNormalize(mesh->tnormals_array[i]); - - mesh->colors4f_array[i][0] = 1; - mesh->colors4f_array[i][1] = 1; - mesh->colors4f_array[i][2] = 1; - mesh->colors4f_array[i][3] = 1; - } -} -#endif - -#if 0 -/* -======================== -GL_CreateSurfaceLightmap -======================== -*/ -void Surf_CreateSurfaceLightmap (msurface_t *surf, int shift) -{ - int smax, tmax; - qbyte *base, *luxbase; stmap *stainbase; - - if (surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB)) - surf->lightmaptexturenum = -1; - if (surf->texinfo->flags & TEX_SPECIAL) - surf->lightmaptexturenum = -1; - - //surfaces with lightmaps that do not animate, supposedly - if (surf->texinfo->flags & (TI_SKY|TI_TRANS33|TI_TRANS66|TI_WARP)) - surf->lightmaptexturenum = -1; - - if (surf->lightmaptexturenum<0) - { - surf->lightmaptexturenum = -1; - return; - } - - smax = (surf->extents[0]>>4)+1; - tmax = (surf->extents[1]>>4)+1; - - if (smax > LMBLOCK_WIDTH || tmax > LMBLOCK_HEIGHT || smax < 0 || tmax < 0) - { //whoa, buggy. - surf->lightmaptexturenum = -1; - return; - } - - if (currentmodel->fromgame == fg_quake3) - { - Surf_LM_FillBlock(surf->lightmaptexturenum, smax, tmax, surf->light_s, surf->light_t); - return; - } - else - surf->lightmaptexturenum = Surf_LM_AllocBlock (smax, tmax, &surf->light_s, &surf->light_t, surf->texinfo->texture->shader); - base = lightmap[surf->lightmaptexturenum]->lightmaps; - base += (surf->light_t * LMBLOCK_WIDTH + surf->light_s) * lightmap_bytes; - - luxbase = lightmap[surf->lightmaptexturenum]->deluxmaps; - luxbase += (surf->light_t * LMBLOCK_WIDTH + surf->light_s) * 3; - - stainbase = lightmap[surf->lightmaptexturenum]->stainmaps; - stainbase += (surf->light_t * LMBLOCK_WIDTH + surf->light_s) * 3; - - Surf_BuildLightMap (surf, base, luxbase, stainbase, shift, r_ambient.value*255); -} -#endif - - - void Surf_DeInit(void) { int i; @@ -2672,10 +2313,9 @@ void Surf_DeInit(void) { if (!lightmap[i]) break; - if (lightmap[i]->external) + if (!lightmap[i]->external) { R_DestroyTexture(lightmap[i]->lightmap_texture); - R_DestroyTexture(lightmap[i]->deluxmap_texture); } BZ_Free(lightmap[i]); lightmap[i] = NULL; @@ -2717,13 +2357,14 @@ void Surf_LightmapMode(void) switch(qrenderer) { - case QR_DIRECT3D: #ifdef D3DQUAKE + case QR_DIRECT3D9: + case QR_DIRECT3D11: /*always bgra, hope your card supports it*/ lightmap_bytes = 4; lightmap_bgra = true; -#endif break; +#endif case QR_OPENGL: #ifdef GLQUAKE /*favour bgra if the gpu supports it, otherwise use rgb only if it'll be used*/ @@ -2748,16 +2389,16 @@ void Surf_LightmapMode(void) lightmap_bytes = 1; break; #endif - case QR_NONE: + default: break; } } //needs to be followed by a BE_UploadAllLightmaps at some point -int Surf_NewLightmaps(int count, int width, int height) +int Surf_NewLightmaps(int count, int width, int height, qboolean deluxe) { int first = numlightmaps; - int i, k; + int i; if (!count) return -1; @@ -2768,29 +2409,74 @@ int Surf_NewLightmaps(int count, int width, int height) { i--; - lightmap[i] = Z_Malloc(sizeof(*lightmap[i]) + (sizeof(qbyte)*8 + sizeof(stmap)*3)*width*height); - lightmap[i]->width = width; - lightmap[i]->height = height; - lightmap[i]->lightmaps = (qbyte*)(lightmap[i]+1); - lightmap[i]->deluxmaps = (qbyte*)(lightmap[i]->lightmaps+4*width*height); - lightmap[i]->stainmaps = (stmap*)(lightmap[i]->deluxmaps+4*width*height); + if (deluxe && ((i - numlightmaps)&1)) + { + lightmap[i] = Z_Malloc(sizeof(*lightmap[i]) + (sizeof(qbyte)*8)*width*height); + lightmap[i]->width = width; + lightmap[i]->height = height; + lightmap[i]->lightmaps = (qbyte*)(lightmap[i]+1); + lightmap[i]->stainmaps = NULL; + lightmap[i]->hasdeluxe = false; + } + else + { + lightmap[i] = Z_Malloc(sizeof(*lightmap[i]) + (sizeof(qbyte)*8 + sizeof(stmap)*3)*width*height); + lightmap[i]->width = width; + lightmap[i]->height = height; + lightmap[i]->lightmaps = (qbyte*)(lightmap[i]+1); + lightmap[i]->stainmaps = (stmap*)(lightmap[i]->lightmaps+4*width*height); + lightmap[i]->hasdeluxe = deluxe; + } + lightmap[i]->rectchange.l = 0; + lightmap[i]->rectchange.t = 0; + lightmap[i]->rectchange.h = LMBLOCK_WIDTH; + lightmap[i]->rectchange.w = LMBLOCK_WIDTH; + + + lightmap[i]->lightmap_texture = r_nulltex; lightmap[i]->modified = true; // lightmap[i]->shader = NULL; lightmap[i]->external = false; // reset stainmap since it now starts at 255 - memset(lightmap[i]->stainmaps, 255, width*height*3*sizeof(stmap)); + if (lightmap[i]->stainmaps) + memset(lightmap[i]->stainmaps, 255, width*height*3*sizeof(stmap)); + } - //clear out the deluxmaps incase there is none on the map. - for (k = 0; k < width*height*3; k+=3) - { - lightmap[i]->deluxmaps[k+0] = 128; - lightmap[i]->deluxmaps[k+1] = 128; - lightmap[i]->deluxmaps[k+2] = 255; - } + numlightmaps += count; - TEXASSIGN(lightmap[i]->lightmap_texture, R_AllocNewTexture("***lightmap***", width, height)); - TEXASSIGN(lightmap[i]->deluxmap_texture, R_AllocNewTexture("***deluxmap***", width, height)); + return first; +} +int Surf_NewExternalLightmaps(int count, char *filepattern, qboolean deluxe) +{ + int first = numlightmaps; + int i; + char nname[MAX_QPATH]; + + if (!count) + return -1; + + i = numlightmaps + count; + lightmap = BZ_Realloc(lightmap, sizeof(*lightmap)*(i)); + while(i > first) + { + i--; + + lightmap[i] = Z_Malloc(sizeof(*lightmap[i])); + lightmap[i]->width = 0; + lightmap[i]->height = 0; + lightmap[i]->lightmaps = NULL; + lightmap[i]->stainmaps = NULL; + + lightmap[i]->modified = false; + lightmap[i]->external = true; + lightmap[i]->hasdeluxe = (deluxe && ((i - numlightmaps)&1)); + + Q_snprintfz(nname, sizeof(nname), filepattern, i - numlightmaps); + + TEXASSIGN(lightmap[i]->lightmap_texture, R_LoadHiResTexture(nname, NULL, 0)); + lightmap[i]->width = image_width; + lightmap[i]->height = image_height; } numlightmaps += count; @@ -2865,7 +2551,17 @@ void Surf_BuildLightmaps (void) if (*m->name == '*' && m->fromgame == fg_quake3) //FIXME: should be all bsp formats newfirst = cl.model_precache[1]->lightmaps.first; else - newfirst = Surf_NewLightmaps(m->lightmaps.count, m->lightmaps.width, m->lightmaps.height); + { + if (!m->lightdata && m->lightmaps.count) + { + char pattern[MAX_QPATH]; + COM_StripAllExtensions(m->name, pattern, sizeof(pattern)); + Q_strncatz(pattern, "/lm_%04u.tga", sizeof(pattern)); + newfirst = Surf_NewExternalLightmaps(m->lightmaps.count, pattern, m->lightmaps.deluxemapping); + } + else + newfirst = Surf_NewLightmaps(m->lightmaps.count, m->lightmaps.width, m->lightmaps.height, m->lightmaps.deluxemapping); + } //fixup batch lightmaps for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++) @@ -2907,9 +2603,12 @@ void Surf_BuildLightmaps (void) unsigned char *dst; for (i = 0; i < m->lightmaps.count; i++) { + if (lightmap[newfirst+i]->external) + continue; + dst = lightmap[newfirst+i]->lightmaps; src = m->lightdata + i*m->lightmaps.width*m->lightmaps.height*3; - if (lightmap_bytes == 4) + if (lightmap_bytes == 4 && m->lightdata) { if (lightmap_bgra) { @@ -2937,7 +2636,8 @@ void Surf_BuildLightmaps (void) else { int j; - lightmapinfo_t *lm; + lightmapinfo_t *lm, *dlm; + qbyte *deluxemap; //fixup surface lightmaps, and paint for (i=0; inummodelsurfaces; i++) { @@ -2952,10 +2652,17 @@ void Surf_BuildLightmaps (void) surf->lightmaptexturenums[j] = surf->lightmaptexturenums[0] - m->lightmaps.first + newfirst; lm = lightmap[surf->lightmaptexturenums[j]]; + if (lm->hasdeluxe) + { + dlm = lightmap[surf->lightmaptexturenums[j]+1]; + deluxemap = dlm->lightmaps + (surf->light_t[j] * dlm->width + surf->light_s[j]) * lightmap_bytes; + } + else + deluxemap = NULL; Surf_BuildLightMap (surf, lm->lightmaps + (surf->light_t[j] * lm->width + surf->light_s[j]) * lightmap_bytes, - lm->deluxmaps + (surf->light_t[j] * lm->width + surf->light_s[j]) * 3, + deluxemap, lm->stainmaps + (surf->light_t[j] * lm->width + surf->light_s[j]) * 3, shift, r_ambient.value*255); } @@ -2963,132 +2670,6 @@ void Surf_BuildLightmaps (void) } m->lightmaps.first = newfirst; } -#if 0 - for (j=1 ; jtype != mod_brush) - continue; - - currentmodel = m; - shift = Surf_LightmapShift(currentmodel); - - memsize = 0; - for (i=0; inummodelsurfaces; i++) - { - surf = m->surfaces + i + m->firstmodelsurface; - memsize += Surf_CalcMemSize(surf); - } - mem = Hunk_AllocName(memsize, m->name); - - for (i=0; inummodelsurfaces; i++) - { - surf = m->surfaces + i + m->firstmodelsurface; - if (surf->mesh) //there are some surfaces that have a display list already (q3 ones) - continue; - Surf_CreateSurfaceLightmap (surf, shift); - Surf_BuildSurfaceDisplayList (m, surf, &mem); - } - - for (t = m->numtextures-1; t >= 0; t--) - { - if (m == cl.worldmodel) - ptype = P_FindParticleType(va("tex_%s", m->textures[t]->name)); - else - ptype = P_INVALID; - - sortid = m->textures[t]->shader->sort; - bstop = m->batches[sortid]; - batch = NULL; - for (i=0; inummodelsurfaces; i++) - {//extra texture loop so we get slightly less texture switches - surf = m->surfaces + i + m->firstmodelsurface; - if (surf->texinfo->texture == m->textures[t]) - { - P_EmitSkyEffectTris(m, surf, ptype); - - /*the excessive logic is to give portals separate batches for separate planes*/ - if (sortid == SHADER_SORT_PORTAL || (m->textures[t]->shader->flags & (SHADER_HASREFLECT | SHADER_HASREFRACT))) - { - if (surf->flags & SURF_PLANEBACK) - VectorNegate(surf->plane->normal, sn); - else - VectorCopy(surf->plane->normal, sn); - - if (!batch || batch->lightmap != surf->lightmaptexturenum || batch->firstmesh + surf->mesh->numvertexes > MAX_INDICIES || !VectorCompare(sn, batch->normal)) - { - for (batch = m->batches[sortid]; batch != bstop; batch = batch->next) - { - if (batch->lightmap == surf->lightmaptexturenum && VectorCompare(sn, batch->normal) && batch->firstmesh + surf->mesh->numvertexes <= MAX_INDICIES) - break; - } - if (batch == bstop) - { - batch = Z_Malloc(sizeof(*batch)); - batch->lightmap = surf->lightmaptexturenum; - batch->texture = m->textures[t]; - batch->next = m->batches[sortid]; - batch->ent = &r_worldentity; - VectorCopy(sn, batch->normal); - m->batches[sortid] = batch; - } - } - } - else - { - if (!batch || batch->lightmap != surf->lightmaptexturenum || batch->firstmesh + surf->mesh->numvertexes > MAX_INDICIES) - { - for (batch = m->batches[sortid]; batch != bstop; batch = batch->next) - { - if (batch->lightmap == surf->lightmaptexturenum && batch->firstmesh + surf->mesh->numvertexes <= MAX_INDICIES) - break; - } - if (batch == bstop) - { - batch = Z_Malloc(sizeof(*batch)); - batch->lightmap = surf->lightmaptexturenum; - batch->texture = m->textures[t]; - batch->next = m->batches[sortid]; - batch->ent = &r_worldentity; - VectorClear(batch->normal); - m->batches[sortid] = batch; - } - } - } - surf->sbatch = batch; - batch->maxmeshes++; - batch->firstmesh += surf->mesh->numvertexes; - } - } - } - - for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++) - for (batch = m->batches[sortid]; batch != NULL; batch = batch->next) - { - batch->mesh = BZ_Malloc(sizeof(*batch->mesh)*batch->maxmeshes*2); - } - for (i=0; inummodelsurfaces; i++) - { - surf = m->surfaces + i + m->firstmodelsurface; - surf->sbatch->mesh[surf->sbatch->meshes++] = surf->mesh; - } - BE_GenBrushModelVBO(m); - /*for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++) - for (batch = m->batches[sortid]; batch != NULL; batch = batch->next) - { - batch->vbo = &batch->texture->vbo; - } - */ - for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++) - for (batch = m->batches[sortid]; batch != NULL; batch = batch->next) - { - batch->firstmesh = 0; - batch->meshes = 0; - } - } -#endif BE_UploadAllLightmaps(); } #endif diff --git a/engine/client/render.h b/engine/client/render.h index a3246ed9c..8a0ebf300 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -214,19 +214,13 @@ typedef unsigned char stmap; struct mesh_s; typedef struct { texid_t lightmap_texture; - texid_t deluxmap_texture; qboolean modified; - qboolean deluxmodified; qboolean external; + qboolean hasdeluxe; int width; int height; glRect_t rectchange; - glRect_t deluxrectchange; -#if 0 //def TERRAIN - int allocated[LMBLOCK_WIDTH]; -#endif qbyte *lightmaps;//[4*LMBLOCK_WIDTH*LMBLOCK_HEIGHT]; - qbyte *deluxmaps;//[4*LMBLOCK_WIDTH*LMBLOCK_HEIGHT]; //fixme: make seperate structure for easy disabling with less memory usage. stmap *stainmaps;//[3*LMBLOCK_WIDTH*LMBLOCK_HEIGHT]; //rgb no a. added to lightmap for added (hopefully) speed. } lightmapinfo_t; extern lightmapinfo_t **lightmap; @@ -268,11 +262,11 @@ enum imageflags { /*warning: many of these flags only apply the first time it is requested*/ IF_CLAMP = 1<<0, - IF_NOPICMIP = 1<<1, - IF_NOMIPMAP = 1<<2, - IF_NOALPHA = 1<<3, - IF_NOGAMMA = 1<<4, - IF_NEAREST = 1<<5, + IF_NEAREST = 1<<1, + IF_NOPICMIP = 1<<2, + IF_NOMIPMAP = 1<<3, + IF_NOALPHA = 1<<4, + IF_NOGAMMA = 1<<5, IF_3DMAP = 1<<6, /*waning - don't test directly*/ IF_CUBEMAP = 1<<7, /*waning - don't test directly*/ IF_CUBEMAPEXTRA = 1<<8, @@ -291,7 +285,7 @@ enum imageflags /*it seems a little excessive to have to include glquake (and windows headers), just to load some textures/shaders for the backend*/ #ifdef GLQUAKE -texid_tf GL_AllocNewTexture(char *name, int w, int h); +texid_tf GL_AllocNewTexture(char *name, int w, int h, unsigned int flags); void GL_UploadFmt(texid_t tex, char *name, enum uploadfmt fmt, void *data, void *palette, int width, int height, unsigned int flags); texid_tf GL_LoadTextureFmt (char *identifier, int width, int height, enum uploadfmt fmt, void *data, unsigned int flags); void GL_DestroyTexture(texid_t tex); @@ -302,19 +296,20 @@ texid_t D3D9_LoadTexture8Pal24 (char *identifier, int width, int height, qbyte * texid_t D3D9_LoadTexture8Pal32 (char *identifier, int width, int height, qbyte *data, qbyte *palette32, unsigned int flags); texid_t D3D9_LoadCompressed (char *name); texid_t D3D9_FindTexture (char *identifier, unsigned int flags); -texid_t D3D9_AllocNewTexture(char *ident, int width, int height); +texid_t D3D9_AllocNewTexture(char *ident, int width, int height, unsigned int flags); void D3D9_Upload (texid_t tex, char *name, enum uploadfmt fmt, void *data, void *palette, int width, int height, unsigned int flags); void D3D9_DestroyTexture (texid_t tex); -void D3D_Image_Shutdown(void); +void D3D9_Image_Shutdown(void); texid_t D3D11_LoadTexture (char *identifier, int width, int height, enum uploadfmt fmt, void *data, unsigned int flags); texid_t D3D11_LoadTexture8Pal24 (char *identifier, int width, int height, qbyte *data, qbyte *palette24, unsigned int flags); texid_t D3D11_LoadTexture8Pal32 (char *identifier, int width, int height, qbyte *data, qbyte *palette32, unsigned int flags); texid_t D3D11_LoadCompressed (char *name); -texid_t D3D11_FindTexture (char *identifier); -texid_t D3D11_AllocNewTexture(char *ident, int width, int height); +texid_t D3D11_FindTexture (char *identifier, unsigned int flags); +texid_t D3D11_AllocNewTexture(char *ident, int width, int height, unsigned int flags); void D3D11_Upload (texid_t tex, char *name, enum uploadfmt fmt, void *data, void *palette, int width, int height, unsigned int flags); void D3D11_DestroyTexture (texid_t tex); +void D3D11_Image_Shutdown(void); #endif extern int image_width, image_height; @@ -379,6 +374,7 @@ void R_SetRenderer(rendererinfo_t *ri); void R_AnimateLight (void); struct texture_s *R_TextureAnimation (int frame, struct texture_s *base); void RQ_Init(void); +void RQ_Shutdown(void); void CLQ2_EntityEvent(entity_state_t *es); void CLQ2_TeleporterParticles(entity_state_t *es); diff --git a/engine/client/renderer.c b/engine/client/renderer.c index bad83ca63..4f76800bf 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -204,6 +204,9 @@ cvar_t vid_wndalpha = CVAR ("vid_wndalpha", "1"); cvar_t vid_width = CVARF ("vid_width", "0", CVAR_ARCHIVE | CVAR_RENDERERLATCH); +cvar_t r_stereo_separation = CVARD("r_stereo_separation", "4", "How far your eyes are apart, in quake units. A non-zero value will enable stereoscoping rendering. You might need some of them retro 3d glasses. Hardware support is recommended, see r_stereo_context."); +cvar_t r_stereo_method = CVARD("r_stereo_method", "0", "Value 0 = Off.\nValue 1 = Attempt hardware acceleration. Requires vid_restart.\nValue 2 = red/cyan.\nValue 3 = red/blue. Value 4=red/green"); + extern cvar_t r_dodgytgafiles; extern cvar_t r_dodgypcxfiles; extern cvar_t r_drawentities; @@ -331,9 +334,9 @@ cvar_t r_lightprepass = CVARFD("r_lightprepass", "0", CVAR_SHADERSYSTEM, "E cvar_t r_shadow_bumpscale_basetexture = SCVAR ("r_shadow_bumpscale_basetexture", "4"); cvar_t r_shadow_bumpscale_bumpmap = SCVAR ("r_shadow_bumpscale_bumpmap", "10"); -cvar_t r_glsl_offsetmapping = CVARF ("r_glsl_offsetmapping", "0", CVAR_ARCHIVE); +cvar_t r_glsl_offsetmapping = CVARF ("r_glsl_offsetmapping", "0", CVAR_ARCHIVE|CVAR_SHADERSYSTEM); cvar_t r_glsl_offsetmapping_scale = CVAR ("r_glsl_offsetmapping_scale", "0.04"); -cvar_t r_glsl_offsetmapping_reliefmapping = CVARF("r_glsl_offsetmapping_reliefmapping", "1", CVAR_RENDERERLATCH); +cvar_t r_glsl_offsetmapping_reliefmapping = CVARF("r_glsl_offsetmapping_reliefmapping", "1", CVAR_ARCHIVE|CVAR_SHADERSYSTEM); cvar_t r_shadow_realtime_world = SCVARF ("r_shadow_realtime_world", "0", CVAR_ARCHIVE); cvar_t r_shadow_realtime_world_shadows = SCVARF ("r_shadow_realtime_world_shadows", "1", CVAR_ARCHIVE); @@ -365,6 +368,7 @@ void GLD3DRenderer_Init(void) { Cvar_Register (&gl_mindist, GLRENDEREROPTIONS); Cvar_Register (&gl_load24bit, GRAPHICALNICETIES); + Cvar_Register (&gl_blendsprites, GLRENDEREROPTIONS); } #endif @@ -462,8 +466,6 @@ void GLRenderer_Init(void) Cvar_Register (&gl_blend2d, GLRENDEREROPTIONS); - Cvar_Register (&gl_blendsprites, GLRENDEREROPTIONS); - Cvar_Register (&gl_menutint_shader, GLRENDEREROPTIONS); R_BloomRegister(); @@ -535,9 +537,11 @@ void Renderer_Init(void) #ifdef SWQUAKE { extern cvar_t sw_interlace; - extern cvar_t sw_threads; + extern cvar_t sw_vthread; + extern cvar_t sw_fthreads; Cvar_Register(&sw_interlace, "Software Rendering Options"); - Cvar_Register(&sw_threads, "Software Rendering Options"); + Cvar_Register(&sw_vthread, "Software Rendering Options"); + Cvar_Register(&sw_fthreads, "Software Rendering Options"); } #endif @@ -598,6 +602,8 @@ void Renderer_Init(void) Cvar_Register (&r_sun_colour, GRAPHICALNICETIES); Cvar_Register (&r_waterstyle, GRAPHICALNICETIES); Cvar_Register (&r_wireframe, GRAPHICALNICETIES); + Cvar_Register (&r_stereo_separation, GRAPHICALNICETIES); + Cvar_Register (&r_stereo_method, GRAPHICALNICETIES); Cvar_Register(&scr_viewsize, SCREENOPTIONS); Cvar_Register(&scr_fov, SCREENOPTIONS); @@ -842,7 +848,8 @@ rendererinfo_t *pdedicatedrendererinfo = &dedicatedrendererinfo; rendererinfo_t openglrendererinfo; -rendererinfo_t d3drendererinfo; +rendererinfo_t d3d9rendererinfo; +rendererinfo_t d3d11rendererinfo; rendererinfo_t swrendererinfo; rendererinfo_t *rendererinfo[] = @@ -854,7 +861,8 @@ rendererinfo_t *rendererinfo[] = &openglrendererinfo, #endif #ifdef D3DQUAKE - &d3drendererinfo, + &d3d9rendererinfo, + &d3d11rendererinfo, #endif #ifdef SWQUAKE &swrendererinfo, @@ -950,6 +958,9 @@ void R_ShutdownRenderer(void) R_DeInit(); } + if (Draw_Shutdown) + Draw_Shutdown(); + if (VID_DeInit) { TRACE(("dbg: R_ApplyRenderer: VID_DeInit\n")); @@ -966,6 +977,8 @@ void R_ShutdownRenderer(void) BZ_Free(host_basepal); host_basepal = NULL; + RQ_Shutdown(); + S_Shutdown(); } @@ -1349,10 +1362,15 @@ TRACE(("dbg: R_ApplyRenderer: efrags\n")); "OpenGL renderer initialized\n"); break; - case QR_DIRECT3D: + case QR_DIRECT3D9: Con_Printf( "\n" "-----------------------------\n" - "Direct3d renderer initialized\n"); + "Direct3d9 renderer initialized\n"); + break; + case QR_DIRECT3D11: + Con_Printf( "\n" + "-----------------------------\n" + "Direct3d11 renderer initialized\n"); break; } @@ -1399,6 +1417,7 @@ TRACE(("dbg: R_RestartRenderer_f\n")); newr.bpp = vid_bpp.value; newr.fullscreen = vid_fullscreen.value; newr.rate = vid_refreshrate.value; + newr.stereo = (r_stereo_method.ival == 1); if (!*_vid_wait_override.string || _vid_wait_override.value < 0) newr.wait = -1; @@ -1425,13 +1444,18 @@ TRACE(("dbg: R_RestartRenderer_f\n")); } if (!newr.renderer) { + int i; Con_Printf("vid_renderer unset or unsupported. Using default.\n"); + //gotta do this after main hunk is saved off. -#if defined(GLQUAKE) - Cmd_ExecuteString("setrenderer gl\n", RESTRICT_LOCAL); -#elif defined(D3DQUAKE) - Cmd_ExecuteString("setrenderer d3d\n", RESTRICT_LOCAL); -#endif + for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++) + { + if (rendererinfo[i]->name[0] && stricmp(rendererinfo[i]->name[0], "none")) + { + Cmd_ExecuteString(va("setrenderer %s\n", rendererinfo[i]->name[0]), RESTRICT_LOCAL); + break; + } + } return; } @@ -1968,46 +1992,62 @@ qbyte *R_CalcVis_Q1 (void) qbyte *R_MarkLeaves_Q1 (void) { - static qbyte fatvis[MAX_MAP_LEAFS/8]; - static qbyte *vis; + static qbyte fatvis[2][MAX_MAP_LEAFS/8]; + static qbyte *cvis[2]; + qbyte *vis; mnode_t *node; int i; - qbyte solid[4096]; + qboolean portal = r_refdef.recurse; + + //for portals to work, we need two sets of any pvs caches + //this means lights can still check pvs at the end of the frame despite recursing in the mean time + //however, we still need to invalidate the cache because we only have one 'visframe' field in nodes. if (r_refdef.forcevis) { - vis = r_refdef.forcedvis; + vis = cvis[portal] = r_refdef.forcedvis; r_oldviewleaf = NULL; r_oldviewleaf2 = NULL; } else { - if (((r_oldviewleaf == r_viewleaf && r_oldviewleaf2 == r_viewleaf2) && !r_novis.ival) || r_novis.ival & 2) - return vis; + if (!portal) + { + if (((r_oldviewleaf == r_viewleaf && r_oldviewleaf2 == r_viewleaf2) && !r_novis.ival) || r_novis.ival & 2) + return cvis[portal]; - r_oldviewleaf = r_viewleaf; - r_oldviewleaf2 = r_viewleaf2; + r_oldviewleaf = r_viewleaf; + r_oldviewleaf2 = r_viewleaf2; + } + else + { + r_oldviewleaf = NULL; + r_oldviewleaf2 = NULL; + } if (r_novis.ival) { - vis = solid; - memset (solid, 0xff, (cl.worldmodel->numleafs+7)>>3); + vis = cvis[portal] = fatvis[portal]; + memset (fatvis[portal], 0xff, (cl.worldmodel->numleafs+7)>>3); + + r_oldviewleaf = NULL; + r_oldviewleaf2 = NULL; } else if (r_viewleaf2 && r_viewleaf2 != r_viewleaf) { int c; - Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf2, fatvis, sizeof(fatvis)); - vis = Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf, NULL, 0); + Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf2, fatvis[portal], sizeof(fatvis[portal])); + vis = cvis[portal] = Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf, NULL, 0); c = (cl.worldmodel->numleafs+31)/32; for (i=0 ; i digits) ptr += (l-digits); - if (l < digits) - x += (digits-l)*24; + if (!left) + if (l < digits) + x += (digits-l)*24; while (*ptr) { @@ -3235,20 +3236,20 @@ void Sbar_CoopIntermission (void) // time dig = cl.completed_time/60; - Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 160, (sbar_rect.height - 200)/2 + 64, dig, 3, 0); + Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 230 - 24*4, (sbar_rect.height - 200)/2 + 64, dig, 4, 0, false); num = cl.completed_time - dig*60; - R2D_ScalePic ((sbar_rect.width - 320)/2 + 234,(sbar_rect.height - 200)/2 + 64, 16, 24, sb_colon); - R2D_ScalePic ((sbar_rect.width - 320)/2 + 246,(sbar_rect.height - 200)/2 + 64, 16, 26, sb_nums[0][num/10]); - R2D_ScalePic ((sbar_rect.width - 320)/2 + 266,(sbar_rect.height - 200)/2 + 64, 16, 24, sb_nums[0][num%10]); + R2D_ScalePic ((sbar_rect.width - 320)/2 + 230,(sbar_rect.height - 200)/2 + 64, 16, 24, sb_colon); + R2D_ScalePic ((sbar_rect.width - 320)/2 + 254,(sbar_rect.height - 200)/2 + 64, 16, 26, sb_nums[0][num/10]); + R2D_ScalePic ((sbar_rect.width - 320)/2 + 278,(sbar_rect.height - 200)/2 + 64, 16, 24, sb_nums[0][num%10]); //it is assumed that secrits/monsters are going to be constant for any player... - Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 160, (sbar_rect.height - 200)/2 + 104, cl.playerview[pnum].stats[STAT_SECRETS], 3, 0); - R2D_ScalePic ((sbar_rect.width - 320)/2 + 232,(sbar_rect.height - 200)/2 + 104, 16, 24, sb_slash); - Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 240, (sbar_rect.height - 200)/2 + 104, cl.playerview[pnum].stats[STAT_TOTALSECRETS], 3, 0); + Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 230 - 24*4, (sbar_rect.height - 200)/2 + 104, cl.playerview[pnum].stats[STAT_SECRETS], 4, 0, false); + R2D_ScalePic ((sbar_rect.width - 320)/2 + 230, (sbar_rect.height - 200)/2 + 104, 16, 24, sb_slash); + Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 254, (sbar_rect.height - 200)/2 + 104, cl.playerview[pnum].stats[STAT_TOTALSECRETS], 4, 0, true); - Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 160, (sbar_rect.height - 200)/2 + 144, cl.playerview[pnum].stats[STAT_MONSTERS], 3, 0); - R2D_ScalePic ((sbar_rect.width - 320)/2 + 232,(sbar_rect.height - 200)/2 + 144, 16, 24, sb_slash); - Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 240, (sbar_rect.height - 200)/2 + 144, cl.playerview[pnum].stats[STAT_TOTALMONSTERS], 3, 0); + Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 230 - 24*4, (sbar_rect.height - 200)/2 + 144, cl.playerview[pnum].stats[STAT_MONSTERS], 4, 0, false); + R2D_ScalePic ((sbar_rect.width - 320)/2 + 230,(sbar_rect.height - 200)/2 + 144, 16, 24, sb_slash); + Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 254, (sbar_rect.height - 200)/2 + 144, cl.playerview[pnum].stats[STAT_TOTALMONSTERS], 4, 0, true); } /* ================== diff --git a/engine/client/skin.c b/engine/client/skin.c index 549a99ac6..6e93b2872 100644 --- a/engine/client/skin.c +++ b/engine/client/skin.c @@ -276,22 +276,18 @@ qbyte *Skin_Cache8 (skin_t *skin) { if (strcmp(skin->name, baseskin.string)) { -#if defined(GLQUAKE) || defined(D3DQUAKE) - if (qrenderer == QR_OPENGL || qrenderer == QR_DIRECT3D) + TEXASSIGN(skin->tex_base, R_LoadReplacementTexture(skin->name, "skins", IF_NOALPHA)); + if (TEXVALID(skin->tex_base)) { - TEXASSIGN(skin->tex_base, R_LoadReplacementTexture(skin->name, "skins", IF_NOALPHA)); - if (TEXVALID(skin->tex_base)) - { - Q_snprintfz (name, sizeof(name), "%s_shirt", skin->name); - TEXASSIGN(skin->tex_upper, R_LoadReplacementTexture(name, "skins", 0)); - Q_snprintfz (name, sizeof(name), "%s_pants", skin->name); - TEXASSIGN(skin->tex_lower, R_LoadReplacementTexture(name, "skins", 0)); + Q_snprintfz (name, sizeof(name), "%s_shirt", skin->name); + TEXASSIGN(skin->tex_upper, R_LoadReplacementTexture(name, "skins", 0)); + Q_snprintfz (name, sizeof(name), "%s_pants", skin->name); + TEXASSIGN(skin->tex_lower, R_LoadReplacementTexture(name, "skins", 0)); - skin->failedload = true; - return NULL; - } + skin->failedload = true; + return NULL; } -#endif + //if its not already the base skin, try the base (and warn if anything not base couldn't load). Con_Printf ("Couldn't load skin %s\n", name); Q_snprintfz (name, sizeof(name), "skins/%s.pcx", baseskin.string); diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c index 0cba54448..7b8c087c3 100644 --- a/engine/client/snd_dma.c +++ b/engine/client/snd_dma.c @@ -659,6 +659,7 @@ void S_Voip_Parse(void) sounddriver pOPENAL_InitCard; sounddriver pDSOUND_InitCard; sounddriver pALSA_InitCard; +sounddriver pSNDIO_InitCard; sounddriver pOSS_InitCard; sounddriver pMacOS_InitCard; sounddriver pSDL_InitCard; @@ -677,9 +678,10 @@ sdriver_t drivers[] = { {"DSound", &pDSOUND_InitCard}, //prefered on windows {"MacOS", &pMacOS_InitCard}, //prefered on mac - {"Droid", &pDroid_InitCard}, //prefered on android (java thread) + {"Droid", &pDroid_InitCard}, //prefered on android (java thread) {"AHI", &pAHI_InitCard}, //prefered on morphos {"PPAPI", &pPPAPI_InitCard}, //google's native client + {"SNDIO", &pSNDIO_InitCard}, //prefered on OpenBSD {"SDL", &pSDL_InitCard}, //prefered on linux {"ALSA", &pALSA_InitCard}, //pure shite @@ -911,7 +913,8 @@ void S_SetUnderWater(qboolean underwater) soundcardinfo_t *sc; for (sc = sndcardinfo; sc; sc=sc->next) - sc->SetWaterDistortion(sc, underwater); + if (sc->SetWaterDistortion) + sc->SetWaterDistortion(sc, underwater); } //why isn't this part of S_Restart_f anymore? diff --git a/engine/client/snd_mix.c b/engine/client/snd_mix.c index 10cc15f15..21f55d543 100644 --- a/engine/client/snd_mix.c +++ b/engine/client/snd_mix.c @@ -115,6 +115,7 @@ void SND_PaintChannelFrom16_8Speaker (channel_t *ch, sfxcache_t *sc, int count); void SND_PaintChannelFrom8Stereo (channel_t *ch, sfxcache_t *sc, int count); void SND_PaintChannelFrom16Stereo (channel_t *ch, sfxcache_t *sc, int count); +//NOTE: MAY NOT CALL SYS_ERROR void S_PaintChannels(soundcardinfo_t *sc, int endtime) { int i; diff --git a/engine/client/snd_sndio.c b/engine/client/snd_sndio.c new file mode 100644 index 000000000..4d3670f1f --- /dev/null +++ b/engine/client/snd_sndio.c @@ -0,0 +1,210 @@ +/* +* Copyright (c) 2010 Jacob Meuser +* +* Permission to use, copy, modify, and distribute this software for any +* purpose with or without fee is hereby granted, provided that the above +* copyright notice and this permission notice appear in all copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +/* Modifified for FTEQW by Alf Schlichting, a.schlichting@lemarit.com */ +/* note: this is for OpenBSD */ + +#include "quakedef.h" +#include "sound.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +struct sndio_private +{ + struct sio_hdl *hdl; + + unsigned char *dma_buffer; + size_t dma_buffer_size, dma_ptr; +}; + +static int sndio_init(soundcardinfo_t *, int); +static void *sndio_lock(soundcardinfo_t *); +static void sndio_unlock(soundcardinfo_t *, void *); +static void sndio_shutdown(soundcardinfo_t *); +static unsigned int sndio_getdmapos(soundcardinfo_t *); +static void sndio_submit(soundcardinfo_t *, int, int); +static void sndio_setunderwater(soundcardinfo_t *sc, qboolean underwater); //simply a stub. Any ideas how to actually implement this properly? + +static void sndio_setunderwater(soundcardinfo_t *sc, qboolean underwater) //simply a stub. Any ideas how to actually implement this properly? +{ +} + + +#define SND_ERROR 0 +#define SND_LOADED 1 +#define SND_NOMORE 2 //like error, but doesn't try the next card. +static int +sndio_init(soundcardinfo_t *sc, int cardnum) +{ + struct sndio_private *sp; + struct sio_par par; + unsigned samp_per_buf; + char *s; + int i; + + Con_DPrintf("sndio_init called\n"); + if (cardnum) + return SND_NOMORE; + + sp = calloc(sizeof(struct sndio_private), 1); + if (sp == NULL) + { + Con_Printf("Could not get mem"); + return SND_ERROR; + } + + Con_DPrintf("trying to open sp->hdl\n"); + sp->hdl = sio_open(SIO_DEVANY, SIO_PLAY, 1); + if (sp->hdl == NULL) + { + Con_Printf("Could not open sndio device\n"); + return SND_NOMORE; + } + Con_DPrintf("Opened sndio\n"); + sc->GetDMAPos = sndio_getdmapos; + sc->Submit = sndio_submit; + sc->Shutdown = sndio_shutdown; + sc->Lock = sndio_lock; + sc->Unlock = sndio_unlock; + sc->SetWaterDistortion = sndio_setunderwater; + sc->handle = sp; + + sio_initpar(&par); + par.rate = sc->sn.speed; + par.bits = sc->sn.samplebits; + par.sig = 1; + par.le = SIO_LE_NATIVE; + par.pchan = sc->sn.numchannels; + par.appbufsz = par.rate / 20; /* 1/20 second latency */ + + if (!sio_setpar(sp->hdl, &par) || !sio_getpar(sp->hdl, &par)) + { + Con_Printf("Error setting audio parameters\n"); + sio_close(sp->hdl); + return SND_ERROR; + } + if ((par.pchan != 1 && par.pchan != 2) || + (par.bits != 16 || par.sig != 1)) + { + Con_Printf("Could not set appropriate audio parameters\n"); + sio_close(sp->hdl); + return SND_ERROR; + } +/* sc->sn.speed = par.rate; + sc->sn.numchannels = par.pchan; + sc->sn.samplebits = par.bits; +*/ + + /* + * find the smallest power of two larger than the buffer size + * and use it as the internal buffer's size + */ + for (i = 1; i < par.appbufsz; i <<= 1) + ; /* nothing */ + sc->sn.samples = i * par.pchan; + + sp->dma_buffer_size = sc->sn.samples * sc->sn.samplebits / 8; + sc->sn.buffer = calloc(1, sp->dma_buffer_size); + if (sc->sn.buffer == NULL) + { + Con_Printf("Could not allocate audio ring buffer\n"); + return SND_ERROR; + } + dma_ptr = 0; + if (!sio_start(sp->hdl)) + { + Con_Printf("Could not start audio\n"); + sio_close(sp->hdl); + return SND_ERROR; + } + sc->sn.samplepos = 0; + + Con_DPrintf("sc->sn.speed = %d, par.rate = %d\n", sc->sn.speed, par.rate); + Con_DPrintf("sc->sn.samplebits = %d, par.bits = %d\n", sc->sn.samplebits, par.bits); + Con_DPrintf("sc->sn.numchannels = %d, par.pchan = %d\n", sc->sn.numchannels, par.pchan); + Con_DPrintf("sc->sn.samples = %d, par.pchan = %d\n", sc->sn.samples, par.pchan); + Con_DPrintf("dma_buffer_size = %d\n", sp->dma_buffer_size); + return SND_LOADED; +} + + +static void * +sndio_lock(soundcardinfo_t *sc, unsigned int *sampidx) +{ + return sc->sn.buffer; +} + +static void +sndio_unlock(soundcardinfo_t *sci, void *p) +{ +} + +static void +sndio_shutdown(soundcardinfo_t *sc) +{ + struct sndio_private *sp = sc->handle; + + sio_close(sp->hdl); + free(sc->sn.buffer); + sc->sn.buffer = NULL; + *sc->name = '\0'; +} + +static unsigned int +sndio_getdmapos(soundcardinfo_t *sc) +{ + struct sndio_private *sp = sc->handle; + sc->sn.samplepos = dma_ptr / (sc->sn.samplebits / 8); + return sc->sn.samplepos; +} + +static void +sndio_submit(soundcardinfo_t *sc, int startcount, int endcount) +{ + struct pollfd pfd; + struct sndio_private *sp = sc->handle; + size_t count, todo, avail; + int n; + + n = sio_pollfd(sp->hdl, &pfd, POLLOUT); + while (poll(&pfd, n, 0) < 0 && errno == EINTR) + ; + if (!(sio_revents(sp->hdl, &pfd) & POLLOUT)) + return; + avail = sp->dma_buffer_size; + while (avail > 0) + { + todo = sp->dma_buffer_size - dma_ptr; + if (todo > avail) + todo = avail; + count = sio_write(sp->hdl, sc->sn.buffer + dma_ptr, todo); + if (count == 0) + break; + dma_ptr += count; + if (dma_ptr >= sp->dma_buffer_size) + dma_ptr -= sp->dma_buffer_size; + avail -= count; + } +} + +int (*pSNDIO_InitCard) (soundcardinfo_t *sc, int cardnum) = &sndio_init; diff --git a/engine/client/sound.h b/engine/client/sound.h index f4e614017..5584838b7 100644 --- a/engine/client/sound.h +++ b/engine/client/sound.h @@ -58,8 +58,8 @@ typedef struct sfx_s // !!! if this is changed, it much be changed in asm_i386.h too !!! typedef struct sfxcache_s { - unsigned int length; - unsigned int loopstart; + unsigned int length; //sample count + unsigned int loopstart; //-1 or sample index to begin looping at once the sample ends unsigned int speed; unsigned int width; unsigned int numchannels; @@ -256,6 +256,7 @@ typedef int (*sounddriver) (soundcardinfo_t *sc, int cardnum); extern sounddriver pOPENAL_InitCard; extern sounddriver pDSOUND_InitCard; extern sounddriver pALSA_InitCard; +extern sounddriver pSNDIO_InitCard; extern sounddriver pOSS_InitCard; extern sounddriver pSDL_InitCard; extern sounddriver pWAV_InitCard; @@ -285,16 +286,16 @@ struct soundcardinfo_s { //windows has one defined AFTER directsound int samplequeue; //this is the number of samples the device can enqueue. if set, DMAPos returns the write point (rather than hardware read point) (in samplepairs). //callbacks - void *(*Lock) (soundcardinfo_t *sc, unsigned int *startoffset); - void (*Unlock) (soundcardinfo_t *sc, void *buffer); - void (*Submit) (soundcardinfo_t *sc, int start, int end); - void (*Shutdown) (soundcardinfo_t *sc); - unsigned int (*GetDMAPos) (soundcardinfo_t *sc); - void (*SetWaterDistortion) (soundcardinfo_t *sc, qboolean underwater); - void (*Restore) (soundcardinfo_t *sc); - void (*ChannelUpdate) (soundcardinfo_t *sc, channel_t *channel, unsigned int schanged); + void *(*Lock) (soundcardinfo_t *sc, unsigned int *startoffset); //grab a pointer to the hardware ringbuffer or whatever. startoffset is the starting offset. you can set it to 0 and bump the start offset if you need. + void (*Unlock) (soundcardinfo_t *sc, void *buffer); //release the hardware ringbuffer memory + void (*Submit) (soundcardinfo_t *sc, int start, int end); //if the ringbuffer is emulated, this is where you should push it to the device. + void (*Shutdown) (soundcardinfo_t *sc); //kill the device + unsigned int (*GetDMAPos) (soundcardinfo_t *sc); //get the current point that the hardware is reading from (the return value should not wrap, at least not very often) + void (*SetWaterDistortion) (soundcardinfo_t *sc, qboolean underwater); //if you have eax enabled, change the environment. fixme. generally this is a stub. optional. + void (*Restore) (soundcardinfo_t *sc); //called before lock/unlock/lock/unlock/submit. optional + void (*ChannelUpdate) (soundcardinfo_t *sc, channel_t *channel, unsigned int schanged); //properties of a sound effect changed. this is to notify hardware mixers. optional. -//driver -specific +//driver-specific - if you need more stuff, you should just shove it in the handle pointer void *thread; void *handle; int snd_sent; diff --git a/engine/client/sys_droid.c b/engine/client/sys_droid.c index 87fbb1d93..1a5d48a9d 100644 --- a/engine/client/sys_droid.c +++ b/engine/client/sys_droid.c @@ -18,19 +18,24 @@ qboolean isDedicated = false; #endif #endif void *sys_window; /*public so the renderer can attach to the correct place*/ -static qboolean sys_running = false; +static int sys_running = false; int sys_glesversion; +static void *sys_memheap; +static unsigned int sys_lastframe; +static unsigned int vibrateduration; +static char errormessage[256]; +extern jmp_buf host_abort; + cvar_t sys_vibrate = CVAR("sys_vibrate", "1"); cvar_t sys_osk = CVAR("sys_osk", "0"); //to be toggled cvar_t sys_keepscreenon = CVAR("sys_keepscreenon", "1"); //to be toggled +cvar_t sys_orientation = CVAR("sys_orientation", "sensor"); +extern cvar_t vid_conautoscale; #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, DISTRIBUTION"Droid", __VA_ARGS__)) #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, DISTRIBUTION"Droid", __VA_ARGS__)) - -static void *sys_memheap; -static unsigned int sys_lastframe; -static unsigned int vibrateduration; +#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, DISTRIBUTION"Droid", __VA_ARGS__)) void Sys_Vibrate(int count) { @@ -43,11 +48,26 @@ JNIEXPORT jint JNICALL Java_com_fteqw_FTEDroidEngine_getvibrateduration(JNIEnv * return dur; } +JNIEXPORT jstring JNICALL Java_com_fteqw_FTEDroidEngine_geterrormessage(JNIEnv *env, jobject obj) +{ + return (*env)->NewStringUTF(env, errormessage); +} +JNIEXPORT jstring JNICALL Java_com_fteqw_FTEDroidEngine_getpreferedorientation(JNIEnv *env, jobject obj) +{ + sys_orientation.modified = false; + return (*env)->NewStringUTF(env, sys_orientation.string); +} + JNIEXPORT jint JNICALL Java_com_fteqw_FTEDroidEngine_frame(JNIEnv *env, jobject obj, jfloat ax, jfloat ay, jfloat az) { int ret; static vec3_t oac; + + //if we had an error, don't even run a frame any more. + if (*errormessage) + return 8; + #ifdef SERVERONLY SV_Frame(); #else @@ -74,18 +94,48 @@ JNIEXPORT jint JNICALL Java_com_fteqw_FTEDroidEngine_frame(JNIEnv *env, jobject ret |= 2; if (sys_keepscreenon.ival) ret |= 4; + if (*errormessage) + ret |= 8; + if (sys_orientation.modified) + ret |= 16; return ret; } +//tells us that our old gl context got completely obliterated +JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_newglcontext(JNIEnv *env, jobject obj) +{ + if (sys_running) + sys_running = 2; + + //fixme: wipe image handles +} + +//called for init or resizes JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_init(JNIEnv *env, jobject obj, jint width, jint height, jint glesversion, jstring japkpath, jstring jusrpath) { const char *tmp; + + if (*errormessage) + return; + vid.pixelwidth = width; vid.pixelheight = height; sys_glesversion = glesversion; if (sys_running) - Cmd_ExecuteString("vid_restart\n", RESTRICT_LOCAL); + { + Sys_Printf("vid size changed\n"); + if (1)//FFS sys_running == 2) + { + //if our textures got destroyed, we need to reload them all + Cmd_ExecuteString("vid_restart\n", RESTRICT_LOCAL); + } + else + { + //otherwise we just need to set the size properly again. + Cvar_ForceCallback(&vid_conautoscale); + } + } else { const char *args [] = @@ -99,6 +149,7 @@ JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_init(JNIEnv *env, jobject o char *basepack; int align; quakeparms_t parms; + Sys_Printf("reinit\n"); if (sys_memheap) free(sys_memheap); parms.basedir = NULL; /*filled in later*/ @@ -109,6 +160,7 @@ JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_init(JNIEnv *env, jobject o if (!parms.membase) { Sys_Printf("Unable to alloc heap\n"); + Q_strncpyz(errormessage, "Unable to alloc heap\n", sizeof(errormessage)); return; } @@ -224,7 +276,10 @@ void Sys_Quit(void) SV_Shutdown(); #endif - exit (0); + LOGI("%s", "quitting"); + + longjmp(host_abort, 1); + exit(0); } void Sys_Error (const char *error, ...) { @@ -234,9 +289,14 @@ void Sys_Error (const char *error, ...) va_start (argptr, error); vsnprintf (string,sizeof(string)-1, error,argptr); va_end (argptr); + if (!*string) + strcpy(string, "no error"); - LOGW("%s", string); + Q_strncpyz(errormessage, string, sizeof(errormessage)); + LOGE("%s", string); + + longjmp(host_abort, 1); exit(1); } void Sys_Printf (char *fmt, ...) @@ -308,6 +368,7 @@ void Sys_Init(void) Cvar_Register(&sys_vibrate, "android stuff"); Cvar_Register(&sys_osk, "android stuff"); Cvar_Register(&sys_keepscreenon, "android stuff"); + Cvar_Register(&sys_orientation, "android stuff"); } qboolean Sys_GetDesktopParameters(int *width, int *height, int *bpp, int *refreshrate) diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index 2ddb944b1..59a7b66b6 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -1529,14 +1529,14 @@ typedef struct IPropertyStore #endif #endif -static const IID IID_IPropertyStore = {0x886d8eeb, 0x8cf2, 0x4446, {0x8d, 0x02, 0xcd, 0xba, 0x1d, 0xbd, 0xcf, 0x99}}; +static const IID qIID_IPropertyStore = {0x886d8eeb, 0x8cf2, 0x4446, {0x8d, 0x02, 0xcd, 0xba, 0x1d, 0xbd, 0xcf, 0x99}}; #ifndef MINGW #if !defined(VER_PRODUCTBUILD) || VER_PRODUCTBUILD < 7600 #define IObjectArray IUnknown #endif #endif -static const IID IID_IObjectArray = {0x92ca9dcd, 0x5622, 0x4bba, {0xa8,0x05,0x5e,0x9f,0x54,0x1b,0xd8,0xc9}}; +static const IID qIID_IObjectArray = {0x92ca9dcd, 0x5622, 0x4bba, {0xa8,0x05,0x5e,0x9f,0x54,0x1b,0xd8,0xc9}}; #ifndef MINGW #if !defined(VER_PRODUCTBUILD) || VER_PRODUCTBUILD < 7600 @@ -1583,8 +1583,8 @@ typedef struct IObjectCollection } IObjectCollection; #endif #endif -static const IID IID_IObjectCollection = {0x5632b1a4, 0xe38a, 0x400a, {0x92,0x8a,0xd4,0xcd,0x63,0x23,0x02,0x95}}; -static const CLSID CLSID_EnumerableObjectCollection = {0x2d3468c1, 0x36a7, 0x43b6, {0xac,0x24,0xd3,0xf0,0x2f,0xd9,0x60,0x7a}}; +static const IID qIID_IObjectCollection = {0x5632b1a4, 0xe38a, 0x400a, {0x92,0x8a,0xd4,0xcd,0x63,0x23,0x02,0x95}}; +static const CLSID qCLSID_EnumerableObjectCollection = {0x2d3468c1, 0x36a7, 0x43b6, {0xac,0x24,0xd3,0xf0,0x2f,0xd9,0x60,0x7a}}; #ifndef MINGW @@ -1646,8 +1646,8 @@ typedef struct ICustomDestinationList } ICustomDestinationList; #endif #endif -static const IID IID_ICustomDestinationList = {0x6332debf, 0x87b5, 0x4670, {0x90,0xc0,0x5e,0x57,0xb4,0x08,0xa4,0x9e}}; -static const CLSID CLSID_DestinationList = {0x77f10cf0, 0x3db5, 0x4966, {0xb5,0x20,0xb7,0xc5,0x4f,0xd3,0x5e,0xd6}}; +static const IID qIID_ICustomDestinationList = {0x6332debf, 0x87b5, 0x4670, {0x90,0xc0,0x5e,0x57,0xb4,0x08,0xa4,0x9e}}; +static const CLSID qCLSID_DestinationList = {0x77f10cf0, 0x3db5, 0x4966, {0xb5,0x20,0xb7,0xc5,0x4f,0xd3,0x5e,0xd6}}; @@ -1690,7 +1690,7 @@ static IShellLinkW *CreateShellLink(char *command, char *target, char *title, ch IShellLinkW_SetDescription(link, buf); /*tooltip*/ - hr = IShellLinkW_QueryInterface(link, &IID_IPropertyStore, &prop_store); + hr = IShellLinkW_QueryInterface(link, &qIID_IPropertyStore, &prop_store); #ifndef MINGW if(SUCCEEDED(hr)) @@ -1746,13 +1746,13 @@ void Win7_TaskListInit(void) IObjectArray *arr; IShellLinkW *link; CoInitialize(NULL); - if (SUCCEEDED(CoCreateInstance(&CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER, &IID_ICustomDestinationList, &cdl))) + if (SUCCEEDED(CoCreateInstance(&qCLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER, &qIID_ICustomDestinationList, &cdl))) { UINT minslots; IUnknown *removed; - cdl->lpVtbl->BeginList(cdl, &minslots, &IID_IObjectArray, &removed); + cdl->lpVtbl->BeginList(cdl, &minslots, &qIID_IObjectArray, &removed); - if (SUCCEEDED(CoCreateInstance(&CLSID_EnumerableObjectCollection, NULL, CLSCTX_INPROC_SERVER, &IID_IObjectCollection, &col))) + if (SUCCEEDED(CoCreateInstance(&qCLSID_EnumerableObjectCollection, NULL, CLSCTX_INPROC_SERVER, &qIID_IObjectCollection, &col))) { switch(M_GameType()) @@ -1761,13 +1761,13 @@ void Win7_TaskListInit(void) link = CreateShellLink("+menu_servers", "", "Server List", "Pick a multiplayer server to join"); if (link) { - col->lpVtbl->AddObject(col, link); + col->lpVtbl->AddObject(col, (IUnknown*)link); link->lpVtbl->Release(link); } link = CreateShellLink("+map start", "", "Start New Game (Quake)", "Begin a new single-player game"); if (link) { - col->lpVtbl->AddObject(col, link); + col->lpVtbl->AddObject(col, (IUnknown*)link); link->lpVtbl->Release(link); } break; @@ -1775,13 +1775,13 @@ void Win7_TaskListInit(void) link = CreateShellLink("+menu_servers", "", "Quake2 Server List", "Pick a multiplayer server to join"); if (link) { - col->lpVtbl->AddObject(col, link); + col->lpVtbl->AddObject(col, (IUnknown*)link); link->lpVtbl->Release(link); } link = CreateShellLink("+map unit1", "", "Start New Game (Quake2)", "Begin a new game"); if (link) { - col->lpVtbl->AddObject(col, link); + col->lpVtbl->AddObject(col, (IUnknown*)link); link->lpVtbl->Release(link); } break; @@ -1789,19 +1789,19 @@ void Win7_TaskListInit(void) link = CreateShellLink("+menu_servers", "", "Hexen2 Server List", "Pick a multiplayer server to join"); if (link) { - col->lpVtbl->AddObject(col, link); + col->lpVtbl->AddObject(col, (IUnknown*)link); link->lpVtbl->Release(link); } link = CreateShellLink("+map demo1", "", "Start New Game (Hexen2)", "Begin a new game"); if (link) { - col->lpVtbl->AddObject(col, link); + col->lpVtbl->AddObject(col, (IUnknown*)link); link->lpVtbl->Release(link); } break; } - if (SUCCEEDED(col->lpVtbl->QueryInterface(col, &IID_IObjectArray, &arr))) + if (SUCCEEDED(col->lpVtbl->QueryInterface(col, &qIID_IObjectArray, &arr))) { cdl->lpVtbl->AddUserTasks(cdl, arr); arr->lpVtbl->Release(arr); @@ -2161,12 +2161,12 @@ qboolean Sys_GetDesktopParameters(int *width, int *height, int *bpp, int *refres /* Thread creation calls */ typedef struct threadwrap_s { - void (*func)(void *); + int (*func)(void *); void *args; } threadwrap_t; // the thread call is wrapped so we don't need WINAPI everywhere -DWORD WINAPI threadwrapper(void *args) +unsigned WINAPI threadwrapper(void *args) { threadwrap_t tw; tw.func = ((threadwrap_t *)args)->func; diff --git a/engine/client/vid.h b/engine/client/vid.h index ff0a0c7bc..f82fee2aa 100644 --- a/engine/client/vid.h +++ b/engine/client/vid.h @@ -25,13 +25,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // a pixel can be one, two, or four bytes typedef qbyte pixel_t; -typedef enum {QR_NONE, QR_OPENGL, QR_DIRECT3D, QR_SOFTWARE} r_qrenderer_t; +typedef enum {QR_NONE, QR_OPENGL, QR_DIRECT3D9, QR_DIRECT3D11, QR_SOFTWARE} r_qrenderer_t; typedef struct { //you are not allowed to make anything not work if it's not based on these vars... int width; int height; qboolean fullscreen; + qboolean stereo; int bpp; int rate; int wait; //-1 = default, 0 = off, 1 = on, 2 = every other diff --git a/engine/client/view.c b/engine/client/view.c index cde705aac..fcc1bfc61 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -472,7 +472,7 @@ void V_cshift_f (void) char *c = Cmd_Argv(4); // malice jumbles commands into a v_cshift so this attempts to fix - while (isdigit(*c)) + while (isdigit(*c) || *c == '.') c++; if (*c) diff --git a/engine/client/winquake.rc b/engine/client/winquake.rc index 7a337126b..cefbe2c49 100644 --- a/engine/client/winquake.rc +++ b/engine/client/winquake.rc @@ -85,7 +85,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. -IDI_ICON3 ICON "bymorphed.ico" +IDI_ICON1 ICON "bymorphed.ico" ///////////////////////////////////////////////////////////////////////////// // diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 0f6d508bc..1bb93ce14 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -105,6 +105,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. //#define DYNAMIC_LIBPNG //#define DYNAMIC_LIBJPEG +#ifdef D3DQUAKE +#define D3D9QUAKE +#endif + +#if (defined(D3D9QUAKE) || defined(D3D11Quake)) && !defined(D3DQUAKE) +#define D3DQUAKE +#endif + #if defined(_MSC_VER) //too lazy to fix up the makefile //#define BOTLIB_STATIC #endif @@ -306,26 +314,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. //remove any options that depend upon GL. #ifndef SERVERONLY - #if !defined(GLQUAKE) && !defined(D3DQUAKE) - #undef DOOMWADS - #undef HALFLIFEMODELS - #undef Q3BSPS - #undef R_XFLIP - #undef RUNTIMELIGHTING - #undef Q3CLIENT - #endif - // undefine things not supported yet for D3D #if defined(D3DQUAKE) && !defined(GLQUAKE) #undef DDS // this is dumb - #undef HALFLIFEMODELS #endif #endif -#if !defined(GLQUAKE) && !defined(D3DQUAKE) && !defined(SERVERONLY) - #undef Q3BSPS -#endif #if !defined(Q3BSPS) #undef Q3CLIENT //reconsider this (later) #undef Q3SERVER //reconsider this (later) diff --git a/engine/common/bspfile.h b/engine/common/bspfile.h index 71c529b60..06255acb7 100644 --- a/engine/common/bspfile.h +++ b/engine/common/bspfile.h @@ -56,7 +56,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define BSPVERSION 29 //HalfLife support #define BSPVERSIONHL 30 -#define BSPVERSION_LONG (('B' << 24) | ('S' << 16) | ('P' << 8) | '2') /*RMQ support. 32bits instead of shorts for all but bbox sizes*/ +#define BSPVERSION_LONG1 (('B' << 24) | ('S' << 16) | ('P' << 8) | '2') /*RMQ support (2PSB). 32bits instead of shorts for all but bbox sizes*/ +#define BSPVERSION_LONG2 (('B' << 0) | ('S' << 8) | ('P' << 16) | ('2'<<24)) /*BSP2 support. 32bits instead of shorts for everything*/ typedef struct { @@ -172,7 +173,16 @@ typedef struct short maxs[3]; unsigned int firstface; unsigned int numfaces; // counting both sides -} dlnode_t; +} dl1node_t; +typedef struct +{ + int planenum; + int children[2]; // negative numbers are -(leafs+1), not nodes + float mins[3]; // for sphere culling + float maxs[3]; + unsigned int firstface; + unsigned int numfaces; // counting both sides +} dl2node_t; typedef struct { @@ -274,7 +284,20 @@ typedef struct unsigned int nummarksurfaces; qbyte ambient_level[NUM_AMBIENTS]; -} dlleaf_t; +} dl1leaf_t; +typedef struct +{ + int contents; + int visofs; // -1 = no visibility info + + float mins[3]; // for frustum culling + float maxs[3]; + + unsigned int firstmarksurface; + unsigned int nummarksurfaces; + + qbyte ambient_level[NUM_AMBIENTS]; +} dl2leaf_t; //============================================================================ diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index e06a3bafc..f029d8381 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -45,11 +45,7 @@ void Mod_DoCRC(model_t *mod, char *buffer, int buffersize) -#if defined(D3DQUAKE) || defined(GLQUAKE) || defined(SERVERONLY) - -#ifdef GLQUAKE -#include "glquake.h" -#endif +#if 1 #ifdef _WIN32 #include @@ -1369,6 +1365,7 @@ static void Alias_BuildSkeletalMesh(mesh_t *mesh, float *bonepose, galiasinfo_t } #ifdef GLQUAKE +#include "glquake.h" static void Alias_GLDrawSkeletalBones(galiasbone_t *bones, float *bonepose, int bonecount) { PPL_RevertToKnownState(); @@ -2810,9 +2807,6 @@ qboolean Mod_LoadQ1Model (model_t *mod, void *buffer) { default: #if defined(GLQUAKE) || defined(D3DQUAKE) - case QR_DIRECT3D: - case QR_OPENGL: - case QR_SOFTWARE: pinstverts = (dstvert_t *)Q1_LoadSkins_GL(skinstart, skintranstype); break; #endif @@ -3762,6 +3756,43 @@ int Mod_SkinNumForName(model_t *model, char *name) } #endif +const char *Mod_FrameNameForNum(model_t *model, int num) +{ + galiasgroup_t *group; + galiasinfo_t *inf; + + if (!model) + return NULL; + if (model->type != mod_alias) + return NULL; + + inf = Mod_Extradata(model); + + if (num >= inf->groups) + return NULL; + group = (galiasgroup_t*)((char*)inf + inf->groupofs); + return group[num].name; +} + +const char *Mod_SkinNameForNum(model_t *model, int num) +{ +#ifdef SERVERONLY + return NULL; +#else + galiasinfo_t *inf; + galiasskin_t *skin; + + if (!model || model->type != mod_alias) + return NULL; + inf = Mod_Extradata(model); + + if (num >= inf->numskins) + return NULL; + skin = (galiasskin_t*)((char*)inf+inf->ofsskins); + return skin[num].name; +#endif +} + float Mod_FrameDuration(model_t *model, int frameno) { galiasinfo_t *inf; @@ -5808,7 +5839,7 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) for (i = 0; i < h->num_joints; i++) { - Q_strncpyz(bones[i].name, strings+ijoint[i].name, sizeof(ijoint[i].name)); + Q_strncpyz(bones[i].name, strings+ijoint[i].name, sizeof(bones[i].name)); bones[i].parent = ijoint[i].parent; GenMatrixPosQuat3Scale(ijoint[i].translate, ijoint[i].rotate, ijoint[i].scale, &basepose[i*12]); @@ -5906,6 +5937,8 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) fgroup[i].numposes = LittleLong(anim[i].num_frames); fgroup[i].poseofs = (char*)(opose+LittleLong(anim[i].first_frame)*12*h->num_poses) - (char*)&fgroup[i]; fgroup[i].rate = LittleFloat(anim[i].framerate); + if (!fgroup[i].rate) + fgroup[i].rate = 10; } } diff --git a/engine/common/com_phys_ode.c b/engine/common/com_phys_ode.c index 0c1945712..d3c7c920d 100644 --- a/engine/common/com_phys_ode.c +++ b/engine/common/com_phys_ode.c @@ -2317,43 +2317,31 @@ static void VARGS nearCallback (void *data, dGeomID o1, dGeomID o2) void World_ODE_Frame(world_t *world, double frametime, double gravity) { - if (world->ode.ode) + if (world->ode.ode && (world->ode.hasodeents))// || world->ode.hasragdoll)) { int i; wedict_t *ed; - if (!world->ode.hasodeents) - { - for (i = 0; i < world->num_edicts; i++) - { - ed = (wedict_t*)EDICT_NUM(world->progs, i); - if (ed->v->movetype >= SOLID_PHYSICS_BOX) - { - world->ode.hasodeents = true; - break; - } - } - if (!world->ode.hasodeents) - return; - } - world->ode.ode_iterations = bound(1, physics_ode_iterationsperframe.ival, 1000); world->ode.ode_step = frametime / world->ode.ode_iterations; world->ode.ode_movelimit = physics_ode_movelimit.value / world->ode.ode_step; - // copy physics properties from entities to physics engine - for (i = 0;i < world->num_edicts;i++) + if (world->ode.hasodeents) { - ed = (wedict_t*)EDICT_NUM(world->progs, i); - if (!ed->isfree) - World_ODE_Frame_BodyFromEntity(world, ed); - } - // oh, and it must be called after all bodies were created - for (i = 0;i < world->num_edicts;i++) - { - ed = (wedict_t*)EDICT_NUM(world->progs, i); - if (!ed->isfree) - World_ODE_Frame_JointFromEntity(world, ed); + // copy physics properties from entities to physics engine + for (i = 0;i < world->num_edicts;i++) + { + ed = (wedict_t*)EDICT_NUM(world->progs, i); + if (!ed->isfree) + World_ODE_Frame_BodyFromEntity(world, ed); + } + // oh, and it must be called after all bodies were created + for (i = 0;i < world->num_edicts;i++) + { + ed = (wedict_t*)EDICT_NUM(world->progs, i); + if (!ed->isfree) + World_ODE_Frame_JointFromEntity(world, ed); + } } for (i = 0;i < world->ode.ode_iterations;i++) @@ -2379,12 +2367,15 @@ void World_ODE_Frame(world_t *world, double frametime, double gravity) dJointGroupEmpty(world->ode.ode_contactgroup); } - // copy physics properties from physics engine to entities - for (i = 1;i < world->num_edicts;i++) + if (world->ode.hasodeents) { - ed = (wedict_t*)EDICT_NUM(world->progs, i); - if (!ed->isfree) - World_ODE_Frame_BodyToEntity(world, ed); + // copy physics properties from physics engine to entities + for (i = 1;i < world->num_edicts;i++) + { + ed = (wedict_t*)EDICT_NUM(world->progs, i); + if (!ed->isfree) + World_ODE_Frame_BodyToEntity(world, ed); + } } } } diff --git a/engine/common/common.c b/engine/common/common.c index afb5e2b1a..a452e9a09 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -644,7 +644,7 @@ void deleetstring(char *result, char *leet) char *s2 = leet; while(*s2) { - if (*s2 == 0xff) + if (*s2 == (char)0xff) { s2++; continue; @@ -3192,8 +3192,11 @@ void COM_Version_f (void) #ifdef GLQUAKE Con_Printf("OpenGL available\n"); #endif -#ifdef D3DQUAKE - Con_Printf("Direct3D available\n"); +#ifdef D3D9QUAKE + Con_Printf("Direct3D9 available\n"); +#endif +#ifdef D3D11QUAKE + Con_Printf("Direct3D11 available\n"); #endif #ifdef QCJIT @@ -3342,6 +3345,11 @@ void COM_CrashMe_f(void) *crashaddr = 0; } +void COM_ErrorMe_f(void) +{ + Sys_Error("\"errorme\" command used"); +} + /* ================ COM_Init @@ -3379,6 +3387,7 @@ void COM_Init (void) Cmd_AddCommand ("version", COM_Version_f); //prints the pak or whatever where this file can be found. Cmd_AddCommand ("crashme", COM_CrashMe_f); + Cmd_AddCommand ("errorme", COM_ErrorMe_f); COM_InitFilesystem (); COM_CheckRegistered (); @@ -4442,5 +4451,5 @@ void COM_TimeOfDay(date_t *date) date->min = newtime->tm_min; date->sec = newtime->tm_sec; strftime( date->str, 128, - "%a %b %d, %H:%M:%S %Y", newtime); + "%a %b %d, %H:%M:%S %Y", newtime); } diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index 90454562e..d8963c1fb 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -1,5 +1,5 @@ #include "quakedef.h" -#if defined(GLQUAKE) || defined(D3DQUAKE) +#ifndef SERVERONLY #include "glquake.h" #endif #include "com_mesh.h" @@ -1374,12 +1374,8 @@ qboolean CMod_LoadFaces (lump_t *l) i = LittleLong(in->lightofs); if (i == -1) out->samples = NULL; -#if defined(GLQUAKE) || defined(D3DQUAKE) - else if (qrenderer == QR_OPENGL || qrenderer == QR_DIRECT3D) - out->samples = loadmodel->lightdata + i; -#endif else - out->samples = loadmodel->lightdata + i/3; + out->samples = loadmodel->lightdata + i; // set the drawing flags @@ -2274,7 +2270,7 @@ qboolean CModRBSP_LoadFaces (lump_t *l) return true; } -#if defined(GLQUAKE) || defined(D3DQUAKE) +#ifndef SERVERONLY /* ================= @@ -2500,15 +2496,7 @@ void CModRBSP_BuildSurfMesh(model_t *mod, msurface_t *out, void *cookie) if (LittleLong(in->facetype) == MST_PATCH) { -// out->mesh->numindexes = 0; -// out->mesh->numvertexes = 0; - //FIXME GL_CreateMeshForPatch(loadmodel, out->mesh, LittleLong(in->patchwidth), LittleLong(in->patchheight), LittleLong(in->num_vertices), LittleLong(in->firstvertex)); -// if (out->mesh) -// { -// Mod_AccumulateMeshTextureVectors(out->mesh); -// Mod_NormaliseTextureVectors(out->mesh->normals_array, out->mesh->snormals_array, out->mesh->tnormals_array, out->mesh->numvertexes); -// } } else if (LittleLong(in->facetype) == MST_PLANAR || LittleLong(in->facetype) == MST_TRIANGLE_SOUP) { @@ -2530,35 +2518,6 @@ void CModRBSP_BuildSurfMesh(model_t *mod, msurface_t *out, void *cookie) { out->mesh->indexes[i] = map_surfindexes[fv + i]; } - -/* numindexes = LittleLong(in->num_indexes); - numverts = LittleLong(in->num_vertices); - if (numindexes%3 || numindexes < 0 || numverts < 0) - { - Con_Printf(CON_ERROR "mesh indexes should be multiples of 3\n"); - return false; - } - - out->mesh = Hunk_Alloc(sizeof(mesh_t)); - out->mesh->normals_array= map_normals_array + LittleLong(in->firstvertex); - out->mesh->snormals_array = map_svector_array + LittleLong(in->firstvertex); - out->mesh->tnormals_array = map_tvector_array + LittleLong(in->firstvertex); - - out->mesh->colors4f_array = map_colors4f_array + LittleLong(in->firstvertex); - out->mesh->indexes = map_surfindexes + LittleLong(in->firstindex); - out->mesh->xyz_array = map_verts + LittleLong(in->firstvertex); - out->mesh->st_array = map_vertstmexcoords + LittleLong(in->firstvertex); - out->mesh->lmst_array = map_vertlstmexcoords + LittleLong(in->firstvertex); - - out->mesh->numindexes = numindexes; - out->mesh->numvertexes = numverts; - - if (LittleLong(in->facetype) == MST_PLANAR) - if (out->mesh->numindexes == (out->mesh->numvertexes-2)*3) - out->mesh->istrifan = true; - - Mod_AccumulateMeshTextureVectors(out->mesh); -*/ } else { @@ -3454,7 +3413,7 @@ int CM_GetQ2Palette (void) FS_FreeFile(f); -#if defined(GLQUAKE) || defined(D3DQUAKE) +#if 1 { float inf; qbyte palette[768]; @@ -3858,153 +3817,135 @@ cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned *c Q1BSPX_Setup(loadmodel, mod_base, com_filesize, header.lumps, Q3LUMPS_TOTAL); - switch(qrenderer) + mapisq3 = true; + noerrors = noerrors && CModQ3_LoadShaders (&header.lumps[Q3LUMP_SHADERS]); + noerrors = noerrors && CModQ3_LoadPlanes (&header.lumps[Q3LUMP_PLANES]); + noerrors = noerrors && CModQ3_LoadLeafBrushes (&header.lumps[Q3LUMP_LEAFBRUSHES]); + noerrors = noerrors && CModQ3_LoadBrushes (&header.lumps[Q3LUMP_BRUSHES]); + if (header.version == 1) + { + noerrors = noerrors && CModRBSP_LoadBrushSides (&header.lumps[Q3LUMP_BRUSHSIDES]); + noerrors = noerrors && CModRBSP_LoadVertexes (&header.lumps[Q3LUMP_DRAWVERTS]); + } + else + { + noerrors = noerrors && CModQ3_LoadBrushSides (&header.lumps[Q3LUMP_BRUSHSIDES]); + noerrors = noerrors && CModQ3_LoadVertexes (&header.lumps[Q3LUMP_DRAWVERTS]); + } + if (header.version == 1) + noerrors = noerrors && CModRBSP_LoadFaces (&header.lumps[Q3LUMP_SURFACES]); + else + noerrors = noerrors && CModQ3_LoadFaces (&header.lumps[Q3LUMP_SURFACES]); +#ifndef SERVERONLY + if (qrenderer != QR_NONE) { -#if defined(GLQUAKE) - case QR_OPENGL: -#endif -#if defined(D3DQUAKE) - case QR_DIRECT3D: -#endif - case QR_NONE: //dedicated only - mapisq3 = true; - noerrors = noerrors && CModQ3_LoadShaders (&header.lumps[Q3LUMP_SHADERS]); - noerrors = noerrors && CModQ3_LoadPlanes (&header.lumps[Q3LUMP_PLANES]); - noerrors = noerrors && CModQ3_LoadLeafBrushes (&header.lumps[Q3LUMP_LEAFBRUSHES]); - noerrors = noerrors && CModQ3_LoadBrushes (&header.lumps[Q3LUMP_BRUSHES]); - if (header.version == 1) - { - noerrors = noerrors && CModRBSP_LoadBrushSides (&header.lumps[Q3LUMP_BRUSHSIDES]); - noerrors = noerrors && CModRBSP_LoadVertexes (&header.lumps[Q3LUMP_DRAWVERTS]); - } - else - { - noerrors = noerrors && CModQ3_LoadBrushSides (&header.lumps[Q3LUMP_BRUSHSIDES]); - noerrors = noerrors && CModQ3_LoadVertexes (&header.lumps[Q3LUMP_DRAWVERTS]); - } - if (header.version == 1) - noerrors = noerrors && CModRBSP_LoadFaces (&header.lumps[Q3LUMP_SURFACES]); - else - noerrors = noerrors && CModQ3_LoadFaces (&header.lumps[Q3LUMP_SURFACES]); -#if defined(GLQUAKE) || defined(D3DQUAKE) - if (qrenderer != QR_NONE) - { - if (noerrors) - RMod_LoadLighting (&header.lumps[Q3LUMP_LIGHTMAPS]); //fixme: duplicated loading. - if (header.version == 1) - noerrors = noerrors && CModRBSP_LoadLightgrid (&header.lumps[Q3LUMP_LIGHTGRID], &header.lumps[RBSPLUMP_LIGHTINDEXES]); - else - noerrors = noerrors && CModQ3_LoadLightgrid (&header.lumps[Q3LUMP_LIGHTGRID]); - noerrors = noerrors && CModQ3_LoadIndexes (&header.lumps[Q3LUMP_DRAWINDEXES]); - - if (header.version != Q3BSPVERSION+1) - noerrors = noerrors && CModQ3_LoadFogs (&header.lumps[Q3LUMP_FOGS]); - else - map_numfogs = 0; - - buildcookie = (void *)(mod_base + header.lumps[Q3LUMP_SURFACES].fileofs); - if (header.version == 1) - { - noerrors = noerrors && CModRBSP_LoadRFaces (&header.lumps[Q3LUMP_SURFACES]); - buildmeshes = CModRBSP_BuildSurfMesh; - } - else - { - noerrors = noerrors && CModQ3_LoadRFaces (&header.lumps[Q3LUMP_SURFACES]); - buildmeshes = CModQ3_BuildSurfMesh; - } - noerrors = noerrors && CModQ3_LoadMarksurfaces (&header.lumps[Q3LUMP_LEAFSURFACES]); //fixme: duplicated loading. - - /*make sure all textures have a shader*/ - for (i=0; inumtextures; i++) - { - if (!loadmodel->textures[i]->shader) - loadmodel->textures[i]->shader = R_RegisterShader_Lightmap(loadmodel->textures[i]->name); - } - } -#endif - noerrors = noerrors && CModQ3_LoadLeafFaces (&header.lumps[Q3LUMP_LEAFSURFACES]); - noerrors = noerrors && CModQ3_LoadLeafs (&header.lumps[Q3LUMP_LEAFS]); - noerrors = noerrors && CModQ3_LoadNodes (&header.lumps[Q3LUMP_NODES]); - noerrors = noerrors && CModQ3_LoadSubmodels (&header.lumps[Q3LUMP_MODELS]); - noerrors = noerrors && CModQ3_LoadVisibility (&header.lumps[Q3LUMP_VISIBILITY]); if (noerrors) - CMod_LoadEntityString (&header.lumps[Q3LUMP_ENTITIES]); + RMod_LoadLighting (&header.lumps[Q3LUMP_LIGHTMAPS]); //fixme: duplicated loading. + if (header.version == 1) + noerrors = noerrors && CModRBSP_LoadLightgrid (&header.lumps[Q3LUMP_LIGHTGRID], &header.lumps[RBSPLUMP_LIGHTINDEXES]); + else + noerrors = noerrors && CModQ3_LoadLightgrid (&header.lumps[Q3LUMP_LIGHTGRID]); + noerrors = noerrors && CModQ3_LoadIndexes (&header.lumps[Q3LUMP_DRAWINDEXES]); - if (!noerrors) + if (header.version != Q3BSPVERSION+1) + noerrors = noerrors && CModQ3_LoadFogs (&header.lumps[Q3LUMP_FOGS]); + else + map_numfogs = 0; + + buildcookie = (void *)(mod_base + header.lumps[Q3LUMP_SURFACES].fileofs); + if (header.version == 1) { - if (map_faces) - BZ_Free(map_faces); - if (map_leaffaces) - BZ_Free(map_leaffaces); - - Hunk_FreeToLowMark(start); - return NULL; + noerrors = noerrors && CModRBSP_LoadRFaces (&header.lumps[Q3LUMP_SURFACES]); + buildmeshes = CModRBSP_BuildSurfMesh; } + else + { + noerrors = noerrors && CModQ3_LoadRFaces (&header.lumps[Q3LUMP_SURFACES]); + buildmeshes = CModQ3_BuildSurfMesh; + } + noerrors = noerrors && CModQ3_LoadMarksurfaces (&header.lumps[Q3LUMP_LEAFSURFACES]); //fixme: duplicated loading. + + /*make sure all textures have a shader*/ + for (i=0; inumtextures; i++) + { + if (!loadmodel->textures[i]->shader) + loadmodel->textures[i]->shader = R_RegisterShader_Lightmap(loadmodel->textures[i]->name); + } + } +#endif + noerrors = noerrors && CModQ3_LoadLeafFaces (&header.lumps[Q3LUMP_LEAFSURFACES]); + noerrors = noerrors && CModQ3_LoadLeafs (&header.lumps[Q3LUMP_LEAFS]); + noerrors = noerrors && CModQ3_LoadNodes (&header.lumps[Q3LUMP_NODES]); + noerrors = noerrors && CModQ3_LoadSubmodels (&header.lumps[Q3LUMP_MODELS]); + noerrors = noerrors && CModQ3_LoadVisibility (&header.lumps[Q3LUMP_VISIBILITY]); + if (noerrors) + CMod_LoadEntityString (&header.lumps[Q3LUMP_ENTITIES]); + + if (!noerrors) + { + if (map_faces) + BZ_Free(map_faces); + if (map_leaffaces) + BZ_Free(map_leaffaces); + + Hunk_FreeToLowMark(start); + return NULL; + } #ifndef CLIENTONLY - loadmodel->funcs.FatPVS = Q2BSP_FatPVS; - loadmodel->funcs.EdictInFatPVS = Q2BSP_EdictInFatPVS; - loadmodel->funcs.FindTouchedLeafs = Q2BSP_FindTouchedLeafs; + loadmodel->funcs.FatPVS = Q2BSP_FatPVS; + loadmodel->funcs.EdictInFatPVS = Q2BSP_EdictInFatPVS; + loadmodel->funcs.FindTouchedLeafs = Q2BSP_FindTouchedLeafs; #endif - loadmodel->funcs.LeafPVS = CM_LeafnumPVS; - loadmodel->funcs.LeafnumForPoint = CM_PointLeafnum; - -#if defined(GLQUAKE) || defined(D3DQUAKE) - loadmodel->funcs.LightPointValues = GLQ3_LightGrid; - loadmodel->funcs.StainNode = GLR_Q2BSP_StainNode; - loadmodel->funcs.MarkLights = Q2BSP_MarkLights; -#endif - loadmodel->funcs.PointContents = Q2BSP_PointContents; - loadmodel->funcs.NativeTrace = CM_NativeTrace; - loadmodel->funcs.NativeContents = CM_NativeContents; + loadmodel->funcs.LeafPVS = CM_LeafnumPVS; + loadmodel->funcs.LeafnumForPoint = CM_PointLeafnum; #ifndef SERVERONLY - //light grid info - if (loadmodel->lightgrid) + loadmodel->funcs.LightPointValues = GLQ3_LightGrid; + loadmodel->funcs.StainNode = GLR_Q2BSP_StainNode; + loadmodel->funcs.MarkLights = Q2BSP_MarkLights; +#endif + loadmodel->funcs.PointContents = Q2BSP_PointContents; + loadmodel->funcs.NativeTrace = CM_NativeTrace; + loadmodel->funcs.NativeContents = CM_NativeContents; + +#ifndef SERVERONLY + //light grid info + if (loadmodel->lightgrid) + { + float maxs; + q3lightgridinfo_t *lg = loadmodel->lightgrid; + if ( lg->gridSize[0] < 1 || lg->gridSize[1] < 1 || lg->gridSize[2] < 1 ) { - float maxs; - q3lightgridinfo_t *lg = loadmodel->lightgrid; - if ( lg->gridSize[0] < 1 || lg->gridSize[1] < 1 || lg->gridSize[2] < 1 ) - { - lg->gridSize[0] = 64; - lg->gridSize[1] = 64; - lg->gridSize[2] = 128; - } - - for ( i = 0; i < 3; i++ ) - { - lg->gridMins[i] = lg->gridSize[i] * ceil( (map_cmodels->mins[i] + 1) / lg->gridSize[i] ); - maxs = lg->gridSize[i] * floor( (map_cmodels->maxs[i] - 1) / lg->gridSize[i] ); - lg->gridBounds[i] = (maxs - lg->gridMins[i])/lg->gridSize[i] + 1; - } - - lg->gridBounds[3] = lg->gridBounds[1] * lg->gridBounds[0]; + lg->gridSize[0] = 64; + lg->gridSize[1] = 64; + lg->gridSize[2] = 128; } + + for ( i = 0; i < 3; i++ ) + { + lg->gridMins[i] = lg->gridSize[i] * ceil( (map_cmodels->mins[i] + 1) / lg->gridSize[i] ); + maxs = lg->gridSize[i] * floor( (map_cmodels->maxs[i] - 1) / lg->gridSize[i] ); + lg->gridBounds[i] = (maxs - lg->gridMins[i])/lg->gridSize[i] + 1; + } + + lg->gridBounds[3] = lg->gridBounds[1] * lg->gridBounds[0]; + } #endif - if (!CM_CreatePatchesForLeafs ()) //for clipping - { - BZ_Free(map_faces); - BZ_Free(map_leaffaces); - Hunk_FreeToLowMark(start); - return NULL; - } -#ifndef CLIENTONLY - CMQ3_CalcPHS(); -#endif -// BZ_Free(map_verts); + if (!CM_CreatePatchesForLeafs ()) //for clipping + { BZ_Free(map_faces); BZ_Free(map_leaffaces); - break; - default: -#ifdef SERVERONLY - SV_Error("Cannot load q3bsps with the current renderer (only dedicated and opengl renderer)\n"); -#else - Con_Printf(CON_ERROR "Cannot load q3bsps with the current renderer (only dedicated and opengl renderer)\n"); + Hunk_FreeToLowMark(start); return NULL; -#endif } +#ifndef CLIENTONLY + CMQ3_CalcPHS(); +#endif +// BZ_Free(map_verts); + BZ_Free(map_faces); + BZ_Free(map_leaffaces); break; #endif case Q2BSPVERSION: @@ -4056,7 +3997,8 @@ cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned *c break; #if defined(GLQUAKE) || defined(D3DQUAKE) - case QR_DIRECT3D: + case QR_DIRECT3D9: + case QR_DIRECT3D11: case QR_OPENGL: // load into heap #ifndef SERVERONLY @@ -4243,21 +4185,21 @@ char *CM_EntityString (model_t *model) int CM_LeafContents (model_t *model, int leafnum) { - if (leafnum < 0 || leafnum >= numleafs) + if (leafnum < 0 || leafnum >= model->numleafs) Host_Error ("CM_LeafContents: bad number"); return map_leafs[leafnum].contents; } int CM_LeafCluster (model_t *model, int leafnum) { - if (leafnum < 0 || leafnum >= numleafs) + if (leafnum < 0 || leafnum >= model->numleafs) Host_Error ("CM_LeafCluster: bad number"); return map_leafs[leafnum].cluster; } int CM_LeafArea (model_t *model, int leafnum) { - if (leafnum < 0 || leafnum >= numleafs) + if (leafnum < 0 || leafnum >= model->numleafs) Host_Error ("CM_LeafArea: bad number"); return map_leafs[leafnum].area; } diff --git a/engine/common/mathlib.h b/engine/common/mathlib.h index 5caa95478..09a4a40d3 100644 --- a/engine/common/mathlib.h +++ b/engine/common/mathlib.h @@ -69,15 +69,15 @@ extern vec3_t vec3_origin; #define VectorCopy(a,b) do{(b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];}while(0) #define VectorScale(a,s,b) do{(b)[0]=(s)*(a)[0];(b)[1]=(s)*(a)[1];(b)[2]=(s)*(a)[2];}while(0) #define VectorClear(a) ((a)[0]=(a)[1]=(a)[2]=0) -#define VectorSet(r,x,y,z) {(r)[0] = x; (r)[1] = y;(r)[2] = z;} +#define VectorSet(r,x,y,z) do{(r)[0] = x; (r)[1] = y;(r)[2] = z;}while(0) #define VectorNegate(a,b) ((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2]) #define VectorLength(a) Length(a) #define VectorMA(a,s,b,c) do{(c)[0] = (a)[0] + (s)*(b)[0];(c)[1] = (a)[1] + (s)*(b)[1];(c)[2] = (a)[2] + (s)*(b)[2];}while(0) #define VectorEquals(a,b) ((a)[0] == (b)[0] && (a)[1] == (b)[1] && (a)[2] == (b)[2]) #define VectorAvg(a,b,c) ((c)[0]=((a)[0]+(b)[0])*0.5f,(c)[1]=((a)[1]+(b)[1])*0.5f, (c)[2]=((a)[2]+(b)[2])*0.5f) #define VectorInterpolate(a, bness, b, c) FloatInterpolate((a)[0], bness, (b)[0], (c)[0]),FloatInterpolate((a)[1], bness, (b)[1], (c)[1]),FloatInterpolate((a)[2], bness, (b)[2], (c)[2]) -#define Vector2Copy(a,b) {(b)[0]=(a)[0];(b)[1]=(a)[1];} -#define Vector2Set(r,x,y) {(r)[0] = x; (r)[1] = y;} +#define Vector2Copy(a,b) do{(b)[0]=(a)[0];(b)[1]=(a)[1];}while(0) +#define Vector2Set(r,x,y) do{(r)[0] = x; (r)[1] = y;}while(0) #define Vector2Interpolate(a, bness, b, c) FloatInterpolate((a)[0], bness, (b)[0], (c)[0]),FloatInterpolate((a)[1], bness, (b)[1], (c)[1]) #define Vector4Copy(a,b) do{(b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];(b)[3]=(a)[3];}while(0) diff --git a/engine/common/net.h b/engine/common/net.h index 7843ec169..3bc459d9e 100644 --- a/engine/common/net.h +++ b/engine/common/net.h @@ -257,6 +257,7 @@ void Huff_EmitByte(int ch, qbyte *buffer, int *count); #define RMQFL_FLOATCOORD (1 << 4) #define RMQFL_EDICTSCALE (1 << 5) #define RMQFL_ALPHASANITY (1 << 6) +#define RMQFL_INT32COORD (1 << 7) #define RMQFL_MOREFLAGS (1 << 31) #endif diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index 3083cbd50..cedf69b15 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -2655,9 +2655,16 @@ qboolean FTENET_TCPConnect_SendPacket(ftenet_generic_connection_t *gcon, int len case TCPC_QIZMO: { unsigned short slen = BigShort((unsigned short)length); - #pragma warningmsg("TCPConnect: these calls can fail half way through the write, corrupting the message stream") - send(st->socketnum, (char*)&slen, sizeof(slen), 0); - send(st->socketnum, data, length, 0); + if (st->outlen + sizeof(slen) + length > sizeof(st->outbuffer)) + { + Con_DPrintf("FTENET_TCPConnect_SendPacket: outgoing overflow\n"); + } + else + { + memcpy(st->outbuffer + st->outlen, &slen, sizeof(slen)); + memcpy(st->outbuffer + st->outlen + sizeof(slen), data, length); + st->outlen += sizeof(slen) + length; + } } break; case TCPC_WEBSOCKET: diff --git a/engine/common/netinc.h b/engine/common/netinc.h index 68f2cc7e9..2b112bef4 100644 --- a/engine/common/netinc.h +++ b/engine/common/netinc.h @@ -42,7 +42,7 @@ #include #ifndef IPPROTO_IPV6 /*for msvc6*/ - #define IPPROTO_IPV6 + #define IPPROTO_IPV6 41 #ifndef EAI_NONAME #define EAI_NONAME 8 diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index 30bafcbf9..de38869bc 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -87,7 +87,7 @@ char *PF_VarString (progfuncs_t *prinst, int first, struct globalvars_s *pr_glob #define MAX_TEMPSTRS ((int)pr_tempstringcount.value) #define MAXTEMPBUFFERLEN ((int)pr_tempstringsize.value) -string_t PR_TempString(progfuncs_t *prinst, char *str) +string_t PR_TempString(progfuncs_t *prinst, const char *str) { char *tmp; if (!prinst->tempstringbase) @@ -370,6 +370,61 @@ void QCBUILTIN PF_getsurfaceclippedpoint(progfuncs_t *prinst, struct globalvars_ { } +// #628 float(entity e, float s) getsurfacenumtriangles +void QCBUILTIN PF_getsurfacenumtriangles(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + unsigned int surfnum; + model_t *model; + wedict_t *ent; + world_t *w = prinst->parms->user; + + ent = G_WEDICT(prinst, OFS_PARM0); + surfnum = G_FLOAT(OFS_PARM1); + + model = w->Get_CModel(w, ent->v->modelindex); + + if (!model || model->type != mod_brush || surfnum >= model->nummodelsurfaces) + { + G_FLOAT(OFS_RETURN) = 0; + } + else + { + surfnum += model->firstmodelsurface; + G_FLOAT(OFS_RETURN) = model->surfaces[surfnum].mesh->numindexes/3; + } +} +// #629 float(entity e, float s) getsurfacetriangle +void QCBUILTIN PF_getsurfacetriangle(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + unsigned int surfnum, firstidx; + model_t *model; + wedict_t *ent; + world_t *w = prinst->parms->user; + + ent = G_WEDICT(prinst, OFS_PARM0); + surfnum = G_FLOAT(OFS_PARM1); + firstidx = G_FLOAT(OFS_PARM2)*3; + + model = w->Get_CModel(w, ent->v->modelindex); + + if (model && model->type == mod_brush && surfnum < model->nummodelsurfaces) + { + surfnum += model->firstmodelsurface; + + if (firstidx+2 < model->surfaces[surfnum].mesh->numindexes) + { + G_FLOAT(OFS_RETURN+0) = model->surfaces[surfnum].mesh->indexes[firstidx+0]; + G_FLOAT(OFS_RETURN+1) = model->surfaces[surfnum].mesh->indexes[firstidx+1]; + G_FLOAT(OFS_RETURN+2) = model->surfaces[surfnum].mesh->indexes[firstidx+2]; + return; + } + } + + G_FLOAT(OFS_RETURN+0) = 0; + G_FLOAT(OFS_RETURN+1) = 0; + G_FLOAT(OFS_RETURN+2) = 0; +} + #ifndef TERRAIN void QCBUILTIN PF_terrain_edit(progfuncs_t *prinst, struct globalvars_s *pr_globals) { @@ -2155,10 +2210,30 @@ struct strbuf { #define NUMSTRINGBUFS 16 struct strbuf strbuflist[NUMSTRINGBUFS]; +void PF_buf_shutdown(progfuncs_t *prinst) +{ + int i, bufno; + + for (bufno = 0; bufno < NUMSTRINGBUFS; bufno++) + { + if (strbuflist[bufno].prinst == prinst) + { + for (i = 0; i < strbuflist[bufno].used; i++) + Z_Free(strbuflist[bufno].strings[i]); + Z_Free(strbuflist[bufno].strings); + + strbuflist[bufno].strings = NULL; + strbuflist[bufno].used = 0; + strbuflist[bufno].allocated = 0; + + strbuflist[bufno].prinst = NULL; + } + } +} + // #440 float() buf_create (DP_QC_STRINGBUFFERS) void QCBUILTIN PF_buf_create (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - int i; for (i = 0; i < NUMSTRINGBUFS; i++) @@ -2300,6 +2375,8 @@ void QCBUILTIN PF_bufstr_set (progfuncs_t *prinst, struct globalvars_s *pr_glob strbuflist[bufno].strings = BZ_Realloc(strbuflist[bufno].strings, strbuflist[bufno].allocated*sizeof(char*)); memset(strbuflist[bufno].strings+oldcount, 0, (strbuflist[bufno].allocated - oldcount) * sizeof(char*)); } + if (strbuflist[bufno].strings[index]) + Z_Free(strbuflist[bufno].strings[index]); strbuflist[bufno].strings[index] = Z_Malloc(strlen(string)+1); strcpy(strbuflist[bufno].strings[index], string); diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index 16de02a24..c87e6605a 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -83,7 +83,7 @@ void VARGS PR_CB_Free(void *mem); void PF_InitTempStrings(progfuncs_t *prinst); -string_t PR_TempString(progfuncs_t *prinst, char *str); //returns a tempstring containing str +string_t PR_TempString(progfuncs_t *prinst, const char *str); //returns a tempstring containing str char *PF_TempStr(progfuncs_t *prinst); //returns a tempstring which can be filled in with whatever junk you want. #define RETURN_SSTRING(s) (((int *)pr_globals)[OFS_RETURN] = PR_SetString(prinst, s)) //static - exe will not change it. @@ -188,6 +188,8 @@ void QCBUILTIN PF_getsurfacenormal(progfuncs_t *prinst, struct globalvars_s *pr_ void QCBUILTIN PF_getsurfacetexture(progfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_getsurfacenearpoint(progfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_getsurfaceclippedpoint(progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_getsurfacenumtriangles(progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_getsurfacetriangle(progfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_skel_set_bone_world (progfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_skel_mmap(progfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_skel_ragedit(progfuncs_t *prinst, struct globalvars_s *pr_globals); @@ -204,6 +206,11 @@ void QCBUILTIN PF_skel_mul_bone (progfuncs_t *prinst, struct globalvars_s *pr_gl void QCBUILTIN PF_skel_mul_bones (progfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_skel_copybones (progfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_skel_delete (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_frametoname (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_skintoname (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_frameforname (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_frameduration (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_skinforname (progfuncs_t *prinst, struct globalvars_s *pr_globals); void skel_lookup(progfuncs_t *prinst, int skelidx, framestate_t *out); void skel_dodelete(progfuncs_t *prinst); void skel_reset(progfuncs_t *prinst); diff --git a/engine/common/protocol.h b/engine/common/protocol.h index af3c0e5fc..6d5d7235f 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -149,7 +149,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define svc_bad 0 #define svc_nop 1 #define svc_disconnect 2 -#define svc_updatestat 3 // [qbyte] [qbyte] +#define svcqw_updatestatbyte 3 // [qbyte] [qbyte] +#define svcnq_updatestatlong 3 // [qbyte] [long] #define svc_version 4 // [long] server version #define svc_setview 5 // [short] entity number #define svc_sound 6 // @@ -201,7 +202,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define svc_updateping 36 // [qbyte] [short] #define svc_updateentertime 37 // [qbyte] [float] -#define svc_updatestatlong 38 // [qbyte] [long] +#define svcqw_updatestatlong 38 // [qbyte] [long] #define svc_muzzleflash 39 // [short] entity diff --git a/engine/common/unzip.c b/engine/common/unzip.c index 6d7bbea2c..780b4895c 100644 --- a/engine/common/unzip.c +++ b/engine/common/unzip.c @@ -283,7 +283,6 @@ extern unzFile ZEXPORT unzOpen (vfsfile_t *fin) { if ((central_pos + +extern ID3D11Device *pD3DDev11; +extern ID3D11DeviceContext *d3ddevctx; + +//#define d3dcheck(foo) foo +#define d3dcheck(foo) do{HRESULT err = foo; if (FAILED(err)) Sys_Error("D3D reported error on backend line %i - error 0x%x\n", __LINE__, (unsigned int)err);} while(0) + +#define MAX_TMUS 8 + +extern float d3d_trueprojection[16]; + +static void BE_RotateForEntity (const entity_t *e, const model_t *mod); + +/*========================================== tables for deforms =====================================*/ +#if 0 +#define frand() (rand()*(1.0/RAND_MAX)) +#define FTABLE_SIZE 1024 +#define FTABLE_CLAMP(x) (((int)((x)*FTABLE_SIZE) & (FTABLE_SIZE-1))) +#define FTABLE_EVALUATE(table,x) (table ? table[FTABLE_CLAMP(x)] : frand()*((x)-floor(x))) + +static float r_sintable[FTABLE_SIZE]; +static float r_triangletable[FTABLE_SIZE]; +static float r_squaretable[FTABLE_SIZE]; +static float r_sawtoothtable[FTABLE_SIZE]; +static float r_inversesawtoothtable[FTABLE_SIZE]; + +static float *FTableForFunc ( unsigned int func ) +{ + switch (func) + { + case SHADER_FUNC_SIN: + return r_sintable; + + case SHADER_FUNC_TRIANGLE: + return r_triangletable; + + case SHADER_FUNC_SQUARE: + return r_squaretable; + + case SHADER_FUNC_SAWTOOTH: + return r_sawtoothtable; + + case SHADER_FUNC_INVERSESAWTOOTH: + return r_inversesawtoothtable; + } + + //bad values allow us to crash (so I can debug em) + return NULL; +} + +static void FTable_Init(void) +{ + unsigned int i; + double t; + for (i = 0; i < FTABLE_SIZE; i++) + { + t = (double)i / (double)FTABLE_SIZE; + + r_sintable[i] = sin(t * 2*M_PI); + + if (t < 0.25) + r_triangletable[i] = t * 4.0; + else if (t < 0.75) + r_triangletable[i] = 2 - 4.0 * t; + else + r_triangletable[i] = (t - 0.75) * 4.0 - 1.0; + + if (t < 0.5) + r_squaretable[i] = 1.0f; + else + r_squaretable[i] = -1.0f; + + r_sawtoothtable[i] = t; + r_inversesawtoothtable[i] = 1.0 - t; + } +} + +typedef vec3_t mat3_t[3]; +static mat3_t axisDefault={{1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}}; + +static void Matrix3_Transpose (mat3_t in, mat3_t out) +{ + out[0][0] = in[0][0]; + out[1][1] = in[1][1]; + out[2][2] = in[2][2]; + + out[0][1] = in[1][0]; + out[0][2] = in[2][0]; + out[1][0] = in[0][1]; + out[1][2] = in[2][1]; + out[2][0] = in[0][2]; + out[2][1] = in[1][2]; +} +static void Matrix3_Multiply_Vec3 (const mat3_t a, const vec3_t b, vec3_t product) +{ + product[0] = a[0][0]*b[0] + a[0][1]*b[1] + a[0][2]*b[2]; + product[1] = a[1][0]*b[0] + a[1][1]*b[1] + a[1][2]*b[2]; + product[2] = a[2][0]*b[0] + a[2][1]*b[1] + a[2][2]*b[2]; +} + +static int Matrix3_Compare(const mat3_t in, const mat3_t out) +{ + return !memcmp(in, out, sizeof(mat3_t)); +} +#endif +/*================================================*/ + +//global constant-buffer +typedef struct +{ + float m_view[16]; + float m_projection[16]; + vec3_t v_eyepos; + float v_time; +} cbuf_view_t; + +//entity-specific constant-buffer +typedef struct +{ + float m_model[16]; + vec3_t e_eyepos; + float e_time; + vec3_t e_light_ambient; float pad1; + vec3_t e_light_dir; float pad2; + vec3_t e_light_mul; float pad3; +} cbuf_entity_t; + +//vertex attributes +typedef struct +{ + vecV_t coord; + vec2_t tex; + vec2_t lm; + vec3_t ndir; + vec3_t sdir; + vec3_t tdir; + byte_vec4_t colorsb; +} vbovdata_t; + +typedef struct +{ + backendmode_t mode; + unsigned int flags; + + float curtime; + const entity_t *curentity; + const dlight_t *curdlight; + vec3_t curdlight_colours; + shader_t *curshader; + texnums_t *curtexnums; + int curvertdecl; + unsigned int shaderbits; + unsigned int curcull; + float depthbias; + float depthfactor; + float m_model[16]; + unsigned int lastpasscount; + vbo_t *batchvbo; + batch_t *curbatch; + batch_t dummybatch; + + shader_t *shader_rtlight; + texid_t curtex[MAX_TMUS]; + unsigned int tmuflags[MAX_TMUS]; + ID3D11SamplerState *cursamplerstate[MAX_TMUS]; + ID3D11SamplerState *sampstate[(SHADER_PASS_NEAREST|SHADER_PASS_CLAMP)+1]; + + mesh_t **meshlist; + unsigned int nummeshes; + + ID3D11Buffer *cbuffers[2]; + + unsigned int wbatch; + unsigned int maxwbatches; + batch_t *wbatches; +} d3d11backend_t; + +#define DYNVBUFFSIZE 65536 +#define DYNIBUFFSIZE 65536 + +static d3d11backend_t shaderstate; + +extern int be_maxpasses; + +static void BE_CreateSamplerStates(void) +{ + D3D11_SAMPLER_DESC sampdesc; + int flags; + for (flags = 0; flags <= (SHADER_PASS_CLAMP|SHADER_PASS_NEAREST); flags++) + { + if (flags & SHADER_PASS_NEAREST) + sampdesc.Filter = D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR; + else + sampdesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + if (flags & SHADER_PASS_CLAMP) + { + sampdesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + sampdesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + sampdesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + } + else + { + sampdesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + sampdesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + sampdesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + } + sampdesc.MipLODBias = 0.0f; + sampdesc.MaxAnisotropy = 1; + sampdesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + sampdesc.BorderColor[0] = 0; + sampdesc.BorderColor[1] = 0; + sampdesc.BorderColor[2] = 0; + sampdesc.BorderColor[3] = 0; + sampdesc.MinLOD = 0; + sampdesc.MaxLOD = D3D11_FLOAT32_MAX; + + ID3D11Device_CreateSamplerState(pD3DDev11, &sampdesc, &shaderstate.sampstate[flags]); + } +} +static void BE_DestroySamplerStates(void) +{ + int flags; + for (flags = 0; flags <= (SHADER_PASS_CLAMP|SHADER_PASS_NEAREST); flags++) + { + ID3D11SamplerState_Release(shaderstate.sampstate[flags]); + shaderstate.sampstate[flags] = NULL; + } +} + +static void BE_ApplyTMUState(unsigned int tu, unsigned int flags) +{ + ID3D11SamplerState *nstate; + + flags = flags & (SHADER_PASS_CLAMP|SHADER_PASS_NEAREST); + nstate = shaderstate.sampstate[flags]; + if (nstate != shaderstate.cursamplerstate[tu]) + { + shaderstate.cursamplerstate[tu] = nstate; + + //fixme: is it significant to bulk-apply this later? + ID3D11DeviceContext_PSSetSamplers(d3ddevctx, tu, 1, &nstate); + } + /* + if ((flags ^ shaderstate.tmuflags[tu]) & (SHADER_PASS_NEAREST|SHADER_PASS_CLAMP)) + { + D3D11_SAMPLER_DESC sampdesc; + ID3D11SamplerState *sstate; + + shaderstate.tmuflags[tu] = flags; + + if (flags & SHADER_PASS_NEAREST) + sampdesc.Filter = D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR; + else + sampdesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + if (flags & SHADER_PASS_CLAMP) + { + sampdesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + sampdesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + sampdesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + } + else + { + sampdesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + sampdesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + sampdesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + } + sampdesc.MipLODBias = 0.0f; + sampdesc.MaxAnisotropy = 1; + sampdesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + sampdesc.BorderColor[0] = 0; + sampdesc.BorderColor[1] = 0; + sampdesc.BorderColor[2] = 0; + sampdesc.BorderColor[3] = 0; + sampdesc.MinLOD = 0; + sampdesc.MaxLOD = D3D11_FLOAT32_MAX; + + if (!FAILED(ID3D11Device_CreateSamplerState(pD3DDev11, &sampdesc, &sstate))) + { + ID3D11DeviceContext_PSSetSamplers(d3ddevctx, tu, 1, &sstate); + ID3D11SamplerState_Release(sstate); + } + } + */ +} + +static void D3D11BE_ApplyShaderBits(unsigned int bits) +{ + unsigned int delta; + + if (shaderstate.flags & (BEF_FORCEADDITIVE|BEF_FORCETRANSPARENT|BEF_FORCENODEPTH|BEF_FORCEDEPTHTEST|BEF_FORCEDEPTHWRITE)) + { + if (shaderstate.flags & BEF_FORCEADDITIVE) + bits = (bits & ~(SBITS_MISC_DEPTHWRITE|SBITS_BLEND_BITS|SBITS_ATEST_BITS)) + | (SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE); + else if (shaderstate.flags & BEF_FORCETRANSPARENT) + { + if ((bits & SBITS_BLEND_BITS) == (SBITS_SRCBLEND_ONE|SBITS_DSTBLEND_ZERO) || !(bits & SBITS_BLEND_BITS)) /*if transparency is forced, clear alpha test bits*/ + bits = (bits & ~(SBITS_MISC_DEPTHWRITE|SBITS_BLEND_BITS|SBITS_ATEST_BITS)) + | (SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA); + } + + if (shaderstate.flags & BEF_FORCENODEPTH) /*EF_NODEPTHTEST dp extension*/ + bits |= SBITS_MISC_NODEPTHTEST; + else + { + if (shaderstate.flags & BEF_FORCEDEPTHTEST) + bits &= ~SBITS_MISC_NODEPTHTEST; + if (shaderstate.flags & BEF_FORCEDEPTHWRITE) + bits |= SBITS_MISC_DEPTHWRITE; + } + } + + delta = bits ^ shaderstate.shaderbits; + if (!delta) + return; + shaderstate.shaderbits = bits; + + if (delta & (SBITS_BLEND_BITS|SBITS_MASK_BITS)) + { + D3D11_BLEND_DESC blend; + ID3D11BlendState *newblendstate; + blend.IndependentBlendEnable = FALSE; + blend.AlphaToCoverageEnable = FALSE; //FIXME + + if (bits & SBITS_BLEND_BITS) + { + switch(bits & SBITS_SRCBLEND_BITS) + { + case SBITS_SRCBLEND_ZERO: blend.RenderTarget[0].SrcBlend = D3D11_BLEND_ZERO; break; + case SBITS_SRCBLEND_ONE: blend.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE; break; + case SBITS_SRCBLEND_DST_COLOR: blend.RenderTarget[0].SrcBlend = D3D11_BLEND_DEST_COLOR; break; + case SBITS_SRCBLEND_ONE_MINUS_DST_COLOR: blend.RenderTarget[0].SrcBlend = D3D11_BLEND_INV_DEST_COLOR; break; + case SBITS_SRCBLEND_SRC_ALPHA: blend.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; break; + case SBITS_SRCBLEND_ONE_MINUS_SRC_ALPHA: blend.RenderTarget[0].SrcBlend = D3D11_BLEND_INV_SRC_ALPHA; break; + case SBITS_SRCBLEND_DST_ALPHA: blend.RenderTarget[0].SrcBlend = D3D11_BLEND_DEST_ALPHA; break; + case SBITS_SRCBLEND_ONE_MINUS_DST_ALPHA: blend.RenderTarget[0].SrcBlend = D3D11_BLEND_INV_DEST_ALPHA; break; + case SBITS_SRCBLEND_ALPHA_SATURATE: blend.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA_SAT; break; + default: Sys_Error("Bad shader blend src\n"); return; + } + switch(bits & SBITS_DSTBLEND_BITS) + { + case SBITS_DSTBLEND_ZERO: blend.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO; break; + case SBITS_DSTBLEND_ONE: blend.RenderTarget[0].DestBlend = D3D11_BLEND_ONE; break; + case SBITS_DSTBLEND_SRC_ALPHA: blend.RenderTarget[0].DestBlend = D3D11_BLEND_SRC_ALPHA; break; + case SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA: blend.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; break; + case SBITS_DSTBLEND_DST_ALPHA: blend.RenderTarget[0].DestBlend = D3D11_BLEND_DEST_ALPHA; break; + case SBITS_DSTBLEND_ONE_MINUS_DST_ALPHA: blend.RenderTarget[0].DestBlend = D3D11_BLEND_INV_DEST_ALPHA; break; + case SBITS_DSTBLEND_SRC_COLOR: blend.RenderTarget[0].DestBlend = D3D11_BLEND_SRC_COLOR; break; + case SBITS_DSTBLEND_ONE_MINUS_SRC_COLOR: blend.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_COLOR; break; + default: Sys_Error("Bad shader blend dst\n"); return; + } + blend.RenderTarget[0].BlendEnable = TRUE; + } + else + { + blend.RenderTarget[0].SrcBlend = D3D11_BLEND_ZERO; + blend.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO; + blend.RenderTarget[0].BlendEnable = FALSE; + } + blend.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + blend.RenderTarget[0].SrcBlendAlpha = blend.RenderTarget[0].SrcBlend; + blend.RenderTarget[0].DestBlendAlpha = blend.RenderTarget[0].DestBlend; + blend.RenderTarget[0].BlendOpAlpha = blend.RenderTarget[0].BlendOp; + + if (bits&SBITS_MASK_BITS) + { + blend.RenderTarget[0].RenderTargetWriteMask = 0; + if (!(bits&SBITS_MASK_RED)) + blend.RenderTarget[0].RenderTargetWriteMask |= D3D11_COLOR_WRITE_ENABLE_RED; + if (!(bits&SBITS_MASK_GREEN)) + blend.RenderTarget[0].RenderTargetWriteMask |= D3D11_COLOR_WRITE_ENABLE_GREEN; + if (!(bits&SBITS_MASK_BLUE)) + blend.RenderTarget[0].RenderTargetWriteMask |= D3D11_COLOR_WRITE_ENABLE_BLUE; + if (!(bits&SBITS_MASK_ALPHA)) + blend.RenderTarget[0].RenderTargetWriteMask |= D3D11_COLOR_WRITE_ENABLE_ALPHA; + } + else + blend.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; + + + if (!FAILED(ID3D11Device_CreateBlendState(pD3DDev11, &blend, &newblendstate))) + { + ID3D11DeviceContext_OMSetBlendState(d3ddevctx, newblendstate, NULL, 0xffffffff); + ID3D11BlendState_Release(newblendstate); + } + } + + if (delta & SBITS_ATEST_BITS) + { +/* + switch(bits & SBITS_ATEST_BITS) + { + case SBITS_ATEST_NONE: + IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHATESTENABLE, FALSE); + // IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHAREF, 0); + // IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHAFUNC, 0); + break; + case SBITS_ATEST_GT0: + IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHATESTENABLE, TRUE); + IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHAREF, 0); + IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHAFUNC, D3DCMP_GREATER); + break; + case SBITS_ATEST_LT128: + IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHATESTENABLE, TRUE); + IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHAREF, 128); + IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHAFUNC, D3DCMP_LESS); + break; + case SBITS_ATEST_GE128: + IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHATESTENABLE, TRUE); + IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHAREF, 128); + IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL); + break; + } +*/ + } + + if (delta & (SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY|SBITS_MISC_NODEPTHTEST|SBITS_MISC_DEPTHWRITE)) + { + D3D11_DEPTH_STENCIL_DESC depthdesc; + ID3D11DepthStencilState *newdepthstate; + + if (bits & SBITS_MISC_NODEPTHTEST) + depthdesc.DepthEnable = false; + else + depthdesc.DepthEnable = true; + if (bits & SBITS_MISC_DEPTHWRITE) + depthdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + else + depthdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; + + switch(bits & (SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY)) + { + default: + case 0: + depthdesc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; + break; + case SBITS_MISC_DEPTHEQUALONLY: + depthdesc.DepthFunc = D3D11_COMPARISON_EQUAL; + break; + case SBITS_MISC_DEPTHCLOSERONLY: + depthdesc.DepthFunc = D3D11_COMPARISON_LESS; + break; + } + + //make sure the stencil part is actually valid, even if we're not using it. + depthdesc.StencilEnable = false; + depthdesc.StencilReadMask = 0xFF; + depthdesc.StencilWriteMask = 0xFF; + depthdesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthdesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + depthdesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthdesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + depthdesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthdesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + depthdesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthdesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + + //and change it + if (!FAILED(ID3D11Device_CreateDepthStencilState(pD3DDev11, &depthdesc, &newdepthstate))) + { + ID3D11DeviceContext_OMSetDepthStencilState(d3ddevctx, newdepthstate, 0); + ID3D11DepthStencilState_Release(newdepthstate); + } + } +} + +void D3D11BE_Reset(qboolean before) +{ + int i; + if (before) + { + /*backbuffer is going away, release stuff so it can be destroyed cleanly*/ + } + else + { + /*we have a new backbuffer etc, reassert state*/ + for (i = 0; i < MAX_TMUS; i++) + { + shaderstate.tmuflags[i] = ~0; + BE_ApplyTMUState(i, 0); + } + + /*force all state to change, thus setting a known state*/ + shaderstate.shaderbits = ~0; + D3D11BE_ApplyShaderBits(0); + } +} + +static const char LIGHTPASS_SHADER[] = "\ +{\n\ + program rtlight\n\ + {\n\ + map $diffuse\n\ + blendfunc add\n\ + }\n\ + {\n\ + map $normalmap\n\ + }\n\ + {\n\ + map $specular\n\ + }\n\ +}"; + +void D3D11BE_Init(void) +{ + D3D11_BUFFER_DESC bd; + int i; + + be_maxpasses = MAX_TMUS; + memset(&shaderstate, 0, sizeof(shaderstate)); + shaderstate.curvertdecl = -1; + for (i = 0; i < MAXLIGHTMAPS; i++) + shaderstate.dummybatch.lightmap[i] = -1; + + BE_CreateSamplerStates(); + +// FTable_Init(); + +/* shaderstate.dynxyz_size = sizeof(vecV_t) * DYNVBUFFSIZE; + shaderstate.dyncol_size = sizeof(byte_vec4_t) * DYNVBUFFSIZE; + shaderstate.dynst_size = sizeof(vec2_t) * DYNVBUFFSIZE; + shaderstate.dynidx_size = sizeof(index_t) * DYNIBUFFSIZE; +*/ + D3D11BE_Reset(false); + + //set up the constant buffers + bd.Usage = D3D11_USAGE_DYNAMIC; + bd.ByteWidth = sizeof(cbuf_entity_t); + bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bd.MiscFlags = 0; + bd.StructureByteStride = 0; + if (FAILED(ID3D11Device_CreateBuffer(pD3DDev11, &bd, NULL, &shaderstate.cbuffers[0]))) + return; + bd.Usage = D3D11_USAGE_DYNAMIC; + bd.ByteWidth = sizeof(cbuf_view_t); + bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bd.MiscFlags = 0; + bd.StructureByteStride = 0; + if (FAILED(ID3D11Device_CreateBuffer(pD3DDev11, &bd, NULL, &shaderstate.cbuffers[1]))) + return; + + shaderstate.shader_rtlight = R_RegisterShader("rtlight", LIGHTPASS_SHADER); + + R_InitFlashblends(); +} + +void D3D11BE_Shutdown(void) +{ + BE_DestroySamplerStates(); + Z_Free(shaderstate.wbatches); + shaderstate.wbatches = NULL; +} + +#if 0 +static void allocvertexbuffer(ID3D11Buffer *buff, unsigned int bmaxsize, unsigned int *offset, void **data, unsigned int bytes) +{ + unsigned int boff; + if (*offset + bytes > bmaxsize) + { + boff = 0; + *offset = bytes; + } + else + { + boff = *offset; + *offset += bytes; + } +// d3dcheck(IDirect3DVertexBuffer9_Lock(buff, boff, bytes, data, boff?D3DLOCK_NOOVERWRITE:D3DLOCK_DISCARD)); +} + +static unsigned int allocindexbuffer(void **dest, unsigned int entries) +{ + unsigned int bytes = entries*sizeof(index_t); + unsigned int offset; +/* + if (shaderstate.dynidx_offs + bytes > DYNIBUFFSIZE) + { + offset = 0; + shaderstate.dynidx_offs = 0; + } + else + { + offset = shaderstate.dynidx_offs; + shaderstate.dynidx_offs += bytes; + } +*/ +// d3dcheck(IDirect3DIndexBuffer9_Lock(shaderstate.dynidx_buff, offset, (unsigned int)entries, dest, offset?D3DLOCK_NOOVERWRITE:D3DLOCK_DISCARD)); + return offset/sizeof(index_t); +} +#endif + +static void BindTexture(unsigned int tu, void *id) +{ + if (shaderstate.curtex[tu].ptr != id) + { + shaderstate.curtex[tu].ptr = id; + ID3D11DeviceContext_PSSetShaderResources(d3ddevctx, tu, 1, (ID3D11ShaderResourceView**)&id); + } +} + +static void SelectPassTexture(unsigned int tu, shaderpass_t *pass) +{ + switch(pass->texgen) + { + default: + case T_GEN_DIFFUSE: + BindTexture(tu, shaderstate.curtexnums->base.ptr); + break; + case T_GEN_NORMALMAP: + BindTexture( tu, shaderstate.curtexnums->bump.ptr); + break; + case T_GEN_SPECULAR: + BindTexture(tu, shaderstate.curtexnums->specular.ptr); + break; + case T_GEN_UPPEROVERLAY: + BindTexture(tu, shaderstate.curtexnums->upperoverlay.ptr); + break; + case T_GEN_LOWEROVERLAY: + BindTexture(tu, shaderstate.curtexnums->loweroverlay.ptr); + break; + case T_GEN_FULLBRIGHT: + BindTexture(tu, shaderstate.curtexnums->fullbright.ptr); + break; + case T_GEN_ANIMMAP: + BindTexture(tu, pass->anim_frames[(int)(pass->anim_fps * shaderstate.curtime) % pass->anim_numframes].ptr); + break; + case T_GEN_SINGLEMAP: + BindTexture(tu, pass->anim_frames[0].ptr); + break; + case T_GEN_DELUXMAP: + { + int lmi = shaderstate.curbatch->lightmap[0]; + if (lmi < 0 || !lightmap[lmi]->hasdeluxe) + BindTexture(tu, NULL); + else + { + lmi+=1; + BindTexture(tu, lightmap[lmi]->lightmap_texture.ptr); + } + } + break; + case T_GEN_LIGHTMAP: + { + int lmi = shaderstate.curbatch->lightmap[0]; + if (lmi < 0) + BindTexture(tu, NULL); + else + BindTexture(tu, lightmap[lmi]->lightmap_texture.ptr); + } + break; + + /*case T_GEN_CURRENTRENDER: + FIXME: no code to grab the current screen and convert to a texture + break;*/ + case T_GEN_VIDEOMAP: + BindTexture(tu, Media_UpdateForShader(pass->cin).ptr); + break; + } + + BE_ApplyTMUState(tu, pass->flags); + + //pass blend modes are skipped - they're really only useful for fixed function. we should just use blend modes instead. +} + +#if 0 +static void colourgenbyte(const shaderpass_t *pass, int cnt, byte_vec4_t *srcb, vec4_t *srcf, byte_vec4_t *dst, const mesh_t *mesh) +{ +/* + D3DCOLOR block; + switch (pass->rgbgen) + { + case RGB_GEN_ENTITY: + block = D3DCOLOR_COLORVALUE(shaderstate.curentity->shaderRGBAf[0], shaderstate.curentity->shaderRGBAf[1], shaderstate.curentity->shaderRGBAf[2], shaderstate.curentity->shaderRGBAf[3]); + while((cnt)--) + { + ((D3DCOLOR*)dst)[cnt] = block; + } + break; + case RGB_GEN_ONE_MINUS_ENTITY: + block = D3DCOLOR_COLORVALUE(1-shaderstate.curentity->shaderRGBAf[0], 1-shaderstate.curentity->shaderRGBAf[1], 1-shaderstate.curentity->shaderRGBAf[2], 1-shaderstate.curentity->shaderRGBAf[3]); + while((cnt)--) + { + ((D3DCOLOR*)dst)[cnt] = block; + } + break; + case RGB_GEN_VERTEX_LIGHTING: + case RGB_GEN_VERTEX_EXACT: + if (srcb) + { + while((cnt)--) + { + qbyte r, g, b; + r=srcb[cnt][0]; + g=srcb[cnt][1]; + b=srcb[cnt][2]; + dst[cnt][0] = b; + dst[cnt][1] = g; + dst[cnt][2] = r; + } + } + else if (srcf) + { + while((cnt)--) + { + int r, g, b; + r=srcf[cnt][0]*255; + g=srcf[cnt][1]*255; + b=srcf[cnt][2]*255; + dst[cnt][0] = bound(0, b, 255); + dst[cnt][1] = bound(0, g, 255); + dst[cnt][2] = bound(0, r, 255); + } + } + else + goto identity; + break; + case RGB_GEN_ONE_MINUS_VERTEX: + if (srcb) + { + while((cnt)--) + { + qbyte r, g, b; + r=255-srcb[cnt][0]; + g=255-srcb[cnt][1]; + b=255-srcb[cnt][2]; + dst[cnt][0] = b; + dst[cnt][1] = g; + dst[cnt][2] = r; + } + } + else if (srcf) + { + while((cnt)--) + { + int r, g, b; + r=255-srcf[cnt][0]*255; + g=255-srcf[cnt][1]*255; + b=255-srcf[cnt][2]*255; + dst[cnt][0] = bound(0, b, 255); + dst[cnt][1] = bound(0, g, 255); + dst[cnt][2] = bound(0, r, 255); + } + } + else + goto identity; + break; + case RGB_GEN_IDENTITY_LIGHTING: + //compensate for overbrights + block = D3DCOLOR_RGBA(255, 255, 255, 255); //shaderstate.identitylighting + while((cnt)--) + { + ((D3DCOLOR*)dst)[cnt] = block; + } + break; + default: + identity: + case RGB_GEN_IDENTITY: + block = D3DCOLOR_RGBA(255, 255, 255, 255); + while((cnt)--) + { + ((D3DCOLOR*)dst)[cnt] = block; + } + break; + case RGB_GEN_CONST: + block = D3DCOLOR_COLORVALUE(pass->rgbgen_func.args[0], pass->rgbgen_func.args[1], pass->rgbgen_func.args[2], 1); + while((cnt)--) + { + ((D3DCOLOR*)dst)[cnt] = block; + } + break; + case RGB_GEN_LIGHTING_DIFFUSE: + //collect lighting details for mobile entities + if (!mesh->normals_array) + { + block = D3DCOLOR_RGBA(255, 255, 255, 255); + while((cnt)--) + { + ((D3DCOLOR*)dst)[cnt] = block; + } + } + else + { + R_LightArraysByte_BGR(shaderstate.curentity , mesh->xyz_array, dst, cnt, mesh->normals_array); + } + break; + case RGB_GEN_WAVE: + { + float *table; + float c; + + table = FTableForFunc(pass->rgbgen_func.type); + c = pass->rgbgen_func.args[2] + shaderstate.curtime * pass->rgbgen_func.args[3]; + c = FTABLE_EVALUATE(table, c) * pass->rgbgen_func.args[1] + pass->rgbgen_func.args[0]; + c = bound(0.0f, c, 1.0f); + block = D3DCOLOR_COLORVALUE(c, c, c, 1); + + while((cnt)--) + { + ((D3DCOLOR*)dst)[cnt] = block; + } + } + break; + + case RGB_GEN_TOPCOLOR: + case RGB_GEN_BOTTOMCOLOR: +#ifdef warningmsg +#pragma warningmsg("fix 24bit player colours") +#endif + block = D3DCOLOR_RGBA(255, 255, 255, 255); + while((cnt)--) + { + ((D3DCOLOR*)dst)[cnt] = block; + } + // Con_Printf("RGB_GEN %i not supported\n", pass->rgbgen); + break; + } +*/ +} + +static void alphagenbyte(const shaderpass_t *pass, int cnt, byte_vec4_t *srcb, vec4_t *srcf, byte_vec4_t *dst, const mesh_t *mesh) +{ + /*FIXME: Skip this if the rgbgen did it*/ +/* + float *table; + unsigned char t; + float f; + vec3_t v1, v2; + + switch (pass->alphagen) + { + default: + case ALPHA_GEN_IDENTITY: + if (shaderstate.flags & BEF_FORCETRANSPARENT) + { + f = shaderstate.curentity->shaderRGBAf[3]; + if (f < 0) + t = 0; + else if (f >= 1) + t = 255; + else + t = f*255; + while(cnt--) + dst[cnt][3] = t; + } + else + { + while(cnt--) + dst[cnt][3] = 255; + } + break; + + case ALPHA_GEN_CONST: + t = pass->alphagen_func.args[0]*255; + while(cnt--) + dst[cnt][3] = t; + break; + + case ALPHA_GEN_WAVE: + table = FTableForFunc(pass->alphagen_func.type); + f = pass->alphagen_func.args[2] + shaderstate.curtime * pass->alphagen_func.args[3]; + f = FTABLE_EVALUATE(table, f) * pass->alphagen_func.args[1] + pass->alphagen_func.args[0]; + t = bound(0.0f, f, 1.0f)*255; + while(cnt--) + dst[cnt][3] = t; + break; + + case ALPHA_GEN_PORTAL: + //FIXME: should this be per-vert? + VectorAdd(mesh->xyz_array[0], shaderstate.curentity->origin, v1); + VectorSubtract(r_origin, v1, v2); + f = VectorLength(v2) * (1.0 / 255.0); + t = bound(0.0f, f, 1.0f)*255; + + while(cnt--) + dst[cnt][3] = t; + break; + + case ALPHA_GEN_VERTEX: + if (srcb) + { + while(cnt--) + { + dst[cnt][3] = srcb[cnt][3]; + } + } + else if (srcf) + { + while(cnt--) + { + dst[cnt][3] = bound(0, srcf[cnt][3]*255, 255); + } + } + else + { + while(cnt--) + { + dst[cnt][3] = 255; + } + } + break; + + case ALPHA_GEN_ENTITY: + t = bound(0, shaderstate.curentity->shaderRGBAf[3], 1)*255; + while(cnt--) + { + dst[cnt][3] = t; + } + break; + + case ALPHA_GEN_SPECULAR: + { + int i; + VectorSubtract(r_origin, shaderstate.curentity->origin, v1); + + if (!Matrix3_Compare(shaderstate.curentity->axis, (void *)axisDefault)) + { + Matrix3_Multiply_Vec3(shaderstate.curentity->axis, v2, v2); + } + else + { + VectorCopy(v1, v2); + } + + for (i = 0; i < cnt; i++) + { + VectorSubtract(v2, mesh->xyz_array[i], v1); + f = DotProduct(v1, mesh->normals_array[i] ) * Q_rsqrt(DotProduct(v1,v1)); + f = f * f * f * f * f; + dst[i][3] = bound (0.0f, (int)(f*255), 255); + } + } + break; + } + */ +} + +static unsigned int BE_GenerateColourMods(unsigned int vertcount, const shaderpass_t *pass) +{ + unsigned int ret = 0; + unsigned char *map; + const mesh_t *m; + unsigned int mno; + + m = shaderstate.meshlist[0]; + + if (pass->flags & SHADER_PASS_NOCOLORARRAY) + { + shaderstate.passsinglecolour = true; +// shaderstate.passcolour = D3DCOLOR_RGBA(255,255,255,255); + colourgenbyte(pass, 1, (byte_vec4_t*)&shaderstate.passcolour, NULL, (byte_vec4_t*)&shaderstate.passcolour, m); + alphagenbyte(pass, 1, (byte_vec4_t*)&shaderstate.passcolour, NULL, (byte_vec4_t*)&shaderstate.passcolour, m); + /*FIXME: just because there's no rgba set, there's no reason to assume it should be a single colour (unshaded ents)*/ +// d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_COL, NULL, 0, 0)); + } + else + { + shaderstate.passsinglecolour = false; + + ret |= D3D_VDEC_COL4B; + if (shaderstate.batchvbo && (m->colors4f_array && + ((pass->rgbgen == RGB_GEN_VERTEX_LIGHTING) || + (pass->rgbgen == RGB_GEN_VERTEX_EXACT) || + (pass->rgbgen == RGB_GEN_ONE_MINUS_VERTEX)) && + (pass->alphagen == ALPHA_GEN_VERTEX))) + { +// d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_COL, shaderstate.batchvbo->colours.d3d.buff, shaderstate.batchvbo->colours.d3d.offs, sizeof(byte_vec4_t))); + } + else + { +/* allocvertexbuffer(shaderstate.dyncol_buff, shaderstate.dyncol_size, &shaderstate.dyncol_offs, (void**)&map, vertcount*sizeof(D3DCOLOR)); + for (vertcount = 0, mno = 0; mno < shaderstate.nummeshes; mno++) + { + m = shaderstate.meshlist[mno]; + colourgenbyte(pass, m->numvertexes, m->colors4b_array, m->colors4f_array, (byte_vec4_t*)map, m); + alphagenbyte(pass, m->numvertexes, m->colors4b_array, m->colors4f_array, (byte_vec4_t*)map, m); + map += m->numvertexes*4; + vertcount += m->numvertexes; + } + d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dyncol_buff)); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_COL, shaderstate.dyncol_buff, shaderstate.dyncol_offs - vertcount*sizeof(D3DCOLOR), sizeof(D3DCOLOR))); +*/ + } + } + return ret; +} +#endif +/*********************************************************************************************************/ +/*========================================== texture coord generation =====================================*/ +#if 0 +static void tcgen_environment(float *st, unsigned int numverts, float *xyz, float *normal) +{ + int i; + vec3_t viewer, reflected; + float d; + + vec3_t rorg; + + RotateLightVector(shaderstate.curentity->axis, shaderstate.curentity->origin, r_origin, rorg); + + for (i = 0 ; i < numverts ; i++, xyz += 3, normal += 3, st += 2 ) + { + VectorSubtract (rorg, xyz, viewer); + VectorNormalizeFast (viewer); + + d = DotProduct (normal, viewer); + + reflected[0] = normal[0]*2*d - viewer[0]; + reflected[1] = normal[1]*2*d - viewer[1]; + reflected[2] = normal[2]*2*d - viewer[2]; + + st[0] = 0.5 + reflected[1] * 0.5; + st[1] = 0.5 - reflected[2] * 0.5; + } +} + +static float *tcgen(const shaderpass_t *pass, int cnt, float *dst, const mesh_t *mesh) +{ + int i; + vecV_t *src; + switch (pass->tcgen) + { + default: + case TC_GEN_BASE: + return (float*)mesh->st_array; + case TC_GEN_LIGHTMAP: + return (float*)mesh->lmst_array; + case TC_GEN_NORMAL: + return (float*)mesh->normals_array; + case TC_GEN_SVECTOR: + return (float*)mesh->snormals_array; + case TC_GEN_TVECTOR: + return (float*)mesh->tnormals_array; + case TC_GEN_ENVIRONMENT: + tcgen_environment(dst, cnt, (float*)mesh->xyz_array, (float*)mesh->normals_array); + return dst; + + case TC_GEN_DOTPRODUCT: + return dst;//mesh->st_array[0]; + case TC_GEN_VECTOR: + src = mesh->xyz_array; + for (i = 0; i < cnt; i++, dst += 2) + { + static vec3_t tc_gen_s = { 1.0f, 0.0f, 0.0f }; + static vec3_t tc_gen_t = { 0.0f, 1.0f, 0.0f }; + + dst[0] = DotProduct(tc_gen_s, src[i]); + dst[1] = DotProduct(tc_gen_t, src[i]); + } + return dst; + } +} + +/*src and dst can be the same address when tcmods are chained*/ +static void tcmod(const tcmod_t *tcmod, int cnt, const float *src, float *dst, const mesh_t *mesh) +{ + float *table; + float t1, t2; + float cost, sint; + int j; +#define R_FastSin(x) sin((x)*(2*M_PI)) + switch (tcmod->type) + { + case SHADER_TCMOD_ROTATE: + cost = tcmod->args[0] * shaderstate.curtime; + sint = R_FastSin(cost); + cost = R_FastSin(cost + 0.25); + + for (j = 0; j < cnt; j++, dst+=2,src+=2) + { + t1 = cost * (src[0] - 0.5f) - sint * (src[1] - 0.5f) + 0.5f; + t2 = cost * (src[1] - 0.5f) + sint * (src[0] - 0.5f) + 0.5f; + dst[0] = t1; + dst[1] = t2; + } + break; + + case SHADER_TCMOD_SCALE: + t1 = tcmod->args[0]; + t2 = tcmod->args[1]; + + for (j = 0; j < cnt; j++, dst+=2,src+=2) + { + dst[0] = src[0] * t1; + dst[1] = src[1] * t2; + } + break; + + case SHADER_TCMOD_TURB: + t1 = tcmod->args[2] + shaderstate.curtime * tcmod->args[3]; + t2 = tcmod->args[1]; + + for (j = 0; j < cnt; j++, dst+=2,src+=2) + { + dst[0] = src[0] + R_FastSin (src[0]*t2+t1) * t2; + dst[1] = src[1] + R_FastSin (src[1]*t2+t1) * t2; + } + break; + + case SHADER_TCMOD_STRETCH: + table = FTableForFunc(tcmod->args[0]); + t2 = tcmod->args[3] + shaderstate.curtime * tcmod->args[4]; + t1 = FTABLE_EVALUATE(table, t2) * tcmod->args[2] + tcmod->args[1]; + t1 = t1 ? 1.0f / t1 : 1.0f; + t2 = 0.5f - 0.5f * t1; + for (j = 0; j < cnt; j++, dst+=2,src+=2) + { + dst[0] = src[0] * t1 + t2; + dst[1] = src[1] * t1 + t2; + } + break; + + case SHADER_TCMOD_SCROLL: + t1 = tcmod->args[0] * shaderstate.curtime; + t2 = tcmod->args[1] * shaderstate.curtime; + + for (j = 0; j < cnt; j++, dst += 2, src+=2) + { + dst[0] = src[0] + t1; + dst[1] = src[1] + t2; + } + break; + + case SHADER_TCMOD_TRANSFORM: + for (j = 0; j < cnt; j++, dst+=2, src+=2) + { + t1 = src[0]; + t2 = src[1]; + dst[0] = t1 * tcmod->args[0] + t2 * tcmod->args[2] + tcmod->args[4]; + dst[1] = t2 * tcmod->args[1] + t1 * tcmod->args[3] + tcmod->args[5]; + } + break; + + default: + break; + } +} + +static void GenerateTCMods(const shaderpass_t *pass, float *dest) +{ + mesh_t *mesh; + unsigned int mno; + // unsigned int fvertex = 0; //unused variable + int i; + float *src; + for (mno = 0; mno < shaderstate.nummeshes; mno++) + { + mesh = shaderstate.meshlist[mno]; + src = tcgen(pass, mesh->numvertexes, dest, mesh); + //tcgen might return unmodified info + if (pass->numtcmods) + { + tcmod(&pass->tcmods[0], mesh->numvertexes, src, dest, mesh); + for (i = 1; i < pass->numtcmods; i++) + { + tcmod(&pass->tcmods[i], mesh->numvertexes, dest, dest, mesh); + } + } + else if (src != dest) + { + memcpy(dest, src, sizeof(vec2_t)*mesh->numvertexes); + } + dest += mesh->numvertexes*2; + } +} +#endif +//end texture coords +/*******************************************************************************************************************/ +#if 0 +static void deformgen(const deformv_t *deformv, int cnt, vecV_t *src, vecV_t *dst, const mesh_t *mesh) +{ + float *table; + int j, k; + float args[4]; + float deflect; + switch (deformv->type) + { + default: + case DEFORMV_NONE: + if (src != dst) + memcpy(dst, src, sizeof(*src)*cnt); + break; + + case DEFORMV_WAVE: + if (!mesh->normals_array) + { + if (src != dst) + memcpy(dst, src, sizeof(*src)*cnt); + return; + } + args[0] = deformv->func.args[0]; + args[1] = deformv->func.args[1]; + args[3] = deformv->func.args[2] + deformv->func.args[3] * shaderstate.curtime; + table = FTableForFunc(deformv->func.type); + + for ( j = 0; j < cnt; j++ ) + { + deflect = deformv->args[0] * (src[j][0]+src[j][1]+src[j][2]) + args[3]; + deflect = FTABLE_EVALUATE(table, deflect) * args[1] + args[0]; + + // Deflect vertex along its normal by wave amount + VectorMA(src[j], deflect, mesh->normals_array[j], dst[j]); + } + break; + + case DEFORMV_NORMAL: + //normal does not actually move the verts, but it does change the normals array + //we don't currently support that. + if (src != dst) + memcpy(dst, src, sizeof(*src)*cnt); +/* + args[0] = deformv->args[1] * shaderstate.curtime; + + for ( j = 0; j < cnt; j++ ) + { + args[1] = normalsArray[j][2] * args[0]; + + deflect = deformv->args[0] * R_FastSin(args[1]); + normalsArray[j][0] *= deflect; + deflect = deformv->args[0] * R_FastSin(args[1] + 0.25); + normalsArray[j][1] *= deflect; + VectorNormalizeFast(normalsArray[j]); + } +*/ break; + + case DEFORMV_MOVE: + table = FTableForFunc(deformv->func.type); + deflect = deformv->func.args[2] + shaderstate.curtime * deformv->func.args[3]; + deflect = FTABLE_EVALUATE(table, deflect) * deformv->func.args[1] + deformv->func.args[0]; + + for ( j = 0; j < cnt; j++ ) + VectorMA(src[j], deflect, deformv->args, dst[j]); + break; + + case DEFORMV_BULGE: + args[0] = deformv->args[0]/(2*M_PI); + args[1] = deformv->args[1]; + args[2] = shaderstate.curtime * deformv->args[2]/(2*M_PI); + + for (j = 0; j < cnt; j++) + { + deflect = R_FastSin(mesh->st_array[j][0]*args[0] + args[2])*args[1]; + dst[j][0] = src[j][0]+deflect*mesh->normals_array[j][0]; + dst[j][1] = src[j][1]+deflect*mesh->normals_array[j][1]; + dst[j][2] = src[j][2]+deflect*mesh->normals_array[j][2]; + } + break; + + case DEFORMV_AUTOSPRITE: + if (mesh->numindexes < 6) + break; + + for (j = 0; j < cnt-3; j+=4, src+=4, dst+=4) + { + vec3_t mid, d; + float radius; + mid[0] = 0.25*(src[0][0] + src[1][0] + src[2][0] + src[3][0]); + mid[1] = 0.25*(src[0][1] + src[1][1] + src[2][1] + src[3][1]); + mid[2] = 0.25*(src[0][2] + src[1][2] + src[2][2] + src[3][2]); + VectorSubtract(src[0], mid, d); + radius = 2*VectorLength(d); + + for (k = 0; k < 4; k++) + { + dst[k][0] = mid[0] + radius*((mesh->st_array[k][0]-0.5)*r_refdef.m_view[0+0]-(mesh->st_array[k][1]-0.5)*r_refdef.m_view[0+1]); + dst[k][1] = mid[1] + radius*((mesh->st_array[k][0]-0.5)*r_refdef.m_view[4+0]-(mesh->st_array[k][1]-0.5)*r_refdef.m_view[4+1]); + dst[k][2] = mid[2] + radius*((mesh->st_array[k][0]-0.5)*r_refdef.m_view[8+0]-(mesh->st_array[k][1]-0.5)*r_refdef.m_view[8+1]); + } + } + break; + + case DEFORMV_AUTOSPRITE2: + if (mesh->numindexes < 6) + break; + + for (k = 0; k < mesh->numindexes; k += 6) + { + int long_axis, short_axis; + vec3_t axis; + float len[3]; + mat3_t m0, m1, m2, result; + float *quad[4]; + vec3_t rot_centre, tv; + + quad[0] = (float *)(dst + mesh->indexes[k+0]); + quad[1] = (float *)(dst + mesh->indexes[k+1]); + quad[2] = (float *)(dst + mesh->indexes[k+2]); + + for (j = 2; j >= 0; j--) + { + quad[3] = (float *)(dst + mesh->indexes[k+3+j]); + if (!VectorEquals (quad[3], quad[0]) && + !VectorEquals (quad[3], quad[1]) && + !VectorEquals (quad[3], quad[2])) + { + break; + } + } + + // build a matrix were the longest axis of the billboard is the Y-Axis + VectorSubtract(quad[1], quad[0], m0[0]); + VectorSubtract(quad[2], quad[0], m0[1]); + VectorSubtract(quad[2], quad[1], m0[2]); + len[0] = DotProduct(m0[0], m0[0]); + len[1] = DotProduct(m0[1], m0[1]); + len[2] = DotProduct(m0[2], m0[2]); + + if ((len[2] > len[1]) && (len[2] > len[0])) + { + if (len[1] > len[0]) + { + long_axis = 1; + short_axis = 0; + } + else + { + long_axis = 0; + short_axis = 1; + } + } + else if ((len[1] > len[2]) && (len[1] > len[0])) + { + if (len[2] > len[0]) + { + long_axis = 2; + short_axis = 0; + } + else + { + long_axis = 0; + short_axis = 2; + } + } + else //if ( (len[0] > len[1]) && (len[0] > len[2]) ) + { + if (len[2] > len[1]) + { + long_axis = 2; + short_axis = 1; + } + else + { + long_axis = 1; + short_axis = 2; + } + } + + if (DotProduct(m0[long_axis], m0[short_axis])) + { + VectorNormalize2(m0[long_axis], axis); + VectorCopy(axis, m0[1]); + + if (axis[0] || axis[1]) + { + VectorVectors(m0[1], m0[2], m0[0]); + } + else + { + VectorVectors(m0[1], m0[0], m0[2]); + } + } + else + { + VectorNormalize2(m0[long_axis], axis); + VectorNormalize2(m0[short_axis], m0[0]); + VectorCopy(axis, m0[1]); + CrossProduct(m0[0], m0[1], m0[2]); + } + + for (j = 0; j < 3; j++) + rot_centre[j] = (quad[0][j] + quad[1][j] + quad[2][j] + quad[3][j]) * 0.25; + + if (shaderstate.curentity) + { + VectorAdd(shaderstate.curentity->origin, rot_centre, tv); + } + else + { + VectorCopy(rot_centre, tv); + } + VectorSubtract(r_origin, tv, tv); + + // filter any longest-axis-parts off the camera-direction + deflect = -DotProduct(tv, axis); + + VectorMA(tv, deflect, axis, m1[2]); + VectorNormalizeFast(m1[2]); + VectorCopy(axis, m1[1]); + CrossProduct(m1[1], m1[2], m1[0]); + + Matrix3_Transpose(m1, m2); + Matrix3_Multiply(m2, m0, result); + + for (j = 0; j < 4; j++) + { + VectorSubtract(quad[j], rot_centre, tv); + Matrix3_Multiply_Vec3((void *)result, tv, quad[j]); + VectorAdd(rot_centre, quad[j], quad[j]); + } + } + break; + +// case DEFORMV_PROJECTION_SHADOW: +// break; + } +} +#endif + +#if 0 +/*does not do the draw call, does not consider indicies (except for billboard generation) */ +static qboolean BE_DrawMeshChain_SetupPass(shaderpass_t *pass, unsigned int vertcount) +{ + int vdec; + void *map; + int i; + unsigned int passno = 0, tmu; + + int lastpass = pass->numMergedPasses; + + for (i = 0; i < lastpass; i++) + { + if (pass[i].texgen == T_GEN_UPPEROVERLAY && !TEXVALID(shaderstate.curtexnums->upperoverlay)) + continue; + if (pass[i].texgen == T_GEN_LOWEROVERLAY && !TEXVALID(shaderstate.curtexnums->loweroverlay)) + continue; + if (pass[i].texgen == T_GEN_FULLBRIGHT && !TEXVALID(shaderstate.curtexnums->fullbright)) + continue; + break; + } + if (i == lastpass) + return false; + + /*all meshes in a chain must have the same features*/ + vdec = 0; + + /*we only use one colour, generated from the first pass*/ + vdec |= BE_GenerateColourMods(vertcount, pass); + + tmu = 0; + /*activate tmus*/ + for (passno = 0; passno < lastpass; passno++) + { + if (pass[passno].texgen == T_GEN_UPPEROVERLAY && !TEXVALID(shaderstate.curtexnums->upperoverlay)) + continue; + if (pass[passno].texgen == T_GEN_LOWEROVERLAY && !TEXVALID(shaderstate.curtexnums->loweroverlay)) + continue; + if (pass[passno].texgen == T_GEN_FULLBRIGHT && !TEXVALID(shaderstate.curtexnums->fullbright)) + continue; + + SelectPassTexture(tmu, pass+passno); + + vdec |= D3D_VDEC_ST0<texcoord.d3d.buff, shaderstate.batchvbo->texcoord.d3d.offs, sizeof(vec2_t))); + else if (shaderstate.batchvbo && pass[passno].tcgen == TC_GEN_LIGHTMAP && !pass[passno].numtcmods) + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0+tmu, shaderstate.batchvbo->lmcoord[0].d3d.buff, shaderstate.batchvbo->lmcoord[0].d3d.offs, sizeof(vec2_t))); + else + { + allocvertexbuffer(shaderstate.dynst_buff[tmu], shaderstate.dynst_size, &shaderstate.dynst_offs[tmu], &map, vertcount*sizeof(vec2_t)); + GenerateTCMods(pass+passno, map); + d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynst_buff[tmu])); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0+tmu, shaderstate.dynst_buff[tmu], shaderstate.dynst_offs[tmu] - vertcount*sizeof(vec2_t), sizeof(vec2_t))); + } +*/ + tmu++; + } + /*deactivate any extras*/ + for (; tmu < shaderstate.lastpasscount; ) + { +// d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0+tmu, NULL, 0, 0)); + BindTexture(tmu, NULL); +// d3dcheck(IDirect3DDevice9_SetTextureStageState(pD3DDev9, tmu, D3DTSS_COLOROP, D3DTOP_DISABLE)); + tmu++; + } + shaderstate.lastpasscount = tmu; + +// if (meshchain->normals_array && +// meshchain->2 && +// meshchain->tnormals_array) +// vdec |= D3D_VDEC_NORMS; + + if (vdec != shaderstate.curvertdecl) + { + shaderstate.curvertdecl = vdec; +// d3dcheck(IDirect3DDevice9_SetVertexDeclaration(pD3DDev9, vertexdecls[shaderstate.curvertdecl])); + } + + D3D11BE_ApplyShaderBits(pass->shaderbits); + return true; +} +#endif + +static void BE_SubmitMeshChain(int idxfirst) +{ + int starti, endi; + int m; + mesh_t *mesh; + + /*if (shaderstate.batchvbo) + { + ID3D11DeviceContext_DrawIndexed(d3ddevctx, shaderstate.batchvbo->indexcount, 0, 0); + return; + }*/ + + for (m = 0, mesh = shaderstate.meshlist[0]; m < shaderstate.nummeshes; ) + { + starti = mesh->vbofirstelement; + + endi = starti+mesh->numindexes; + + //find consecutive surfaces + for (++m; m < shaderstate.nummeshes; m++) + { + mesh = shaderstate.meshlist[m]; + if (endi == mesh->vbofirstelement) + { + endi = mesh->vbofirstelement+mesh->numindexes; + } + else + { + break; + } + } + + ID3D11DeviceContext_DrawIndexed(d3ddevctx, endi - starti, starti, 0); + RQuantAdd(RQUANT_DRAWS, 1); + } +} + +static void BE_ApplyUniforms(program_t *prog, int permu) +{ + //FIXME: how many of these calls can we avoid? + ID3D11DeviceContext_IASetInputLayout(d3ddevctx, prog->handle[permu].hlsl.layout); + ID3D11DeviceContext_VSSetShader(d3ddevctx, prog->handle[permu].hlsl.vert, NULL, 0); + ID3D11DeviceContext_PSSetShader(d3ddevctx, prog->handle[permu].hlsl.frag, NULL, 0); + ID3D11DeviceContext_IASetPrimitiveTopology(d3ddevctx, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + ID3D11DeviceContext_VSSetConstantBuffers(d3ddevctx, 0, sizeof(shaderstate.cbuffers)/sizeof(shaderstate.cbuffers[0]), shaderstate.cbuffers); + ID3D11DeviceContext_PSSetConstantBuffers(d3ddevctx, 0, sizeof(shaderstate.cbuffers)/sizeof(shaderstate.cbuffers[0]), shaderstate.cbuffers); +} + +static void BE_RenderMeshProgram(shader_t *s, unsigned int vertcount, unsigned int idxfirst, unsigned int idxcount) +{ + int passno; + int perm = 0; + + program_t *p = s->prog; + + if (TEXVALID(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_BUMPMAP].hlsl.vert) + perm |= PERMUTATION_BUMPMAP; + if (TEXVALID(shaderstate.curtexnums->specular) && p->handle[perm|PERMUTATION_SPECULAR].hlsl.vert) + perm |= PERMUTATION_SPECULAR; + if (TEXVALID(shaderstate.curtexnums->fullbright) && p->handle[perm|PERMUTATION_FULLBRIGHT].hlsl.vert) + perm |= PERMUTATION_FULLBRIGHT; + if (p->handle[perm|PERMUTATION_UPPERLOWER].hlsl.vert && (TEXVALID(shaderstate.curtexnums->upperoverlay) || TEXVALID(shaderstate.curtexnums->loweroverlay))) + perm |= PERMUTATION_UPPERLOWER; + if (r_refdef.gfog_rgbd[3] && p->handle[perm|PERMUTATION_FOG].hlsl.vert) + perm |= PERMUTATION_FOG; +// if (r_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_OFFSET.hlsl.vert) +// perm |= PERMUTATION_OFFSET; + + BE_ApplyUniforms(p, perm); + + + D3D11BE_ApplyShaderBits(s->passes->shaderbits); + + /*activate tmus*/ + for (passno = 0; passno < s->numpasses; passno++) + { + SelectPassTexture(passno, s->passes+passno); + } + /*deactivate any extras*/ + for (; passno < shaderstate.lastpasscount; passno++) + { + BindTexture(passno, NULL); + } + shaderstate.lastpasscount = passno; + + BE_SubmitMeshChain(idxfirst); +} + +static void D3D11BE_Cull(unsigned int cullflags) +{ + D3D11_RASTERIZER_DESC rasterdesc; + ID3D11RasterizerState *newrasterizerstate; + + cullflags |= r_refdef.flipcull; + + if (shaderstate.curcull != cullflags) + { + shaderstate.curcull = cullflags; + + + rasterdesc.AntialiasedLineEnable = false; + + if (shaderstate.curcull & 1) + { + if (shaderstate.curcull & SHADER_CULL_FRONT) + rasterdesc.CullMode = D3D11_CULL_FRONT; + else if (shaderstate.curcull & SHADER_CULL_BACK) + rasterdesc.CullMode = D3D11_CULL_BACK; + else + rasterdesc.CullMode = D3D11_CULL_NONE; + } + else + { + if (shaderstate.curcull & SHADER_CULL_FRONT) + rasterdesc.CullMode = D3D11_CULL_BACK; + else if (shaderstate.curcull & SHADER_CULL_BACK) + rasterdesc.CullMode = D3D11_CULL_FRONT; + else + rasterdesc.CullMode = D3D11_CULL_NONE; + } + + + rasterdesc.DepthBias = 0; + rasterdesc.DepthBiasClamp = 0.0f; + rasterdesc.DepthClipEnable = true; + rasterdesc.FillMode = D3D11_FILL_SOLID; + rasterdesc.FrontCounterClockwise = false; + rasterdesc.MultisampleEnable = false; + rasterdesc.ScissorEnable = false; + rasterdesc.SlopeScaledDepthBias = 0.0f; + + ID3D11Device_CreateRasterizerState(pD3DDev11, &rasterdesc, &newrasterizerstate); + ID3D11DeviceContext_RSSetState(d3ddevctx, newrasterizerstate); + ID3D11RasterizerState_Release(newrasterizerstate); + } +} + +static void BE_DrawMeshChain_Internal(void) +{ + unsigned int vertcount, idxcount, idxfirst; + mesh_t *m; +// void *map; + int i; + unsigned int mno; + unsigned int passno = 0; + shaderpass_t *pass = shaderstate.curshader->passes; + extern cvar_t r_polygonoffset_submodel_factor; +// float pushdepth; +// float pushfactor; + + D3D11BE_Cull(shaderstate.curshader->flags & (SHADER_CULL_FRONT | SHADER_CULL_BACK)); +/* + pushdepth = (shaderstate.curshader->polyoffset.factor + ((shaderstate.flags & BEF_PUSHDEPTH)?r_polygonoffset_submodel_factor.value:0))/0xffff; + if (pushdepth != shaderstate.depthbias) + { + shaderstate.depthbias = pushdepth; + IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_DEPTHBIAS, *(DWORD*)&shaderstate.depthbias); + } + pushdepth = shaderstate.curshader->polyoffset.unit/-1;// + ((shaderstate.flags & BEF_PUSHDEPTH)?8:0); + pushfactor = shaderstate.curshader->polyoffset.factor/-1; + if (pushfactor != shaderstate.depthfactor) + { + shaderstate.depthfactor = pushfactor; + IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD*)&shaderstate.depthfactor); + } +*/ + + if (shaderstate.batchvbo) + { + vertcount = shaderstate.batchvbo->vertcount; + idxcount = shaderstate.batchvbo->indexcount; + } + else + { + for (mno = 0, vertcount = 0, idxcount = 0; mno < shaderstate.nummeshes; mno++) + { + m = shaderstate.meshlist[mno]; + vertcount += m->numvertexes; + idxcount += m->numindexes; + } + } + + /*vertex buffers are common to all passes*/ + if (shaderstate.batchvbo) + { + unsigned int strides[] = {sizeof(vbovdata_t)}; + ID3D11DeviceContext_IASetVertexBuffers(d3ddevctx, 0, 1, (ID3D11Buffer**)&shaderstate.batchvbo->coord.d3d.buff, strides, &shaderstate.batchvbo->coord.d3d.offs); +// d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_VERT, shaderstate.batchvbo->coord.d3d.buff, shaderstate.batchvbo->coord.d3d.offs, sizeof(vecV_t))); + } + else + { + return; +/* allocvertexbuffer(shaderstate.dynxyz_buff, shaderstate.dynxyz_size, &shaderstate.dynxyz_offs, &map, vertcount*sizeof(vecV_t)); + for (mno = 0, vertcount = 0; mno < shaderstate.nummeshes; mno++) + { + vecV_t *dest = (vecV_t*)((char*)map+vertcount*sizeof(vecV_t)); + m = shaderstate.meshlist[mno]; + deformgen(&shaderstate.curshader->deforms[0], m->numvertexes, m->xyz_array, dest, m); + for (i = 1; i < shaderstate.curshader->numdeforms; i++) + { + deformgen(&shaderstate.curshader->deforms[i], m->numvertexes, dest, dest, m); + } + vertcount += m->numvertexes; + } + d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynxyz_buff)); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_VERT, shaderstate.dynxyz_buff, shaderstate.dynxyz_offs - vertcount*sizeof(vecV_t), sizeof(vecV_t))); +*/ + } + + /*so are index buffers*/ + if (shaderstate.batchvbo) + { + ID3D11DeviceContext_IASetIndexBuffer(d3ddevctx, shaderstate.batchvbo->indicies.d3d.buff, DXGI_FORMAT_R16_UINT, shaderstate.batchvbo->indicies.d3d.offs); + idxfirst = 0; + } + else + { + return; +/* idxfirst = allocindexbuffer(&map, idxcount); + for (mno = 0, vertcount = 0; mno < shaderstate.nummeshes; mno++) + { + m = shaderstate.meshlist[mno]; + for (i = 0; i < m->numindexes; i++) + ((index_t*)map)[i] = m->indexes[i]+vertcount; + map = (char*)map + m->numindexes*sizeof(index_t); + vertcount += m->numvertexes; + } + d3dcheck(IDirect3DIndexBuffer9_Unlock(shaderstate.dynidx_buff)); + d3dcheck(IDirect3DDevice9_SetIndices(pD3DDev9, shaderstate.dynidx_buff)); +*/ + } + + switch (shaderstate.mode) + { + case BEM_LIGHT: + BE_RenderMeshProgram(shaderstate.shader_rtlight, vertcount, idxfirst, idxcount); + break; + case BEM_DEPTHONLY: + shaderstate.lastpasscount = 0; + i = 0; + if (i != shaderstate.curvertdecl) + { + shaderstate.curvertdecl = i; +// d3dcheck(IDirect3DDevice9_SetVertexDeclaration(pD3DDev9, vertexdecls[shaderstate.curvertdecl])); + } +// IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_COLORWRITEENABLE, 0); + /*deactivate any extras*/ + for (passno = 0; passno < shaderstate.lastpasscount; ) + { +// d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0+passno, NULL, 0, 0)); + BindTexture(passno, NULL); +// d3dcheck(IDirect3DDevice9_SetTextureStageState(pD3DDev9, passno, D3DTSS_COLOROP, D3DTOP_DISABLE)); + passno++; + } + shaderstate.lastpasscount = 0; + BE_SubmitMeshChain(idxfirst); +// IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED|D3DCOLORWRITEENABLE_GREEN|D3DCOLORWRITEENABLE_BLUE|D3DCOLORWRITEENABLE_ALPHA); + break; + default: + case BEM_STANDARD: + if (shaderstate.curshader->prog) + { + BE_RenderMeshProgram(shaderstate.curshader, vertcount, idxfirst, idxcount); + } + else if (developer.ival) + Con_DPrintf("Shader %s has no hlsl program\n", shaderstate.curshader->name); + //else d3d11 has no fixed function pipeline. + break; + } +} + +void D3D11BE_SelectMode(backendmode_t mode) +{ + shaderstate.mode = mode; + + if (mode == BEM_STENCIL) + D3D11BE_ApplyShaderBits(SBITS_MASK_BITS); +} + +void D3D11BE_SelectDLight(dlight_t *dl, vec3_t colour) +{ + shaderstate.curdlight = dl; + VectorCopy(colour, shaderstate.curdlight_colours); +} + +void D3D11BE_SelectEntity(entity_t *ent) +{ + BE_RotateForEntity(ent, ent->model); +} + +static void BE_GenTempMeshVBO(vbo_t **vbo, mesh_t *mesh) +{ + static vbovdata_t vbodata[65536]; + static vbo_t tmpvbo; + D3D11_BUFFER_DESC vbodesc; + D3D11_BUFFER_DESC ebodesc; + D3D11_SUBRESOURCE_DATA srd; + ID3D11Buffer *vbuff; + ID3D11Buffer *ebuff; + int i; + + if (tmpvbo.coord.d3d.buff) + ID3D11Buffer_Release((ID3D11Buffer*)tmpvbo.coord.d3d.buff); + if (tmpvbo.indicies.d3d.buff) + ID3D11Buffer_Release((ID3D11Buffer*)tmpvbo.indicies.d3d.buff); + + //common stuff + for (i = 0; i < mesh->numvertexes; i++) + { + VectorCopy(mesh->xyz_array[i], vbodata[i].coord); + Vector2Copy(mesh->st_array[i], vbodata[i].tex); + } + //not so common stuff + if (mesh->normals_array) + { + for (i = 0; i < mesh->numvertexes; i++) + { + VectorCopy(mesh->normals_array[i], vbodata[i].ndir); + VectorCopy(mesh->snormals_array[i], vbodata[i].sdir); + VectorCopy(mesh->tnormals_array[i], vbodata[i].tdir); + } + } + //some sort of colours + if (mesh->colors4b_array) + { + for (i = 0; i < mesh->numvertexes; i++) + { + Vector4Copy(mesh->colors4b_array[i], vbodata[i].colorsb); + } + } + else if (mesh->colors4f_array) + { + for (i = 0; i < mesh->numvertexes; i++) + { + Vector4Scale(mesh->colors4f_array[i], 255, vbodata[i].colorsb); + } + } + else + { + for (i = 0; i < mesh->numvertexes; i++) + { + Vector4Set(vbodata[i].colorsb, 255, 255, 255, 255); + } + } + + //generate the ebo, and submit the data to the driver + ebodesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + ebodesc.ByteWidth = sizeof(*mesh->indexes) * mesh->numindexes; + ebodesc.CPUAccessFlags = 0; + ebodesc.MiscFlags = 0; + ebodesc.StructureByteStride = 0; + ebodesc.Usage = D3D11_USAGE_DEFAULT; + srd.pSysMem = mesh->indexes; + srd.SysMemPitch = 0; + srd.SysMemSlicePitch = 0; + ID3D11Device_CreateBuffer(pD3DDev11, &ebodesc, &srd, &ebuff); + + //generate the vbo, and submit the data to the driver + vbodesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vbodesc.ByteWidth = sizeof(vbodata[0]) * mesh->numvertexes; + vbodesc.CPUAccessFlags = 0; + vbodesc.MiscFlags = 0; + vbodesc.StructureByteStride = 0; + vbodesc.Usage = D3D11_USAGE_DEFAULT; + srd.pSysMem = vbodata; + srd.SysMemPitch = 0; + srd.SysMemSlicePitch = 0; + ID3D11Device_CreateBuffer(pD3DDev11, &vbodesc, &srd, &vbuff); + + tmpvbo.coord.d3d.buff = vbuff; + tmpvbo.coord.d3d.offs = (quintptr_t)&vbodata[0].coord - (quintptr_t)&vbodata[0]; + tmpvbo.texcoord.d3d.buff = vbuff; + tmpvbo.texcoord.d3d.offs = (quintptr_t)&vbodata[0].tex - (quintptr_t)&vbodata[0]; + tmpvbo.lmcoord[0].d3d.buff = vbuff; + tmpvbo.lmcoord[0].d3d.offs = (quintptr_t)&vbodata[0].lm - (quintptr_t)&vbodata[0]; + tmpvbo.normals.d3d.buff = vbuff; + tmpvbo.normals.d3d.offs = (quintptr_t)&vbodata[0].ndir - (quintptr_t)&vbodata[0]; + tmpvbo.svector.d3d.buff = vbuff; + tmpvbo.svector.d3d.offs = (quintptr_t)&vbodata[0].sdir - (quintptr_t)&vbodata[0]; + tmpvbo.tvector.d3d.buff = vbuff; + tmpvbo.tvector.d3d.offs = (quintptr_t)&vbodata[0].tdir - (quintptr_t)&vbodata[0]; + tmpvbo.colours.d3d.buff = vbuff; + tmpvbo.colours.d3d.offs = (quintptr_t)&vbodata[0].colorsb - (quintptr_t)&vbodata[0]; + tmpvbo.indicies.d3d.buff = ebuff; + tmpvbo.indicies.d3d.offs = 0; + + tmpvbo.indexcount = mesh->numindexes; + tmpvbo.vertcount = mesh->numvertexes; + tmpvbo.next = NULL; + + *vbo = &tmpvbo; +} + +void D3D11BE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch) +{ + int maxvboelements; + int maxvboverts; + int vert = 0, idx = 0; + batch_t *batch; + vbo_t *vbo; + int i, j; + mesh_t *m; + ID3D11Buffer *vbuff; + ID3D11Buffer *ebuff; + index_t *vboedata, *vboedatastart; + vbovdata_t *vbovdata, *vbovdatastart; + D3D11_BUFFER_DESC vbodesc; + D3D11_BUFFER_DESC ebodesc; + D3D11_SUBRESOURCE_DATA srd; + + vbo = Z_Malloc(sizeof(*vbo)); + + maxvboverts = 0; + maxvboelements = 0; + for(batch = firstbatch; batch != stopbatch; batch = batch->next) + { + for (i=0 ; imaxmeshes ; i++) + { + m = batch->mesh[i]; + maxvboelements += m->numindexes; + maxvboverts += m->numvertexes; + } + } + + vbovdatastart = vbovdata = BZ_Malloc(sizeof(*vbovdata) * maxvboverts); + vboedatastart = vboedata = BZ_Malloc(sizeof(*vboedata) * maxvboelements); + + for(batch = firstbatch; batch != stopbatch; batch = batch->next) + { + batch->vbo = vbo; + for (j=0 ; jmaxmeshes ; j++) + { + m = batch->mesh[j]; + m->vbofirstvert = vert; + for (i = 0; i < m->numvertexes; i++) + { + VectorCopy(m->xyz_array[i], vbovdata->coord); + vbovdata->coord[3] = 1; + Vector2Copy(m->st_array[i], vbovdata->tex); + if (m->lmst_array[0]) + Vector2Copy(m->lmst_array[0][i], vbovdata->lm); + else + Vector2Copy(m->st_array[i], vbovdata->tex); + if (m->normals_array) + VectorCopy(m->normals_array[i], vbovdata->ndir); + else + VectorSet(vbovdata->ndir, 0, 0, 1); + if (m->snormals_array) + VectorCopy(m->snormals_array[i], vbovdata->sdir); + else + VectorSet(vbovdata->sdir, 1, 0, 0); + if (m->tnormals_array) + VectorCopy(m->tnormals_array[i], vbovdata->tdir); + else + VectorSet(vbovdata->tdir, 0, 1, 0); + if (m->colors4f_array) + Vector4Scale(m->colors4f_array[i], 255, vbovdata->colorsb); + else if (m->colors4b_array) + Vector4Copy(m->colors4b_array[i], vbovdata->colorsb); + else + Vector4Set(vbovdata->colorsb, 255, 255, 255, 255); + + vbovdata++; + } + + m->vbofirstelement = idx; + for (i = 0; i < m->numindexes; i++) + { + *vboedata++ = vert + m->indexes[i]; + } + idx += m->numindexes; + vert += m->numvertexes; + } + } + + //generate the ebo, and submit the data to the driver + ebodesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + ebodesc.ByteWidth = sizeof(*vboedata) * maxvboelements; + ebodesc.CPUAccessFlags = 0; + ebodesc.MiscFlags = 0; + ebodesc.StructureByteStride = 0; + ebodesc.Usage = D3D11_USAGE_DEFAULT; + srd.pSysMem = vboedatastart; + srd.SysMemPitch = 0; + srd.SysMemSlicePitch = 0; + ID3D11Device_CreateBuffer(pD3DDev11, &ebodesc, &srd, &ebuff); + BZ_Free(vboedatastart); + + //generate the vbo, and submit the data to the driver + vbodesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vbodesc.ByteWidth = sizeof(*vbovdata) * maxvboverts; + vbodesc.CPUAccessFlags = 0; + vbodesc.MiscFlags = 0; + vbodesc.StructureByteStride = 0; + vbodesc.Usage = D3D11_USAGE_DEFAULT; + srd.pSysMem = vbovdatastart; + srd.SysMemPitch = 0; + srd.SysMemSlicePitch = 0; + ID3D11Device_CreateBuffer(pD3DDev11, &vbodesc, &srd, &vbuff); + BZ_Free(vbovdatastart); + + vbovdata = NULL; + vbo->coord.d3d.buff = vbuff; + vbo->coord.d3d.offs = (quintptr_t)&vbovdata->coord; + vbo->texcoord.d3d.buff = vbuff; + vbo->texcoord.d3d.offs = (quintptr_t)&vbovdata->tex; + vbo->lmcoord[0].d3d.buff = vbuff; + vbo->lmcoord[0].d3d.offs = (quintptr_t)&vbovdata->lm; + vbo->normals.d3d.buff = vbuff; + vbo->normals.d3d.offs = (quintptr_t)&vbovdata->ndir; + vbo->svector.d3d.buff = vbuff; + vbo->svector.d3d.offs = (quintptr_t)&vbovdata->sdir; + vbo->tvector.d3d.buff = vbuff; + vbo->tvector.d3d.offs = (quintptr_t)&vbovdata->tdir; + vbo->colours.d3d.buff = vbuff; + vbo->colours.d3d.offs = (quintptr_t)&vbovdata->colorsb; + vbo->indicies.d3d.buff = ebuff; + vbo->indicies.d3d.offs = 0; + + vbo->indexcount = maxvboelements; + vbo->vertcount = maxvboverts; + + vbo->next = *vbochain; + *vbochain = vbo; +} + +void D3D11BE_GenBrushModelVBO(model_t *mod) +{ + unsigned int vcount; + + + batch_t *batch, *fbatch; + int sortid; + int i; + + fbatch = NULL; + vcount = 0; + for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++) + { + if (!mod->batches[sortid]) + continue; + + for (fbatch = batch = mod->batches[sortid]; batch != NULL; batch = batch->next) + { + //firstmesh got reused as the number of verticies in each batch + if (vcount + batch->firstmesh > MAX_INDICIES) + { + D3D11BE_GenBatchVBOs(&mod->vbos, fbatch, batch); + fbatch = batch; + vcount = 0; + } + + for (i = 0; i < batch->maxmeshes; i++) + vcount += batch->mesh[i]->numvertexes; + } + + D3D11BE_GenBatchVBOs(&mod->vbos, fbatch, batch); + } +} + +/*Wipes a vbo*/ +void D3D11BE_ClearVBO(vbo_t *vbo) +{ + ID3D11Buffer *vbuff = vbo->coord.d3d.buff; + ID3D11Buffer *ebuff = vbo->indicies.d3d.buff; + if (vbuff) + ID3D11Buffer_Release(vbuff); + if (ebuff) + ID3D11Buffer_Release(ebuff); + vbo->coord.d3d.buff = NULL; + vbo->indicies.d3d.buff = NULL; + + BZ_Free(vbo); +} + +/*upload all lightmaps at the start to reduce lags*/ +static void BE_UploadLightmaps(qboolean force) +{ + int i; + + for (i = 0; i < numlightmaps; i++) + { + if (!lightmap[i]) + continue; + + if (force) + { + lightmap[i]->rectchange.l = 0; + lightmap[i]->rectchange.t = 0; + lightmap[i]->rectchange.w = LMBLOCK_WIDTH; + lightmap[i]->rectchange.h = LMBLOCK_HEIGHT; + lightmap[i]->modified = true; + } + + if (lightmap[i]->modified) + { + D3D11_UploadLightmap(lightmap[i]); + } + } +} + +void D3D11BE_UploadAllLightmaps(void) +{ + BE_UploadLightmaps(true); +} + +qboolean D3D11BE_LightCullModel(vec3_t org, model_t *model) +{ +#ifdef RTLIGHTS + if ((shaderstate.mode == BEM_LIGHT || shaderstate.mode == BEM_STENCIL)) + { + /*true if hidden from current light*/ + /*we have no rtlight support, so mneh*/ + } +#endif + return false; +} + +batch_t *D3D11BE_GetTempBatch(void) +{ + if (shaderstate.wbatch >= shaderstate.maxwbatches) + { + shaderstate.wbatch++; + return NULL; + } + return &shaderstate.wbatches[shaderstate.wbatch++]; +} + +void D3D11BE_SetupViewCBuffer(void) +{ + cbuf_view_t *cbv; + D3D11_MAPPED_SUBRESOURCE msr; + if (FAILED(ID3D11DeviceContext_Map(d3ddevctx, (ID3D11Resource*)shaderstate.cbuffers[1], 0, D3D11_MAP_WRITE_DISCARD, 0, &msr))) + { + Con_Printf("BE_RotateForEntity: failed to map constant buffer\n"); + return; + } + cbv = (cbuf_view_t*)msr.pData; + + memcpy(cbv->m_projection, d3d_trueprojection/*r_refdef.m_projection*/, sizeof(cbv->m_projection)); + memcpy(cbv->m_view, r_refdef.m_view, sizeof(cbv->m_view)); + VectorCopy(r_origin, cbv->v_eyepos); + cbv->v_time = r_refdef.time; + + ID3D11DeviceContext_Unmap(d3ddevctx, (ID3D11Resource*)shaderstate.cbuffers[1], 0); +} + +//also updates the entity constant buffer +static void BE_RotateForEntity (const entity_t *e, const model_t *mod) +{ + float mv[16]; + float *m = shaderstate.m_model; + cbuf_entity_t *cbe; + D3D11_MAPPED_SUBRESOURCE msr; + if (FAILED(ID3D11DeviceContext_Map(d3ddevctx, (ID3D11Resource*)shaderstate.cbuffers[0], 0, D3D11_MAP_WRITE_DISCARD, 0, &msr))) + { + Con_Printf("BE_RotateForEntity: failed to map constant buffer\n"); + return; + } + cbe = (cbuf_entity_t*)msr.pData; + + + shaderstate.curentity = e; + + m[0] = e->axis[0][0]; + m[1] = e->axis[0][1]; + m[2] = e->axis[0][2]; + m[3] = 0; + + m[4] = e->axis[1][0]; + m[5] = e->axis[1][1]; + m[6] = e->axis[1][2]; + m[7] = 0; + + m[8] = e->axis[2][0]; + m[9] = e->axis[2][1]; + m[10] = e->axis[2][2]; + m[11] = 0; + + m[12] = e->origin[0]; + m[13] = e->origin[1]; + m[14] = e->origin[2]; + m[15] = 1; + + if (e->scale != 1 && e->scale != 0) //hexen 2 stuff + { + float z; + float escale; + escale = e->scale; + switch(e->drawflags&SCALE_TYPE_MASKIN) + { + default: + case SCALE_TYPE_UNIFORM: + VectorScale((m+0), escale, (m+0)); + VectorScale((m+4), escale, (m+4)); + VectorScale((m+8), escale, (m+8)); + break; + case SCALE_TYPE_XYONLY: + VectorScale((m+0), escale, (m+0)); + VectorScale((m+4), escale, (m+4)); + break; + case SCALE_TYPE_ZONLY: + VectorScale((m+8), escale, (m+8)); + break; + } + if (mod && (e->drawflags&SCALE_TYPE_MASKIN) != SCALE_TYPE_XYONLY) + { + switch(e->drawflags&SCALE_ORIGIN_MASKIN) + { + case SCALE_ORIGIN_CENTER: + z = ((mod->maxs[2] + mod->mins[2]) * (1-escale))/2; + VectorMA((m+12), z, e->axis[2], (m+12)); + break; + case SCALE_ORIGIN_BOTTOM: + VectorMA((m+12), mod->mins[2]*(1-escale), e->axis[2], (m+12)); + break; + case SCALE_ORIGIN_TOP: + VectorMA((m+12), -mod->maxs[2], e->axis[2], (m+12)); + break; + } + } + } + else if (mod && !strcmp(mod->name, "progs/eyes.mdl")) + { + /*resize eyes, to make them easier to see*/ + m[14] -= (22 + 8); + VectorScale((m+0), 2, (m+0)); + VectorScale((m+4), 2, (m+4)); + VectorScale((m+8), 2, (m+8)); + } + if (mod && !ruleset_allow_larger_models.ival && mod->clampscale != 1) + { //possibly this should be on a per-frame basis, but that's a real pain to do + Con_DPrintf("Rescaling %s by %f\n", mod->name, mod->clampscale); + VectorScale((m+0), mod->clampscale, (m+0)); + VectorScale((m+4), mod->clampscale, (m+4)); + VectorScale((m+8), mod->clampscale, (m+8)); + } + + if (e->flags & Q2RF_WEAPONMODEL && r_refdef.currentplayernum>=0) + { + /*FIXME: no bob*/ + float iv[16]; + Matrix4_Invert(r_refdef.m_view, iv); + Matrix4x4_CM_NewRotation(90, 1, 0, 0); + Matrix4_Multiply(iv, m, mv); + Matrix4_Multiply(mv, Matrix4x4_CM_NewRotation(-90, 1, 0, 0), iv); + Matrix4_Multiply(iv, Matrix4x4_CM_NewRotation(90, 0, 0, 1), mv); + + memcpy(cbe->m_model, mv, sizeof(cbe->m_model)); + } + else + { + memcpy(cbe->m_model, m, sizeof(cbe->m_model)); + } + cbe->e_time = r_refdef.time - shaderstate.curentity->shaderTime; + + VectorCopy(e->light_avg, cbe->e_light_ambient); + VectorCopy(e->light_dir, cbe->e_light_dir); + VectorCopy(e->light_range, cbe->e_light_mul); + + ID3D11DeviceContext_Unmap(d3ddevctx, (ID3D11Resource*)shaderstate.cbuffers[0], 0); + + { +// D3DVIEWPORT9 vport; +// IDirect3DDevice9_GetViewport(pD3DDev9, &vport); +// vport.MaxZ = (e->flags & Q2RF_DEPTHHACK)?0.333:1; +// IDirect3DDevice9_SetViewport(pD3DDev9, &vport); + } +} + +void D3D11BE_SubmitBatch(batch_t *batch) +{ + shaderstate.nummeshes = batch->meshes - batch->firstmesh; + if (!shaderstate.nummeshes) + return; + if (shaderstate.curentity != batch->ent) + { + BE_RotateForEntity(batch->ent, batch->ent->model); + shaderstate.curtime = r_refdef.time - shaderstate.curentity->shaderTime; + } + shaderstate.curbatch = batch; + shaderstate.batchvbo = batch->vbo; + shaderstate.meshlist = batch->mesh + batch->firstmesh; + shaderstate.curshader = batch->shader; + shaderstate.curtexnums = batch->skin; + shaderstate.flags = batch->flags; + + if (!shaderstate.batchvbo) + { + BE_GenTempMeshVBO(&shaderstate.batchvbo, batch->mesh[0]); + BE_DrawMeshChain_Internal(); + } + else + BE_DrawMeshChain_Internal(); +} + +void D3D11BE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_t *vbo, texnums_t *texnums, unsigned int beflags) +{ + shaderstate.curbatch = &shaderstate.dummybatch; + shaderstate.batchvbo = vbo; + shaderstate.curshader = shader; + shaderstate.curtexnums = texnums; + shaderstate.meshlist = meshlist; + shaderstate.nummeshes = nummeshes; + shaderstate.flags = beflags; + + if (!shaderstate.batchvbo) + { + BE_GenTempMeshVBO(&shaderstate.batchvbo, meshlist[0]); + shaderstate.nummeshes = 1; + BE_DrawMeshChain_Internal(); + } + else + BE_DrawMeshChain_Internal(); +} + +void D3D11BE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums, unsigned int beflags) +{ + shaderstate.curbatch = &shaderstate.dummybatch; + shaderstate.batchvbo = vbo; + shaderstate.curtime = realtime; + shaderstate.curshader = shader; + shaderstate.curtexnums = texnums?texnums:&shader->defaulttextures; + shaderstate.meshlist = &meshchain; + shaderstate.nummeshes = 1; + shaderstate.flags = beflags; + + if (!shaderstate.batchvbo) + { + BE_GenTempMeshVBO(&shaderstate.batchvbo, meshchain); + BE_DrawMeshChain_Internal(); + } + else + BE_DrawMeshChain_Internal(); +} + +static void BE_SubmitMeshesSortList(batch_t *sortlist) +{ + batch_t *batch; + for (batch = sortlist; batch; batch = batch->next) + { + if (batch->meshes == batch->firstmesh) + continue; + + if (batch->buildmeshes) + batch->buildmeshes(batch); + else if (batch->texture) + { + batch->shader = R_TextureAnimation(batch->ent->framestate.g[FS_REG].frame[0], batch->texture)->shader; + batch->skin = &batch->shader->defaulttextures; + } + + if (batch->shader->flags & SHADER_NODLIGHT) + if (shaderstate.mode == BEM_LIGHT || shaderstate.mode == BEM_SMAPLIGHT) + continue; + + if (batch->shader->flags & SHADER_SKY) + { + if (!batch->shader->prog) + { + if (shaderstate.mode == BEM_STANDARD) + R_DrawSkyChain (batch); + continue; + } + } + + BE_SubmitBatch(batch); + } +} + + +/*generates a new modelview matrix, as well as vpn vectors*/ +static void R_MirrorMatrix(plane_t *plane) +{ + float mirror[16]; + float view[16]; + float result[16]; + + vec3_t pnorm; + VectorNegate(plane->normal, pnorm); + + mirror[0] = 1-2*pnorm[0]*pnorm[0]; + mirror[1] = -2*pnorm[0]*pnorm[1]; + mirror[2] = -2*pnorm[0]*pnorm[2]; + mirror[3] = 0; + + mirror[4] = -2*pnorm[1]*pnorm[0]; + mirror[5] = 1-2*pnorm[1]*pnorm[1]; + mirror[6] = -2*pnorm[1]*pnorm[2] ; + mirror[7] = 0; + + mirror[8] = -2*pnorm[2]*pnorm[0]; + mirror[9] = -2*pnorm[2]*pnorm[1]; + mirror[10] = 1-2*pnorm[2]*pnorm[2]; + mirror[11] = 0; + + mirror[12] = -2*pnorm[0]*plane->dist; + mirror[13] = -2*pnorm[1]*plane->dist; + mirror[14] = -2*pnorm[2]*plane->dist; + mirror[15] = 1; + + view[0] = vpn[0]; + view[1] = vpn[1]; + view[2] = vpn[2]; + view[3] = 0; + + view[4] = -vright[0]; + view[5] = -vright[1]; + view[6] = -vright[2]; + view[7] = 0; + + view[8] = vup[0]; + view[9] = vup[1]; + view[10] = vup[2]; + view[11] = 0; + + view[12] = r_refdef.vieworg[0]; + view[13] = r_refdef.vieworg[1]; + view[14] = r_refdef.vieworg[2]; + view[15] = 1; + + VectorMA(r_refdef.vieworg, 0.25, plane->normal, r_refdef.pvsorigin); + + Matrix4_Multiply(mirror, view, result); + + vpn[0] = result[0]; + vpn[1] = result[1]; + vpn[2] = result[2]; + + vright[0] = -result[4]; + vright[1] = -result[5]; + vright[2] = -result[6]; + + vup[0] = result[8]; + vup[1] = result[9]; + vup[2] = result[10]; + + r_refdef.vieworg[0] = result[12]; + r_refdef.vieworg[1] = result[13]; + r_refdef.vieworg[2] = result[14]; +} +static entity_t *R_NearestPortal(plane_t *plane) +{ + int i; + entity_t *best = NULL; + float dist, bestd = 0; + for (i = 0; i < cl_numvisedicts; i++) + { + if (cl_visedicts[i].rtype == RT_PORTALSURFACE) + { + dist = DotProduct(cl_visedicts[i].origin, plane->normal)-plane->dist; + dist = fabs(dist); + if (dist < 64 && (!best || dist < bestd)) + best = &cl_visedicts[i]; + } + } + return best; +} + +static void TransformCoord(vec3_t in, vec3_t planea[3], vec3_t planeo, vec3_t viewa[3], vec3_t viewo, vec3_t result) +{ + int i; + vec3_t local; + vec3_t transformed; + float d; + + local[0] = in[0] - planeo[0]; + local[1] = in[1] - planeo[1]; + local[2] = in[2] - planeo[2]; + + VectorClear(transformed); + for ( i = 0 ; i < 3 ; i++ ) + { + d = DotProduct(local, planea[i]); + VectorMA(transformed, d, viewa[i], transformed); + } + + result[0] = transformed[0] + viewo[0]; + result[1] = transformed[1] + viewo[1]; + result[2] = transformed[2] + viewo[2]; +} +static void TransformDir(vec3_t in, vec3_t planea[3], vec3_t viewa[3], vec3_t result) +{ + int i; + float d; + vec3_t tmp; + + VectorCopy(in, tmp); + + VectorClear(result); + for ( i = 0 ; i < 3 ; i++ ) + { + d = DotProduct(tmp, planea[i]); + VectorMA(result, d, viewa[i], result); + } +} +static void R_RenderScene(void) +{ +// IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_PROJECTION, (D3DMATRIX*)d3d_trueprojection); +// IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_VIEW, (D3DMATRIX*)r_refdef.m_view); + R_SetFrustum (r_refdef.m_projection, r_refdef.m_view); + Surf_DrawWorld(); +} + +static void R_DrawPortal(batch_t *batch, batch_t **blist) +{ + entity_t *view; + float glplane[4]; + plane_t plane; + refdef_t oldrefdef; + mesh_t *mesh = batch->mesh[batch->firstmesh]; + int sort; + + if (r_refdef.recurse) + return; + + VectorCopy(mesh->normals_array[0], plane.normal); + plane.dist = DotProduct(mesh->xyz_array[0], plane.normal); + + //if we're too far away from the surface, don't draw anything + if (batch->shader->flags & SHADER_AGEN_PORTAL) + { + /*there's a portal alpha blend on that surface, that fades out after this distance*/ + if (DotProduct(r_refdef.vieworg, plane.normal)-plane.dist > batch->shader->portaldist) + return; + } + //if we're behind it, then also don't draw anything. + if (DotProduct(r_refdef.vieworg, plane.normal)-plane.dist < 0) + return; + + view = R_NearestPortal(&plane); + //if (!view) + // return; + + oldrefdef = r_refdef; + r_refdef.recurse = true; + + r_refdef.externalview = true; + + if (!view || VectorCompare(view->origin, view->oldorigin)) + { + r_refdef.flipcull ^= true; + R_MirrorMatrix(&plane); + } + else + { + float d; + vec3_t paxis[3], porigin, vaxis[3], vorg; + void PerpendicularVector( vec3_t dst, const vec3_t src ); + + /*calculate where the surface is meant to be*/ + VectorCopy(mesh->normals_array[0], paxis[0]); + PerpendicularVector(paxis[1], paxis[0]); + CrossProduct(paxis[0], paxis[1], paxis[2]); + d = DotProduct(view->origin, plane.normal) - plane.dist; + VectorMA(view->origin, -d, paxis[0], porigin); + + /*grab the camera origin*/ + VectorNegate(view->axis[0], vaxis[0]); + VectorNegate(view->axis[1], vaxis[1]); + VectorCopy(view->axis[2], vaxis[2]); + VectorCopy(view->oldorigin, vorg); + + VectorCopy(vorg, r_refdef.pvsorigin); + + /*rotate it a bit*/ + RotatePointAroundVector(vaxis[1], vaxis[0], view->axis[1], sin(realtime)*4); + CrossProduct(vaxis[0], vaxis[1], vaxis[2]); + + TransformCoord(oldrefdef.vieworg, paxis, porigin, vaxis, vorg, r_refdef.vieworg); + TransformDir(vpn, paxis, vaxis, vpn); + TransformDir(vright, paxis, vaxis, vright); + TransformDir(vup, paxis, vaxis, vup); + } + Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_refdef.vieworg); + VectorAngles(vpn, vup, r_refdef.viewangles); + VectorCopy(r_refdef.vieworg, r_origin); + +/*FIXME: the batch stuff should be done in renderscene*/ + + /*fixup the first mesh index*/ + for (sort = 0; sort < SHADER_SORT_COUNT; sort++) + for (batch = blist[sort]; batch; batch = batch->next) + { + batch->firstmesh = batch->meshes; + } + + /*FIXME: can we get away with stenciling the screen?*/ + /*Add to frustum culling instead of clip planes?*/ + glplane[0] = plane.normal[0]; + glplane[1] = plane.normal[1]; + glplane[2] = plane.normal[2]; + glplane[3] = -plane.dist; +// IDirect3DDevice9_SetClipPlane(pD3DDev9, 0, glplane); +// IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_CLIPPLANEENABLE, D3DCLIPPLANE0); + R_RenderScene(); +// IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_CLIPPLANEENABLE, 0); + + for (sort = 0; sort < SHADER_SORT_COUNT; sort++) + for (batch = blist[sort]; batch; batch = batch->next) + { + batch->firstmesh = 0; + } + r_refdef = oldrefdef; + + /*broken stuff*/ + AngleVectors (r_refdef.viewangles, vpn, vright, vup); + VectorCopy (r_refdef.vieworg, r_origin); + +// IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_PROJECTION, (D3DMATRIX*)d3d_trueprojection); +// IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_VIEW, (D3DMATRIX*)r_refdef.m_view); + R_SetFrustum (r_refdef.m_projection, r_refdef.m_view); +} + +static void BE_SubmitMeshesPortals(batch_t **worldlist, batch_t *dynamiclist) +{ + batch_t *batch, *old; + int i; + /*attempt to draw portal shaders*/ + if (shaderstate.mode == BEM_STANDARD) + { + for (i = 0; i < 2; i++) + { + for (batch = i?dynamiclist:worldlist[SHADER_SORT_PORTAL]; batch; batch = batch->next) + { + if (batch->meshes == batch->firstmesh) + continue; + + if (batch->buildmeshes) + batch->buildmeshes(batch); + else + batch->shader = R_TextureAnimation(batch->ent->framestate.g[FS_REG].frame[0], batch->texture)->shader; + + + /*draw already-drawn portals as depth-only, to ensure that their contents are not harmed*/ + BE_SelectMode(BEM_DEPTHONLY); + for (old = worldlist[SHADER_SORT_PORTAL]; old && old != batch; old = old->next) + { + if (old->meshes == old->firstmesh) + continue; + BE_SubmitBatch(old); + } + if (!old) + { + for (old = dynamiclist; old != batch; old = old->next) + { + if (old->meshes == old->firstmesh) + continue; + BE_SubmitBatch(old); + } + } + BE_SelectMode(BEM_STANDARD); + + R_DrawPortal(batch, worldlist); + + /*clear depth again*/ +// IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1, 0); + } + } + } +} + +void D3D11BE_SubmitMeshes (qboolean drawworld, batch_t **blist, int first, int stop) +{ + model_t *model = cl.worldmodel; + int i; + + for (i = first; i < stop; i++) + { + if (drawworld) + { + if (i == SHADER_SORT_PORTAL /*&& !r_noportals.ival*/ && !r_refdef.recurse) + BE_SubmitMeshesPortals(model->batches, blist[i]); + + BE_SubmitMeshesSortList(model->batches[i]); + } + BE_SubmitMeshesSortList(blist[i]); + } +} + +#ifdef RTLIGHTS +void D3D11BE_BaseEntTextures(void) +{ + batch_t *batches[SHADER_SORT_COUNT]; + BE_GenModelBatches(batches); + D3D11BE_SubmitMeshes(false, batches, SHADER_SORT_PORTAL, SHADER_SORT_DECAL); + BE_SelectEntity(&r_worldentity); +} + +void D3D11BE_RenderShadowBuffer(unsigned int numverts, ID3D11Buffer *vbuf, unsigned int numindicies, ID3D11Buffer *ibuf) +{ +/* + IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_VERT, vbuf, 0, sizeof(vecV_t)); + IDirect3DDevice9_SetIndices(pD3DDev9, ibuf); + + if (0 != shaderstate.curvertdecl) + { + shaderstate.curvertdecl = 0; + d3dcheck(IDirect3DDevice9_SetVertexDeclaration(pD3DDev9, vertexdecls[shaderstate.curvertdecl])); + } + + IDirect3DDevice9_DrawIndexedPrimitive(pD3DDev9, D3DPT_TRIANGLELIST, 0, 0, numverts, 0, numindicies/3); +*/ +} +#endif + +void D3D11BE_DrawWorld (qboolean drawworld, qbyte *vis) +{ + batch_t *batches[SHADER_SORT_COUNT]; + RSpeedLocals(); + + shaderstate.curentity = NULL; + + if (!r_refdef.recurse) + { + if (shaderstate.wbatch > shaderstate.maxwbatches) + { + int newm = shaderstate.wbatch; + Z_Free(shaderstate.wbatches); + shaderstate.wbatches = Z_Malloc(newm * sizeof(*shaderstate.wbatches)); + memset(shaderstate.wbatches + shaderstate.maxwbatches, 0, (newm - shaderstate.maxwbatches) * sizeof(*shaderstate.wbatches)); + shaderstate.maxwbatches = newm; + } + shaderstate.wbatch = 0; + } + + D3D11BE_SetupViewCBuffer(); + + BE_GenModelBatches(batches); + + if (vis) + { + BE_UploadLightmaps(false); + + //make sure the world draws correctly + r_worldentity.shaderRGBAf[0] = 1; + r_worldentity.shaderRGBAf[1] = 1; + r_worldentity.shaderRGBAf[2] = 1; + r_worldentity.shaderRGBAf[3] = 1; + r_worldentity.axis[0][0] = 1; + r_worldentity.axis[1][1] = 1; + r_worldentity.axis[2][2] = 1; + + BE_SelectMode(BEM_STANDARD); + + RSpeedRemark(); + D3D11BE_SubmitMeshes(true, batches, SHADER_SORT_PORTAL, SHADER_SORT_DECAL); + RSpeedEnd(RSPEED_WORLD); + +#ifdef RTLIGHTS + RSpeedRemark(); + D3D11BE_SelectEntity(&r_worldentity); + Sh_DrawLights(vis); + RSpeedEnd(RSPEED_STENCILSHADOWS); +#endif + + D3D11BE_SubmitMeshes(true, batches, SHADER_SORT_DECAL, SHADER_SORT_COUNT); + } + else + { + RSpeedRemark(); + D3D11BE_SubmitMeshes(false, batches, SHADER_SORT_PORTAL, SHADER_SORT_COUNT); + RSpeedEnd(RSPEED_DRAWENTITIES); + } + + R_RenderDlights (); + + BE_RotateForEntity(&r_worldentity, NULL); +} + + +#endif diff --git a/engine/d3d/d3d11_image.c b/engine/d3d/d3d11_image.c new file mode 100644 index 000000000..28c81bc29 --- /dev/null +++ b/engine/d3d/d3d11_image.c @@ -0,0 +1,542 @@ +#include "quakedef.h" +#ifdef D3D11QUAKE +#include "winquake.h" +#define COBJMACROS +#include +extern ID3D11Device *pD3DDev11; +extern ID3D11DeviceContext *d3ddevctx; + +typedef struct d3dtexture_s +{ + texcom_t com; + ID3D11ShaderResourceView *view; + struct d3dtexture_s *prev; + struct d3dtexture_s *next; + ID3D11Texture2D *tex2d; + char name[1]; +} d3d11texture_t; +static d3d11texture_t *d3d11textures; + +void D3D11_Image_Shutdown(void) +{ + //destroy all named textures + while(d3d11textures) + { + d3d11texture_t *t = d3d11textures; + d3d11textures = t->next; + + if (t->view) + ID3D11ShaderResourceView_Release(t->view); + if (t->tex2d) + ID3D11Texture2D_Release(t->tex2d); + + free(t); + } +} + +void D3D11_DestroyTexture (texid_t tex) +{ + d3d11texture_t *t = (d3d11texture_t*)tex.ref; + + ID3D11Texture2D *tx = tex.ptr; + if (t->view) + ID3D11ShaderResourceView_Release(t->view); + if (t->tex2d) + ID3D11Texture2D_Release(t->tex2d); + t->view = NULL; + t->tex2d = NULL; + + if (t->prev) + t->prev->next = t->next; + else + d3d11textures = t->next; + if (t->next) + t->next->prev = t->prev; + t->prev = NULL; + t->next = NULL; + free(t); +} + +static d3d11texture_t *d3d_lookup_texture(char *ident) +{ + d3d11texture_t *tex; + + if (*ident) + { + for (tex = d3d11textures; tex; tex = tex->next) + if (!strcmp(tex->name, ident)) + return tex; + } + + tex = calloc(1, sizeof(*tex)+strlen(ident)); + strcpy(tex->name, ident); + tex->view = NULL; + tex->tex2d = NULL; + tex->next = d3d11textures; + tex->prev = NULL; + d3d11textures = tex; + if (tex->next) + tex->next->prev = tex; + + return tex; +} + +extern cvar_t gl_picmip; +extern cvar_t gl_picmip2d; + +static texid_t ToTexID(d3d11texture_t *tex) +{ + texid_t tid; + tid.ref = &tex->com; + if (!tex->view) + ID3D11Device_CreateShaderResourceView(pD3DDev11, (ID3D11Resource *)tex->tex2d, NULL, &tex->view); + tid.ptr = tex->view; + return tid; +} + +static void *D3D11_AllocNewTextureData(void *datargba, int width, int height, unsigned int flags) +{ + HRESULT hr; + ID3D11Texture2D *tx = NULL; + D3D11_TEXTURE2D_DESC tdesc = {0}; + D3D11_SUBRESOURCE_DATA subresdesc = {0}; + + subresdesc.pSysMem = datargba; + subresdesc.SysMemPitch = width*4; + subresdesc.SysMemSlicePitch = width*height*4; + + tdesc.Width = width; + tdesc.Height = height; + tdesc.MipLevels = 1; + tdesc.ArraySize = 1; + tdesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + tdesc.SampleDesc.Count = 1; + tdesc.SampleDesc.Quality = 0; + tdesc.Usage = datargba?D3D11_USAGE_DEFAULT:D3D11_USAGE_DYNAMIC; + tdesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + tdesc.CPUAccessFlags = 0; + tdesc.MiscFlags = 0; + hr = ID3D11Device_CreateTexture2D(pD3DDev11, &tdesc, (datargba?&subresdesc:NULL), &tx); + if (FAILED(hr)) + { + tx = NULL; + } + return tx; +} +texid_t D3D11_AllocNewTexture(char *ident, int width, int height, unsigned int flags) +{ + void *img = D3D11_AllocNewTextureData(NULL, width, height, flags); + d3d11texture_t *t = d3d_lookup_texture(""); + t->tex2d = img; + + return ToTexID(t); +} + +static void D3D11_RoundDimensions(int *scaled_width, int *scaled_height, qboolean mipmap) +{ +// if (gl_config.arb_texture_non_power_of_two) //NPOT is a simple extension that relaxes errors. +// { +// TRACE(("dbg: GL_RoundDimensions: GL_ARB_texture_non_power_of_two\n")); +// } +// else + { + int width = *scaled_width; + int height = *scaled_height; + for (*scaled_width = 1 ; *scaled_width < width ; *scaled_width<<=1) + ; + for (*scaled_height = 1 ; *scaled_height < height ; *scaled_height<<=1) + ; + } + + if (mipmap) + { + TRACE(("dbg: GL_RoundDimensions: %i\n", gl_picmip.ival)); + *scaled_width >>= gl_picmip.ival; + *scaled_height >>= gl_picmip.ival; + } + else + { + *scaled_width >>= gl_picmip2d.ival; + *scaled_height >>= gl_picmip2d.ival; + } + + TRACE(("dbg: GL_RoundDimensions: %i\n", gl_max_size.ival)); + if (gl_max_size.ival) + { + if (*scaled_width > gl_max_size.ival) + *scaled_width = gl_max_size.ival; + if (*scaled_height > gl_max_size.ival) + *scaled_height = gl_max_size.ival; + } + + if (*scaled_width < 1) + *scaled_width = 1; + if (*scaled_height < 1) + *scaled_height = 1; +} + +#if 0 +static void D3D_MipMap (qbyte *out, int outwidth, int outheight, qbyte *in, int inwidth, int inheight) +{ + int i, j; + qbyte *inrow; + + //with npot + int rowwidth = inwidth*4; //rowwidth is the byte width of the input + inrow = in; + + for (i=0 ; i>2; + out[1] = (in[1] + in[5] + in[rowwidth+1] + in[rowwidth+5])>>2; + out[2] = (in[2] + in[6] + in[rowwidth+2] + in[rowwidth+6])>>2; + out[3] = (in[3] + in[7] + in[rowwidth+3] + in[rowwidth+7])>>2; + } + } +} +#endif + +static void Upload_Texture_32(ID3D11Texture2D *tex, unsigned int *data, int width, int height, unsigned int flags) +{ +// int x, y; +// unsigned int *dest; +// unsigned char swapbuf[4]; +// unsigned char swapbuf2[4]; +// D3D11_MAPPED_SUBRESOURCE lock; + + D3D11_TEXTURE2D_DESC desc; + + ID3D11Texture2D_GetDesc(tex, &desc); + if (width == desc.Width && height == desc.Height) + { + ID3D11DeviceContext_UpdateSubresource(d3ddevctx, (ID3D11Resource*)tex, 0, NULL, data, width*4, width*height*4); + return; + } + + Con_Printf("Wrong size!\n"); + return; +#if 0 + if (FAILED(ID3D11DeviceContext_Map(d3ddevctx, (ID3D11Resource*)tex, 0, D3D11_MAP_WRITE_DISCARD, 0, &lock))) + { + Con_Printf("Dynamic texture update failed\n"); + return; + } + + if (width == desc.Width && height == desc.Height) + { + for (y = 0; y < height; y++) + { + dest = (unsigned int *)((char *)lock.pData + lock.RowPitch*y); + for (x = 0; x < width; x++) + { + *(unsigned int*)swapbuf2 = *(unsigned int*)swapbuf = data[x]; + swapbuf[0] = swapbuf2[2]; + swapbuf[2] = swapbuf2[0]; + dest[x] = *(unsigned int*)swapbuf; + } + data += width; + } + } + else + { + int x, y; + int iny; + unsigned int *row, *inrow; + + for (y = 0; y < desc.Height; y++) + { + row = (unsigned int*)((char *)lock.pData + lock.RowPitch*y); + iny = (y * height) / desc.Height; + inrow = data + width*iny; + for (x = 0; x < desc.Width; x++) + { + *(unsigned int*)swapbuf2 = *(unsigned int*)swapbuf = inrow[(x * width)/desc.Width]; + swapbuf[0] = swapbuf2[2]; + swapbuf[2] = swapbuf2[0]; + row[x] = *(unsigned int*)swapbuf; + } + } + } + + ID3D11DeviceContext_Unmap(d3ddevctx, (ID3D11Resource*)tex, 0); +#endif +} + +//create a basic shader from a 32bit image +static void D3D11_LoadTexture_32(d3d11texture_t *tex, unsigned int *data, int width, int height, int flags) +{ + int nwidth, nheight; + +/* + if (!(flags & TF_MANDATORY)) + { + Con_Printf("Texture upload missing flags\n"); + return NULL; + } +*/ + + nwidth = width; + nheight = height; + D3D11_RoundDimensions(&nwidth, &nheight, !(flags & IF_NOMIPMAP)); + + if (!tex->tex2d) + { + tex->tex2d = D3D11_AllocNewTextureData(data, width, height, flags); + return; + } + + Upload_Texture_32(tex->tex2d, data, width, height, flags); +} + +static void D3D11_LoadTexture_8(d3d11texture_t *tex, unsigned char *data, unsigned int *pal32, int width, int height, int flags, enum uploadfmt fmt) +{ + static unsigned trans[1024*1024]; + int i, s; + qboolean noalpha; + int p; + + if (width*height > 1024*1024) + Sys_Error("GL_Upload8: image too big (%i*%i)", width, height); + + s = width*height; + // if there are no transparent pixels, make it a 3 component + // texture even if it was specified as otherwise + if (fmt == TF_TRANS8_FULLBRIGHT) + { + for (i=0 ; i 255-vid.fullbright) + trans[i] = pal32[p]; + else + { + noalpha = false; + trans[i] = 0; + } + } + } + else if ((fmt!=TF_SOLID8) && !(flags & IF_NOALPHA)) + { + noalpha = true; + for (i=0 ; i>4]] & 0x00ffffff; + trans[i] |= ( int )ColorPercent[p&15] << 24; + //trans[i] = 0x7fff0000; + } + break; +*/ + } + } + else + { + for (i=(s&~3)-4 ; i>=0 ; i-=4) + { + trans[i] = pal32[data[i]]; + trans[i+1] = pal32[data[i+1]]; + trans[i+2] = pal32[data[i+2]]; + trans[i+3] = pal32[data[i+3]]; + } + for (i=s&~3 ; imodified = false; + if (!TEXVALID(lm->lightmap_texture)) + { + lm->lightmap_texture = R_AllocNewTexture("***lightmap***", LMBLOCK_WIDTH, LMBLOCK_HEIGHT, 0); + if (!lm->lightmap_texture.ref) + return; + } + tex = (d3d11texture_t*)lm->lightmap_texture.ref; + + if (!tex->tex2d) + tex->tex2d = D3D11_AllocNewTextureData(lm->lightmaps, lm->width, lm->height, 0); + else + { + if (tex->view) + { + ID3D11ShaderResourceView_Release(tex->view); + tex->view = NULL; + } + Upload_Texture_32(tex->tex2d, (void*)lm->lightmaps, lm->width, lm->height, 0); + } + + lm->lightmap_texture = ToTexID(tex); +} + +texid_t D3D11_LoadTexture (char *identifier, int width, int height, enum uploadfmt fmt, void *data, unsigned int flags) +{ + d3d11texture_t *tex; + switch (fmt) + { + case TF_TRANS8_FULLBRIGHT: + { + qbyte *d = data; + unsigned int c = width * height; + while (c) + { + if (d[--c] > 255 - vid.fullbright) + break; + } + /*reject it if there's no fullbrights*/ + if (!c) + return r_nulltex; + } + break; + case TF_INVALID: + case TF_RGBA32: + case TF_BGRA32: + case TF_RGBX32: + case TF_RGB24: + case TF_BGR24_FLIP: + case TF_SOLID8: + case TF_TRANS8: + case TF_HEIGHT8: + case TF_HEIGHT8PAL: + case TF_H2_T7G1: + case TF_H2_TRANS8_0: + case TF_H2_T4A4: + case TF_PALETTES: + case TF_8PAL24: + case TF_8PAL32: + break; + + } + tex = d3d_lookup_texture(identifier); + + switch (fmt) + { + case TF_SOLID8: + case TF_TRANS8: + case TF_H2_T7G1: + case TF_H2_TRANS8_0: + case TF_H2_T4A4: + case TF_TRANS8_FULLBRIGHT: + D3D11_LoadTexture_8(tex, data, d_8to24rgbtable, width, height, flags, fmt); + return ToTexID(tex); + case TF_RGBX32: + flags |= IF_NOALPHA; + case TF_RGBA32: + D3D11_LoadTexture_32(tex, data, width, height, flags); + return ToTexID(tex); + case TF_HEIGHT8PAL: + OutputDebugString(va("D3D11_LoadTexture doesn't support fmt TF_HEIGHT8PAL (%s)\n", identifier)); + return r_nulltex; + default: + OutputDebugString(va("D3D11_LoadTexture doesn't support fmt %i (%s)\n", fmt, identifier)); + return r_nulltex; + } +} + +texid_t D3D11_LoadCompressed (char *name) +{ + return r_nulltex; +} + +texid_t D3D11_FindTexture (char *identifier, unsigned int flags) +{ + d3d11texture_t *tex = d3d_lookup_texture(identifier); + if (tex->tex2d) + return ToTexID(tex); + return r_nulltex; +} + +texid_t D3D11_LoadTexture8Pal32 (char *identifier, int width, int height, qbyte *data, qbyte *palette32, unsigned int flags) +{ + d3d11texture_t *tex = d3d_lookup_texture(identifier); + D3D11_LoadTexture_8(tex, data, (unsigned int *)palette32, width, height, flags, TF_SOLID8); + return ToTexID(tex); +} +texid_t D3D11_LoadTexture8Pal24 (char *identifier, int width, int height, qbyte *data, qbyte *palette24, unsigned int flags) +{ + unsigned int pal32[256]; + int i; + for (i = 0; i < 256; i++) + { + pal32[i] = 0x00000000 | + (palette24[i*3+2]<<24) | + (palette24[i*3+1]<<8) | + (palette24[i*3+0]<<0); + } + return D3D11_LoadTexture8Pal32(identifier, width, height, data, (qbyte*)pal32, flags); +} + +#endif diff --git a/engine/d3d/d3d11_shader.c b/engine/d3d/d3d11_shader.c new file mode 100644 index 000000000..16135eeda --- /dev/null +++ b/engine/d3d/d3d11_shader.c @@ -0,0 +1,341 @@ +#include "quakedef.h" + +#ifdef D3D11QUAKE +#include "shader.h" +#include "winquake.h" +#define COBJMACROS +#include +extern ID3D11Device *pD3DDev11; + + +typedef struct _D3D_SHADER_MACRO +{ + LPCSTR Name; + LPCSTR Definition; + +} D3D_SHADER_MACRO, *LPD3D_SHADER_MACRO; + +typedef enum _D3D_INCLUDE_TYPE { + D3D_INCLUDE_LOCAL = 0, + D3D_INCLUDE_SYSTEM = ( D3D_INCLUDE_LOCAL + 1 ), + D3D_INCLUDE_FORCE_DWORD = 0x7fffffff +} D3D_INCLUDE_TYPE; + +#undef INTERFACE +#define INTERFACE ID3DInclude +DECLARE_INTERFACE_(INTERFACE, IUnknown) +{ + STDMETHOD(Open)(THIS_ D3D_INCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes) PURE; + STDMETHOD(Close)(THIS_ LPCVOID pData) PURE; +}; + +#undef INTERFACE +#define INTERFACE ID3DBlob + +DECLARE_INTERFACE_(INTERFACE, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD_(LPVOID, GetBufferPointer)(THIS) PURE; + STDMETHOD_(SIZE_T, GetBufferSize)(THIS) PURE; +}; + +HRESULT (WINAPI *pD3DCompile) ( + LPCVOID pSrcData, + SIZE_T SrcDataSize, + LPCSTR pSourceName, + const D3D_SHADER_MACRO *pDefines, + ID3DInclude *pInclude, + LPCSTR pEntrypoint, + LPCSTR pTarget, + UINT Flags1, + UINT Flags2, + ID3DBlob **ppCode, + ID3DBlob **ppErrorMsgs +); +dllhandle_t *shaderlib; + + + +void D3D11Shader_Init(void) +{ + dllfunction_t funcs[] = + { + {(void**)&pD3DCompile, "D3DCompileFromMemory"}, + {NULL,NULL} + }; + + if (!shaderlib) + shaderlib = Sys_LoadLibrary("D3dcompiler_34.dll", funcs); + + if (!shaderlib) + return; +} + +HRESULT STDMETHODCALLTYPE d3dinclude_Close(ID3DInclude *this, LPCVOID pData) +{ + free((void*)pData); + return S_OK; +} +HRESULT STDMETHODCALLTYPE d3dinclude_Open(ID3DInclude *this, D3D_INCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes) +{ + if (IncludeType == D3D_INCLUDE_SYSTEM) + { + if (!strcmp(pFileName, "ftedefs.h")) + { + static const char *defstruct = + "cbuffer ftemodeldefs : register(b0)\n" + "{\n" + "matrix m_model;\n" + "float3 e_eyepos; float e_time;\n" + "float3 e_light_ambient; float pad1;\n" + "float3 e_light_dir; float pad2;\n" + "float3 e_light_mul; float pad3;\n" + "};\n" + "cbuffer fteviewdefs : register(b1)\n" + "{\n" + "matrix m_view;\n" + "matrix m_projection;\n" + "float3 v_eyepos; float v_time;\n" + "};\n" + ; + *ppData = strdup(defstruct); + *pBytes = strlen(*ppData); + return S_OK; + } + } + else + { + + } + return E_FAIL; +} +ID3DIncludeVtbl myd3dincludetab = +{ + d3dinclude_Open, + d3dinclude_Close +}; +ID3DInclude myd3dinclude = +{ + &myd3dincludetab +}; + +typedef struct +{ + vecV_t coord; + vec2_t tex; + vec2_t lm; + vec3_t ndir; + vec3_t sdir; + vec3_t tdir; + byte_vec4_t colorsb; +} vbovdata_t; + +qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, int permu, char **precompilerconstants, char *vert, char *frag) +{ + D3D_SHADER_MACRO defines[64]; + ID3DBlob *vcode = NULL, *fcode = NULL, *errors = NULL; + qboolean success = false; + + prog->handle[permu].hlsl.vert = NULL; + prog->handle[permu].hlsl.frag = NULL; + prog->handle[permu].hlsl.layout = NULL; + + if (pD3DCompile) + { + int consts; + for (consts = 2; precompilerconstants[consts]; consts++) + ; + if (consts >= sizeof(defines) / sizeof(defines[0])) + return success; + + consts = 0; + defines[consts].Name = NULL; /*shader type*/ + defines[consts].Definition = "1"; + consts++; + + defines[consts].Name = "ENGINE_"DISTRIBUTION; + defines[consts].Definition = __DATE__; + consts++; + + for (; *precompilerconstants; precompilerconstants++) + { + defines[consts].Name = NULL; + defines[consts].Definition = NULL; + consts++; + } + + defines[consts].Name = NULL; + defines[consts].Definition = NULL; + + success = true; + + defines[0].Name = "VERTEX_SHADER"; + if (FAILED(pD3DCompile(vert, strlen(vert), name, defines, &myd3dinclude, "main", "vs_4_0", 0, 0, &vcode, &errors))) + success = false; + else + { + if (FAILED(ID3D11Device_CreateVertexShader(pD3DDev11, vcode->lpVtbl->GetBufferPointer(vcode), vcode->lpVtbl->GetBufferSize(vcode), NULL, (ID3D11VertexShader**)&prog->handle[permu].hlsl.vert))) + success = false; + } + if (errors) + { + char *messages = errors->lpVtbl->GetBufferPointer(errors); + Con_Printf("%s", messages); + errors->lpVtbl->Release(errors); + } + + defines[0].Name = "FRAGMENT_SHADER"; + if (FAILED(pD3DCompile(frag, strlen(frag), name, defines, &myd3dinclude, "main", "ps_4_0", 0, 0, &fcode, &errors))) + success = false; + else + { + if (FAILED(ID3D11Device_CreatePixelShader(pD3DDev11, fcode->lpVtbl->GetBufferPointer(fcode), fcode->lpVtbl->GetBufferSize(fcode), NULL, (ID3D11PixelShader**)&prog->handle[permu].hlsl.frag))) + success = false; + } + if (errors) + { + char *messages = errors->lpVtbl->GetBufferPointer(errors); + Con_Printf("%s", messages); + errors->lpVtbl->Release(errors); + } + + + + if (success) + { + D3D11_INPUT_ELEMENT_DESC decl[13]; + int elements = 0; + vbovdata_t *foo = NULL; + + decl[elements].SemanticName = "POSITION"; + decl[elements].SemanticIndex = 0; + decl[elements].Format = DXGI_FORMAT_R32G32B32_FLOAT; + decl[elements].InputSlot = 0; + decl[elements].AlignedByteOffset = (char*)&foo->coord[0] - (char*)NULL; + decl[elements].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + decl[elements].InstanceDataStepRate = 0; + elements++; + + decl[elements].SemanticName = "TEXCOORD"; + decl[elements].SemanticIndex = 0; + decl[elements].Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + decl[elements].InputSlot = 0; + decl[elements].AlignedByteOffset = (char*)&foo->tex[0] - (char*)NULL; + decl[elements].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + decl[elements].InstanceDataStepRate = 0; + elements++; + /* + decl[elements].SemanticName = "TEXCOORD"; + decl[elements].SemanticIndex = 1; + decl[elements].Format = DXGI_FORMAT_R32G32_FLOAT; + decl[elements].InputSlot = 1; + decl[elements].AlignedByteOffset = (char*)&foo->lm[0] - (char*)NULL; + decl[elements].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + decl[elements].InstanceDataStepRate = 0; + elements++; + */ + decl[elements].SemanticName = "COLOR"; + decl[elements].SemanticIndex = 0; + decl[elements].Format = DXGI_FORMAT_R8G8B8A8_UNORM; + decl[elements].InputSlot = 0; + decl[elements].AlignedByteOffset = (char*)&foo->colorsb[0] - (char*)NULL; + decl[elements].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + decl[elements].InstanceDataStepRate = 0; + elements++; + + decl[elements].SemanticName = "NORMAL"; + decl[elements].SemanticIndex = 0; + decl[elements].Format = DXGI_FORMAT_R32G32B32_FLOAT; + decl[elements].InputSlot = 0; + decl[elements].AlignedByteOffset = (char*)&foo->ndir[0] - (char*)NULL; + decl[elements].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + decl[elements].InstanceDataStepRate = 0; + elements++; + + decl[elements].SemanticName = "TANGENT"; + decl[elements].SemanticIndex = 0; + decl[elements].Format = DXGI_FORMAT_R32G32B32_FLOAT; + decl[elements].InputSlot = 0; + decl[elements].AlignedByteOffset = (char*)&foo->sdir[0] - (char*)NULL; + decl[elements].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + decl[elements].InstanceDataStepRate = 0; + elements++; + + decl[elements].SemanticName = "BINORMAL"; + decl[elements].SemanticIndex = 0; + decl[elements].Format = DXGI_FORMAT_R32G32B32_FLOAT; + decl[elements].InputSlot = 0; + decl[elements].AlignedByteOffset = (char*)&foo->tdir[0] - (char*)NULL; + decl[elements].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + decl[elements].InstanceDataStepRate = 0; + elements++; + +/* + decl[elements].SemanticName = "BLENDWEIGHT"; + decl[elements].SemanticIndex = 0; + decl[elements].Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + decl[elements].InputSlot = 0; + decl[elements].AlignedByteOffset = 0; + decl[elements].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + decl[elements].InstanceDataStepRate = 0; + elements++; + + decl[elements].SemanticName = "BLENDINDICIES"; + decl[elements].SemanticIndex = 0; + decl[elements].Format = DXGI_FORMAT_R8G8B8A8_UINT; + decl[elements].InputSlot = 0; + decl[elements].AlignedByteOffset = 0; + decl[elements].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + decl[elements].InstanceDataStepRate = 0; + elements++; +*/ + if (FAILED(ID3D11Device_CreateInputLayout(pD3DDev11, decl, elements, vcode->lpVtbl->GetBufferPointer(vcode), vcode->lpVtbl->GetBufferSize(vcode), (ID3D11InputLayout**)&prog->handle[permu].hlsl.layout))) + { + Con_Printf("HLSL Shader %s requires unsupported inputs\n", name); + success = false; + } + } + + if (vcode) + vcode->lpVtbl->Release(vcode); + if (fcode) + fcode->lpVtbl->Release(fcode); + } + return success; +} +/* +static int D3D11Shader_FindUniform_(LPD3DXCONSTANTTABLE ct, char *name) +{ + if (ct) + { + UINT dc = 1; + D3DXCONSTANT_DESC d; + if (!FAILED(ct->lpVtbl->GetConstantDesc(ct, name, &d, &dc))) + return d.RegisterIndex; + } + return -1; +} +*/ +int D3D11Shader_FindUniform(union programhandle_u *h, int type, char *name) +{ +#if 0 + int offs; + + if (!type || type == 1) + { + offs = D3D11Shader_FindUniform_(h->hlsl.ctabv, name); + if (offs >= 0) + return offs; + } + if (!type || type == 2) + { + offs = D3D11Shader_FindUniform_(h->hlsl.ctabf, name); + if (offs >= 0) + return offs; + } +#endif + return -1; +} +#endif \ No newline at end of file diff --git a/engine/d3d/d3d_backend.c b/engine/d3d/d3d_backend.c index baaee6ad0..e9a7d5de4 100644 --- a/engine/d3d/d3d_backend.c +++ b/engine/d3d/d3d_backend.c @@ -1,7 +1,7 @@ #include "quakedef.h" #include "glquake.h" #include "gl_draw.h" -#ifdef D3DQUAKE +#ifdef D3D9QUAKE #include "shader.h" #if !defined(HMONITOR_DECLARED) && (WINVER < 0x0500) #define HMONITOR_DECLARED @@ -277,7 +277,7 @@ static void BE_ApplyTMUState(unsigned int tu, unsigned int flags) } } -static void D3DBE_ApplyShaderBits(unsigned int bits) +static void BE_ApplyShaderBits(unsigned int bits) { unsigned int delta; @@ -419,7 +419,7 @@ static void D3DBE_ApplyShaderBits(unsigned int bits) } } -void D3DBE_Reset(qboolean before) +void D3D9BE_Reset(qboolean before) { int i, tmu; if (before) @@ -560,7 +560,7 @@ void D3DBE_Reset(qboolean before) /*force all state to change, thus setting a known state*/ shaderstate.shaderbits = ~0; - D3DBE_ApplyShaderBits(0); + BE_ApplyShaderBits(0); } } @@ -579,7 +579,7 @@ static const char LIGHTPASS_SHADER[] = "\ }\n\ }"; -void D3DBE_Init(void) +void D3D9BE_Init(void) { be_maxpasses = MAX_TMUS; memset(&shaderstate, 0, sizeof(shaderstate)); @@ -592,7 +592,7 @@ void D3DBE_Init(void) shaderstate.dynst_size = sizeof(vec2_t) * DYNVBUFFSIZE; shaderstate.dynidx_size = sizeof(index_t) * DYNIBUFFSIZE; - D3DBE_Reset(false); + D3D9BE_Reset(false); shaderstate.shader_rtlight = R_RegisterShader("rtlight", LIGHTPASS_SHADER); @@ -1612,7 +1612,7 @@ static qboolean BE_DrawMeshChain_SetupPass(shaderpass_t *pass, unsigned int vert d3dcheck(IDirect3DDevice9_SetVertexDeclaration(pD3DDev9, vertexdecls[shaderstate.curvertdecl])); } - D3DBE_ApplyShaderBits(pass->shaderbits); + BE_ApplyShaderBits(pass->shaderbits); return true; } @@ -1770,7 +1770,7 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertcount, unsigned i BE_ApplyUniforms(p, perm); - D3DBE_ApplyShaderBits(s->passes->shaderbits); + BE_ApplyShaderBits(s->passes->shaderbits); /*activate tmus*/ for (passno = 0; passno < s->numpasses; passno++) @@ -1902,7 +1902,7 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertcount, unsigned i IDirect3DDevice9_SetPixelShader(pD3DDev9, NULL); } -void D3DBE_Cull(unsigned int cullflags) +void D3D9BE_Cull(unsigned int cullflags) { cullflags |= r_refdef.flipcull; if (shaderstate.curcull != cullflags) @@ -1942,7 +1942,7 @@ static void BE_DrawMeshChain_Internal(void) float pushdepth; // float pushfactor; - D3DBE_Cull(shaderstate.curshader->flags & (SHADER_CULL_FRONT | SHADER_CULL_BACK)); + D3D9BE_Cull(shaderstate.curshader->flags & (SHADER_CULL_FRONT | SHADER_CULL_BACK)); pushdepth = (shaderstate.curshader->polyoffset.factor + ((shaderstate.flags & BEF_PUSHDEPTH)?r_polygonoffset_submodel_factor.value:0))/0xffff; if (pushdepth != shaderstate.depthbias) { @@ -2068,28 +2068,28 @@ static void BE_DrawMeshChain_Internal(void) } } -void D3DBE_SelectMode(backendmode_t mode) +void D3D9BE_SelectMode(backendmode_t mode) { shaderstate.mode = mode; if (mode == BEM_STENCIL) - D3DBE_ApplyShaderBits(SBITS_MASK_BITS); + BE_ApplyShaderBits(SBITS_MASK_BITS); } -void D3DBE_SelectDLight(dlight_t *dl, vec3_t colour) +void D3D9BE_SelectDLight(dlight_t *dl, vec3_t colour) { shaderstate.curdlight = dl; VectorCopy(colour, shaderstate.curdlight_colours); } -void D3DBE_SelectEntity(entity_t *ent) +void D3D9BE_SelectEntity(entity_t *ent) { shaderstate.curentity = ent; BE_RotateForEntity(ent, ent->model); } #if 1 -static void D3DBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch) +static void D3D9BE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch) { int maxvboelements; int maxvboverts; @@ -2179,7 +2179,7 @@ static void D3DBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *s *vbochain = vbo; } -void D3DBE_GenBrushModelVBO(model_t *mod) +void D3D9BE_GenBrushModelVBO(model_t *mod) { unsigned int vcount; @@ -2200,7 +2200,7 @@ void D3DBE_GenBrushModelVBO(model_t *mod) //firstmesh got reused as the number of verticies in each batch if (vcount + batch->firstmesh > MAX_INDICIES) { - D3DBE_GenBatchVBOs(&mod->vbos, fbatch, batch); + D3D9BE_GenBatchVBOs(&mod->vbos, fbatch, batch); fbatch = batch; vcount = 0; } @@ -2209,12 +2209,12 @@ void D3DBE_GenBrushModelVBO(model_t *mod) vcount += batch->mesh[i]->numvertexes; } - D3DBE_GenBatchVBOs(&mod->vbos, fbatch, batch); + D3D9BE_GenBatchVBOs(&mod->vbos, fbatch, batch); } } #else /*Generates an optimised vbo for each of the given model's textures*/ -void D3DBE_GenBrushModelVBO(model_t *mod) +void D3D9BE_GenBrushModelVBO(model_t *mod) { #if 1 unsigned int maxvboverts; @@ -2400,7 +2400,7 @@ void D3DBE_GenBrushModelVBO(model_t *mod) } #endif /*Wipes a vbo*/ -void D3DBE_ClearVBO(vbo_t *vbo) +void D3D9BE_ClearVBO(vbo_t *vbo) { IDirect3DVertexBuffer9 *vbuff = vbo->coord.d3d.buff; IDirect3DIndexBuffer9 *ebuff = vbo->indicies.d3d.buff; @@ -2415,7 +2415,7 @@ void D3DBE_ClearVBO(vbo_t *vbo) } /*upload all lightmaps at the start to reduce lags*/ -void BE_UploadLightmaps(qboolean force) +static void BE_UploadLightmaps(qboolean force) { int i; lightmapinfo_t *lm; @@ -2443,7 +2443,7 @@ void BE_UploadLightmaps(qboolean force) int r; if (!tex) { - lm->lightmap_texture = R_AllocNewTexture("***lightmap***", lm->width, lm->height); + lm->lightmap_texture = R_AllocNewTexture("***lightmap***", lm->width, lm->height, 0); tex = lm->lightmap_texture.ptr; if (!tex) continue; @@ -2469,12 +2469,12 @@ void BE_UploadLightmaps(qboolean force) } } -void D3DBE_UploadAllLightmaps(void) +void D3D9BE_UploadAllLightmaps(void) { BE_UploadLightmaps(true); } -qboolean D3DBE_LightCullModel(vec3_t org, model_t *model) +qboolean D3D9BE_LightCullModel(vec3_t org, model_t *model) { #ifdef RTLIGHTS if ((shaderstate.mode == BEM_LIGHT || shaderstate.mode == BEM_STENCIL)) @@ -2486,7 +2486,7 @@ qboolean D3DBE_LightCullModel(vec3_t org, model_t *model) return false; } -batch_t *D3DBE_GetTempBatch(void) +batch_t *D3D9BE_GetTempBatch(void) { if (shaderstate.wbatch >= shaderstate.maxwbatches) { @@ -2602,7 +2602,7 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod) } } -void D3DBE_SubmitBatch(batch_t *batch) +void D3D9BE_SubmitBatch(batch_t *batch) { shaderstate.nummeshes = batch->meshes - batch->firstmesh; if (!shaderstate.nummeshes) @@ -2625,7 +2625,7 @@ void D3DBE_SubmitBatch(batch_t *batch) BE_DrawMeshChain_Internal(); } -void D3DBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_t *vbo, texnums_t *texnums, unsigned int beflags) +void D3D9BE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_t *vbo, texnums_t *texnums, unsigned int beflags) { shaderstate.batchvbo = vbo; shaderstate.curshader = shader; @@ -2638,7 +2638,7 @@ void D3DBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo BE_DrawMeshChain_Internal(); } -void D3DBE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums, unsigned int beflags) +void D3D9BE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums, unsigned int beflags) { shaderstate.batchvbo = vbo; shaderstate.curtime = realtime; @@ -2978,7 +2978,7 @@ static void BE_SubmitMeshesPortals(batch_t **worldlist, batch_t *dynamiclist) } } -void D3DBE_SubmitMeshes (qboolean drawworld, batch_t **blist, int first, int stop) +void D3D9BE_SubmitMeshes (qboolean drawworld, batch_t **blist, int first, int stop) { model_t *model = cl.worldmodel; int i; @@ -2997,15 +2997,15 @@ void D3DBE_SubmitMeshes (qboolean drawworld, batch_t **blist, int first, int sto } #ifdef RTLIGHTS -void D3DBE_BaseEntTextures(void) +void D3D9BE_BaseEntTextures(void) { batch_t *batches[SHADER_SORT_COUNT]; BE_GenModelBatches(batches); - D3DBE_SubmitMeshes(false, batches, SHADER_SORT_PORTAL, SHADER_SORT_DECAL); + D3D9BE_SubmitMeshes(false, batches, SHADER_SORT_PORTAL, SHADER_SORT_DECAL); BE_SelectEntity(&r_worldentity); } -void D3DBE_RenderShadowBuffer(unsigned int numverts, IDirect3DVertexBuffer9 *vbuf, unsigned int numindicies, IDirect3DIndexBuffer9 *ibuf) +void D3D9BE_RenderShadowBuffer(unsigned int numverts, IDirect3DVertexBuffer9 *vbuf, unsigned int numindicies, IDirect3DIndexBuffer9 *ibuf) { IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_VERT, vbuf, 0, sizeof(vecV_t)); IDirect3DDevice9_SetIndices(pD3DDev9, ibuf); @@ -3020,7 +3020,7 @@ void D3DBE_RenderShadowBuffer(unsigned int numverts, IDirect3DVertexBuffer9 *vbu } #endif -void D3DBE_DrawWorld (qboolean drawworld, qbyte *vis) +void D3D9BE_DrawWorld (qboolean drawworld, qbyte *vis) { batch_t *batches[SHADER_SORT_COUNT]; RSpeedLocals(); @@ -3057,25 +3057,25 @@ void D3DBE_DrawWorld (qboolean drawworld, qbyte *vis) BE_SelectMode(BEM_STANDARD); RSpeedRemark(); - D3DBE_SubmitMeshes(true, batches, SHADER_SORT_PORTAL, SHADER_SORT_DECAL); + D3D9BE_SubmitMeshes(true, batches, SHADER_SORT_PORTAL, SHADER_SORT_DECAL); RSpeedEnd(RSPEED_WORLD); #ifdef RTLIGHTS if (vis) { RSpeedRemark(); - D3DBE_SelectEntity(&r_worldentity); + D3D9BE_SelectEntity(&r_worldentity); Sh_DrawLights(vis); RSpeedEnd(RSPEED_STENCILSHADOWS); } #endif - D3DBE_SubmitMeshes(true, batches, SHADER_SORT_DECAL, SHADER_SORT_COUNT); + D3D9BE_SubmitMeshes(true, batches, SHADER_SORT_DECAL, SHADER_SORT_COUNT); } else { RSpeedRemark(); - D3DBE_SubmitMeshes(false, batches, SHADER_SORT_PORTAL, SHADER_SORT_COUNT); + D3D9BE_SubmitMeshes(false, batches, SHADER_SORT_PORTAL, SHADER_SORT_COUNT); RSpeedEnd(RSPEED_DRAWENTITIES); } diff --git a/engine/d3d/d3d_image.c b/engine/d3d/d3d_image.c index 594b4d628..58e58f871 100644 --- a/engine/d3d/d3d_image.c +++ b/engine/d3d/d3d_image.c @@ -1,6 +1,6 @@ #include "quakedef.h" #include "winquake.h" -#ifdef D3DQUAKE +#ifdef D3D9QUAKE #if !defined(HMONITOR_DECLARED) && (WINVER < 0x0500) #define HMONITOR_DECLARED DECLARE_HANDLE(HMONITOR); @@ -17,7 +17,7 @@ typedef struct d3dtexture_s } d3dtexture_t; static d3dtexture_t *d3dtextures; -void D3D_Image_Shutdown(void) +void D3D9_Image_Shutdown(void) { LPDIRECT3DTEXTURE9 tx; while(d3dtextures) @@ -57,7 +57,7 @@ static d3dtexture_t *d3d_lookup_texture(char *ident) extern cvar_t gl_picmip; extern cvar_t gl_picmip2d; -texid_t D3D9_AllocNewTexture(char *ident, int width, int height) +texid_t D3D9_AllocNewTexture(char *ident, int width, int height, unsigned int flags) { IDirect3DTexture9 *tx; texid_t ret = r_nulltex; @@ -355,7 +355,7 @@ void D3D9_Upload (texid_t tex, char *name, enum uploadfmt fmt, void *data, vo Upload_Texture_32(tex.ptr, data, width, height, flags); break; default: - OutputDebugString(va("D3D_LoadTextureFmt doesn't support fmt %i (%s)", fmt, name)); + OutputDebugString(va("D3D9_LoadTextureFmt doesn't support fmt %i (%s)", fmt, name)); break; } } @@ -416,7 +416,7 @@ texid_t D3D9_LoadTexture (char *identifier, int width, int height, enum uploadfm D3D9_LoadTexture_32(tex, data, width, height, flags); return tex->tex; default: - OutputDebugString(va("D3D_LoadTexture doesn't support fmt %i", fmt)); + OutputDebugString(va("D3D9_LoadTexture doesn't support fmt %i", fmt)); return r_nulltex; } } diff --git a/engine/d3d/d3d_shader.c b/engine/d3d/d3d_shader.c index 3095f909e..bdcdee6d5 100644 --- a/engine/d3d/d3d_shader.c +++ b/engine/d3d/d3d_shader.c @@ -1,6 +1,6 @@ #include "quakedef.h" -#ifdef D3DQUAKE +#ifdef D3D9QUAKE #include "shader.h" #include "winquake.h" #if !defined(HMONITOR_DECLARED) && (WINVER < 0x0500) @@ -18,17 +18,17 @@ typedef struct { #define D3DXHANDLE void * #define LPD3DXINCLUDE void * -#undef INTERFACE -#define INTERFACE d3dxbuffer -DECLARE_INTERFACE_(d3dxbuffer,IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - - STDMETHOD_(LPVOID,GetBufferPointer)(THIS) PURE; - STDMETHOD_(SIZE_T,GetBufferSize)(THIS) PURE; -}; +#undef INTERFACE +#define INTERFACE d3dxbuffer +DECLARE_INTERFACE_(d3dxbuffer,IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + STDMETHOD_(LPVOID,GetBufferPointer)(THIS) PURE; + STDMETHOD_(SIZE_T,GetBufferSize)(THIS) PURE; +}; typedef struct d3dxbuffer *LPD3DXBUFFER; typedef enum _D3DXREGISTER_SET @@ -99,26 +99,26 @@ typedef struct _D3DXCONSTANTTABLE_DESC } D3DXCONSTANTTABLE_DESC, *LPD3DXCONSTANTTABLE_DESC; -#undef INTERFACE -#define INTERFACE d3dxconstanttable -DECLARE_INTERFACE_(d3dxconstanttable,IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - - STDMETHOD_(LPVOID,GetBufferPointer)(THIS) PURE; - STDMETHOD_(SIZE_T,GetBufferSize)(THIS) PURE; - +#undef INTERFACE +#define INTERFACE d3dxconstanttable +DECLARE_INTERFACE_(d3dxconstanttable,IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + STDMETHOD_(LPVOID,GetBufferPointer)(THIS) PURE; + STDMETHOD_(SIZE_T,GetBufferSize)(THIS) PURE; + STDMETHOD(GetDesc)(THIS_ D3DXCONSTANTTABLE_DESC *pDesc) PURE; STDMETHOD(GetConstantDesc)(THIS_ D3DXHANDLE hConstant, D3DXCONSTANT_DESC *pConstantDesc, UINT *pCount) PURE; STDMETHOD_(D3DXHANDLE, GetConstant)(THIS_ D3DXHANDLE hConstant, UINT Index) PURE; STDMETHOD_(D3DXHANDLE, GetConstantByName)(THIS_ D3DXHANDLE hConstant, LPCSTR pName) PURE; - STDMETHOD_(D3DXHANDLE, GetConstantElement)(THIS_ D3DXHANDLE hConstant, UINT Index) PURE; - - /*more stuff not included here cos I don't need it*/ -}; + STDMETHOD_(D3DXHANDLE, GetConstantElement)(THIS_ D3DXHANDLE hConstant, UINT Index) PURE; + + /*more stuff not included here cos I don't need it*/ +}; typedef struct d3dxconstanttable *LPD3DXCONSTANTTABLE; @@ -138,7 +138,7 @@ dllhandle_t *shaderlib; -void D3DShader_Init(void) +void D3D9Shader_Init(void) { dllfunction_t funcs[] = { @@ -155,7 +155,7 @@ void D3DShader_Init(void) return; } -qboolean D3DShader_CreateProgram (program_t *prog, int permu, char **precompilerconstants, char *vert, char *frag) +qboolean D3D9Shader_CreateProgram (program_t *prog, int permu, char **precompilerconstants, char *vert, char *frag) { D3DXMACRO defines[64]; LPD3DXBUFFER code = NULL, errors = NULL; @@ -226,7 +226,7 @@ qboolean D3DShader_CreateProgram (program_t *prog, int permu, char **precompiler return success; } -static int D3DShader_FindUniform_(LPD3DXCONSTANTTABLE ct, char *name) +static int D3D9Shader_FindUniform_(LPD3DXCONSTANTTABLE ct, char *name) { if (ct) { @@ -238,19 +238,19 @@ static int D3DShader_FindUniform_(LPD3DXCONSTANTTABLE ct, char *name) return -1; } -int D3DShader_FindUniform(union programhandle_u *h, int type, char *name) +int D3D9Shader_FindUniform(union programhandle_u *h, int type, char *name) { int offs; if (!type || type == 1) { - offs = D3DShader_FindUniform_(h->hlsl.ctabv, name); + offs = D3D9Shader_FindUniform_(h->hlsl.ctabv, name); if (offs >= 0) return offs; } if (!type || type == 2) { - offs = D3DShader_FindUniform_(h->hlsl.ctabf, name); + offs = D3D9Shader_FindUniform_(h->hlsl.ctabf, name); if (offs >= 0) return offs; } diff --git a/engine/d3d/vid_d3d.c b/engine/d3d/vid_d3d.c index cfd77bf50..acf8c63f0 100644 --- a/engine/d3d/vid_d3d.c +++ b/engine/d3d/vid_d3d.c @@ -549,13 +549,14 @@ static qboolean initD3D9Device(HWND hWnd, rendererstate_t *info, unsigned int de memset(&mi, 0, sizeof(mi)); mi.cbSize = sizeof(mi); pGetMonitorInfoA(hm, &mi); - rect.left = rect.top = 0; - rect.right = d3dpp.BackBufferWidth; - rect.bottom = d3dpp.BackBufferHeight; + rect.left = mi.rcWork.left + ((mi.rcWork.right - mi.rcWork.left) - info->width) / 2; + rect.top = mi.rcWork.top + ((mi.rcWork.bottom - mi.rcWork.top) - info->height) / 2; + rect.right = rect.left+d3dpp.BackBufferWidth; + rect.bottom = rect.top+d3dpp.BackBufferHeight; AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, FALSE, 0); - MoveWindow(d3dpp.hDeviceWindow, mi.rcWork.left, mi.rcWork.top, rect.right-rect.left, rect.bottom-rect.top, false); + MoveWindow(d3dpp.hDeviceWindow, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, false); - D3DShader_Init(); + D3D9Shader_Init(); } return true; //successful } @@ -671,18 +672,19 @@ static qboolean D3D9_VID_Init(rendererstate_t *info, unsigned char *palette) else wstyle = WS_OVERLAPPEDWINDOW; - rect.left = rect.top = 0; - rect.right = info->width; - rect.bottom = info->height; + rect.left = (GetSystemMetrics(SM_CXSCREEN) - info->width) / 2; + rect.top = (GetSystemMetrics(SM_CYSCREEN) - info->height) / 2; + rect.right = rect.left+info->width; + rect.bottom = rect.top+info->height; AdjustWindowRectEx(&rect, wstyle, FALSE, 0); - mainwindow = CreateWindow(CLASSNAME, "Direct3D", wstyle, 0, 0, rect.right-rect.left, rect.bottom-rect.top, NULL, NULL, NULL, NULL); + mainwindow = CreateWindow(CLASSNAME, "Direct3D9", wstyle, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, NULL, NULL, NULL, NULL); // Try as specified. initD3D9(mainwindow, info); if (!pD3DDev9) { - Con_Printf("No suitable D3D device found\n"); + Con_Printf("No suitable D3D9 device found\n"); return false; } @@ -755,6 +757,9 @@ static void (D3D9_R_NewMap) (void) Surf_WipeStains(); Surf_BuildLightmaps(); + TP_NewMap(); + R_SetSky(cl.skyname); + #ifdef RTLIGHTS if (r_shadow_realtime_dlight.ival || r_shadow_realtime_world.ival) { @@ -927,11 +932,11 @@ static void (D3D9_SCR_UpdateScreen) (void) //vid.pixelheight = window_rect.bottom - window_rect.top; D3DVID_UpdateWindowStatus(mainwindow); - D3DBE_Reset(true); + D3D9BE_Reset(true); vid.pixelwidth = d3dpp.BackBufferWidth = window_rect.right - window_rect.left; vid.pixelheight = d3dpp.BackBufferHeight = window_rect.bottom - window_rect.top; resetD3D9(); - D3DBE_Reset(false); + D3D9BE_Reset(false); Cvar_ForceCallback(&vid_conautoscale); Cvar_ForceCallback(&vid_conwidth); @@ -943,7 +948,7 @@ static void (D3D9_SCR_UpdateScreen) (void) //the user has task switched away from us or something, don't draw anything until they switch back to us return; case D3DERR_DEVICENOTRESET: - D3DBE_Reset(true); + D3D9BE_Reset(true); resetD3D9(); if (FAILED(IDirect3DDevice9_TestCooperativeLevel(pD3DDev9))) { @@ -951,7 +956,7 @@ static void (D3D9_SCR_UpdateScreen) (void) Cmd_ExecuteString("vid_restart", RESTRICT_LOCAL); return; } - D3DBE_Reset(false); + D3D9BE_Reset(false); VID_ShiftPalette (NULL); break; @@ -1088,9 +1093,6 @@ static void (D3D9_SCR_UpdateScreen) (void) RSpeedEnd(RSPEED_TOTALREFRESH); RSpeedShow(); -#ifdef warningmsg -#pragma warningmsg("Fixme: ... to here") -#endif d3d9error(IDirect3DDevice9_EndScene(pD3DDev9)); @@ -1127,7 +1129,7 @@ static void (D3D9_R_DeInit) (void) { Surf_DeInit(); Shader_Shutdown(); - D3D_Image_Shutdown(); + D3D9_Image_Shutdown(); } @@ -1212,6 +1214,8 @@ static void (D3D9_R_RenderView) (void) } Surf_DrawWorld(); RQ_RenderBatchClear(); + + D3D9_Set2D (); } void (D3D9_R_NewMap) (void); @@ -1234,16 +1238,16 @@ void (D3D9_SCR_UpdateScreen) (void); -rendererinfo_t d3drendererinfo = +rendererinfo_t d3d9rendererinfo = { - "Direct3D9 Native", + "Direct3D9", { + "D3D9", "D3D", "Direct3d", "DirectX", - "DX" }, - QR_DIRECT3D, + QR_DIRECT3D9, D3D9_Draw_Init, D3D9_Draw_Shutdown, @@ -1293,19 +1297,19 @@ rendererinfo_t d3drendererinfo = D3D9_SCR_UpdateScreen, - D3DBE_SelectMode, - D3DBE_DrawMesh_List, - D3DBE_DrawMesh_Single, - D3DBE_SubmitBatch, - D3DBE_GetTempBatch, - D3DBE_DrawWorld, - D3DBE_Init, - D3DBE_GenBrushModelVBO, - D3DBE_ClearVBO, - D3DBE_UploadAllLightmaps, - D3DBE_SelectEntity, - D3DBE_SelectDLight, - D3DBE_LightCullModel, + D3D9BE_SelectMode, + D3D9BE_DrawMesh_List, + D3D9BE_DrawMesh_Single, + D3D9BE_SubmitBatch, + D3D9BE_GetTempBatch, + D3D9BE_DrawWorld, + D3D9BE_Init, + D3D9BE_GenBrushModelVBO, + D3D9BE_ClearVBO, + D3D9BE_UploadAllLightmaps, + D3D9BE_SelectEntity, + D3D9BE_SelectDLight, + D3D9BE_LightCullModel, "no more" }; diff --git a/engine/d3d/vid_d3d11.c b/engine/d3d/vid_d3d11.c new file mode 100644 index 000000000..2cf38da12 --- /dev/null +++ b/engine/d3d/vid_d3d11.c @@ -0,0 +1,1311 @@ +#include "quakedef.h" +#ifdef D3D11QUAKE +#include "winquake.h" +#include "gl_draw.h" +#include "glquake.h" +#include "shader.h" +#include "renderque.h" + +#define COBJMACROS +#include + +//#include + +//#pragma comment(lib, "../libs/dxsdk9/lib/d3d9.lib") + + +/*Fixup outdated windows headers*/ +#ifndef WM_XBUTTONDOWN + #define WM_XBUTTONDOWN 0x020B + #define WM_XBUTTONUP 0x020C +#endif +#ifndef MK_XBUTTON1 + #define MK_XBUTTON1 0x0020 +#endif +#ifndef MK_XBUTTON2 + #define MK_XBUTTON2 0x0040 +#endif +// copied from DarkPlaces in an attempt to grab more buttons +#ifndef MK_XBUTTON3 + #define MK_XBUTTON3 0x0080 +#endif +#ifndef MK_XBUTTON4 + #define MK_XBUTTON4 0x0100 +#endif +#ifndef MK_XBUTTON5 + #define MK_XBUTTON5 0x0200 +#endif +#ifndef MK_XBUTTON6 + #define MK_XBUTTON6 0x0400 +#endif +#ifndef MK_XBUTTON7 + #define MK_XBUTTON7 0x0800 +#endif + +#ifndef WM_INPUT + #define WM_INPUT 255 +#endif + +#define DEFINE_QGUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + const GUID DECLSPEC_SELECTANY name \ + = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } + +DEFINE_QGUID(qIID_ID3D11Texture2D,0x6f15aaf2,0xd208,0x4e89,0x9a,0xb4,0x48,0x95,0x35,0xd3,0x4f,0x9c); + +//static void D3D11_GetBufferSize(int *width, int *height); //not defined +static void resetD3D11(void); +//static LPDIRECT3D11 pD3D; +ID3D11Device *pD3DDev11; +ID3D11DeviceContext *d3ddevctx; +IDXGISwapChain *d3dswapchain; + +ID3D11RenderTargetView *fb_backbuffer; +ID3D11DepthStencilView *fb_backdepthstencil; + +void *d3d11mod; +float d3d_trueprojection[16]; + +qboolean vid_initializing; + +extern qboolean scr_initialized; // ready to draw +extern qboolean scr_drawloading; +extern qboolean scr_con_forcedraw; +static qboolean d3d_resized; + +cvar_t vid_hardwaregamma; + + +//sound/error code needs this +HWND mainwindow; + +//input code needs these +int window_center_x, window_center_y; +RECT window_rect; +int window_x, window_y; + +static void released3dbackbuffer(void); +static qboolean resetd3dbackbuffer(int width, int height); + +void BuildGammaTable (float g, float c); +static void D3D11_VID_GenPaletteTables (unsigned char *palette) +{ + extern unsigned short ramps[3][256]; + qbyte *pal; + unsigned r,g,b; + unsigned v; + unsigned short i; + unsigned *table; + extern qbyte gammatable[256]; + + if (palette) + { + extern cvar_t v_contrast; + BuildGammaTable(v_gamma.value, v_contrast.value); + + // + // 8 8 8 encoding + // + if (1)//vid_hardwaregamma.value) + { + // don't built in the gamma table + + pal = palette; + table = d_8to24rgbtable; + for (i=0 ; i<256 ; i++) + { + r = pal[0]; + g = pal[1]; + b = pal[2]; + pal += 3; + + // v = (255<<24) + (r<<16) + (g<<8) + (b<<0); + // v = (255<<0) + (r<<8) + (g<<16) + (b<<24); + v = (255<<24) + (r<<0) + (g<<8) + (b<<16); + *table++ = v; + } + d_8to24rgbtable[255] &= 0xffffff; // 255 is transparent + } + else + { + //computer has no hardware gamma (poor suckers) increase table accordingly + + pal = palette; + table = d_8to24rgbtable; + for (i=0 ; i<256 ; i++) + { + r = gammatable[pal[0]]; + g = gammatable[pal[1]]; + b = gammatable[pal[2]]; + pal += 3; + + // v = (255<<24) + (r<<16) + (g<<8) + (b<<0); + // v = (255<<0) + (r<<8) + (g<<16) + (b<<24); + v = (255<<24) + (r<<0) + (g<<8) + (b<<16); + *table++ = v; + } + d_8to24rgbtable[255] &= 0xffffff; // 255 is transparent + } + + if (LittleLong(1) != 1) + { + for (i=0 ; i<256 ; i++) + d_8to24rgbtable[i] = LittleLong(d_8to24rgbtable[i]); + } + } + +// if (pD3DDev11) + // d3dswapchain->Set + //IDirect3DDevice11_SetGammaRamp(); +// IDirect3DDevice9_SetGammaRamp(pD3DDev9, 0, D3DSGR_NO_CALIBRATION, (D3DGAMMARAMP *)ramps); +} + +typedef enum {MS_WINDOWED, MS_FULLSCREEN, MS_FULLDIB, MS_UNINIT} modestate_t; +static modestate_t modestate; + + +static void D3DVID_UpdateWindowStatus (HWND hWnd) +{ + POINT p; + RECT nr; + int window_width, window_height; + GetClientRect(hWnd, &nr); + + //if its bad then we're probably minimised + if (nr.right <= nr.left) + return; + if (nr.bottom <= nr.top) + return; + + p.x = 0; + p.y = 0; + ClientToScreen(hWnd, &p); + window_x = p.x; + window_y = p.y; + window_width = nr.right - nr.left; + window_height = nr.bottom - nr.top; +// vid.pixelwidth = window_width; +// vid.pixelheight = window_height; + + window_rect.left = window_x; + window_rect.top = window_y; + window_rect.right = window_x + window_width; + window_rect.bottom = window_y + window_height; + window_center_x = (window_rect.left + window_rect.right) / 2; + window_center_y = (window_rect.top + window_rect.bottom) / 2; + + IN_UpdateClipCursor (); +} + +static qboolean D3D11AppActivate(BOOL fActive, BOOL minimize) +/**************************************************************************** +* +* Function: AppActivate +* Parameters: fActive - True if app is activating +* +* Description: If the application is activating, then swap the system +* into SYSPAL_NOSTATIC mode so that our palettes will display +* correctly. +* +****************************************************************************/ +{ + static BOOL sound_active; + + if (ActiveApp == fActive && Minimized == minimize) + return false; //so windows doesn't crash us over and over again. + + ActiveApp = fActive; + Minimized = minimize; + +// enable/disable sound on focus gain/loss + if (!ActiveApp && sound_active) + { + S_BlockSound (); + sound_active = false; + } + else if (ActiveApp && !sound_active) + { + S_UnblockSound (); + sound_active = true; + } + + IN_UpdateGrabs(modestate != MS_WINDOWED, ActiveApp); + + if (fActive) + { + Cvar_ForceCallback(&v_gamma); + } + if (!fActive) + { + Cvar_ForceCallback(&v_gamma); //wham bam thanks. + } + + return true; +} + + + + + +static LRESULT WINAPI D3D11_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + LONG lRet = 1; + int fActive, fMinimized, temp; + extern unsigned int uiWheelMessage; + + if ( uMsg == uiWheelMessage ) + uMsg = WM_MOUSEWHEEL; + + switch (uMsg) + { +/* case WM_KILLFOCUS: + if (modestate == MS_FULLDIB) + ShowWindow(mainwindow, SW_SHOWMINNOACTIVE); + break; +*/ +// case WM_CREATE: +// break; + + case WM_MOVE: + D3DVID_UpdateWindowStatus (hWnd); + lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); + break; + + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + if (!vid_initializing) + IN_TranslateKeyEvent (wParam, lParam, true, 0); + break; + + case WM_KEYUP: + case WM_SYSKEYUP: + if (!vid_initializing) + IN_TranslateKeyEvent (wParam, lParam, false, 0); + break; + + case WM_SYSCHAR: + // keep Alt-Space from happening + break; + + // this is complicated because Win32 seems to pack multiple mouse events into + // one update sometimes, so we always check all states and look for events + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_MOUSEMOVE: + case WM_XBUTTONDOWN: + case WM_XBUTTONUP: + temp = 0; + + if (wParam & MK_LBUTTON) + temp |= 1; + + if (wParam & MK_RBUTTON) + temp |= 2; + + if (wParam & MK_MBUTTON) + temp |= 4; + + if (wParam & MK_XBUTTON1) + temp |= 8; + + if (wParam & MK_XBUTTON2) + temp |= 16; + + if (wParam & MK_XBUTTON3) + temp |= 32; + + if (wParam & MK_XBUTTON4) + temp |= 64; + + if (wParam & MK_XBUTTON5) + temp |= 128; + + if (wParam & MK_XBUTTON6) + temp |= 256; + + if (wParam & MK_XBUTTON7) + temp |= 512; + + if (!vid_initializing) + IN_MouseEvent (temp); + + break; + + // JACK: This is the mouse wheel with the Intellimouse + // Its delta is either positive or neg, and we generate the proper + // Event. + case WM_MOUSEWHEEL: + if (!vid_initializing) + { + if ((short) HIWORD(wParam) > 0) + { + Key_Event(0, K_MWHEELUP, 0, true); + Key_Event(0, K_MWHEELUP, 0, false); + } + else + { + Key_Event(0, K_MWHEELDOWN, 0, true); + Key_Event(0, K_MWHEELDOWN, 0, false); + } + } + break; + + case WM_INPUT: + // raw input handling + if (!vid_initializing) + IN_RawInput_Read((HANDLE)lParam); + break; + + case WM_GETMINMAXINFO: + { + RECT windowrect; + RECT clientrect; + MINMAXINFO *mmi = (MINMAXINFO *) lParam; + + GetWindowRect (hWnd, &windowrect); + GetClientRect (hWnd, &clientrect); + + mmi->ptMinTrackSize.x = 320 + ((windowrect.right - windowrect.left) - (clientrect.right - clientrect.left)); + mmi->ptMinTrackSize.y = 200 + ((windowrect.bottom - windowrect.top) - (clientrect.bottom - clientrect.top)); + } + return 0; + case WM_SIZE: + d3d_resized = true; + + D3DVID_UpdateWindowStatus(mainwindow); + + released3dbackbuffer(); + IDXGISwapChain_ResizeBuffers(d3dswapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH); + + D3D11BE_Reset(true); + vid.pixelwidth = window_rect.right - window_rect.left; + vid.pixelheight = window_rect.bottom - window_rect.top; + resetd3dbackbuffer(vid.pixelwidth, vid.pixelheight); + resetD3D11(); + D3D11BE_Reset(false); + lRet = 0; + break; + + case WM_CLOSE: + if (!vid_initializing) + if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit", + MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) + { + Cbuf_AddText("\nquit\n", RESTRICT_LOCAL); + } + + break; + + case WM_ACTIVATE: + fActive = LOWORD(wParam); + fMinimized = (BOOL) HIWORD(wParam); + if (!D3D11AppActivate(!(fActive == WA_INACTIVE), fMinimized)) + break;//so, urm, tell me microsoft, what changed? + + ShowWindow(mainwindow, SW_SHOWNORMAL); + + // fix the leftover Alt from any Alt-Tab or the like that switched us away +// ClearAllStates (); + + lRet = 0; + break; + + case WM_DESTROY: + { +// if (dibwindow) +// DestroyWindow (dibwindow); + } + break; + + case MM_MCINOTIFY: + lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); + break; + + default: + /* pass all unhandled messages to DefWindowProc */ + lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); + break; + } + + /* return 1 if handled message, 0 if not */ + return lRet; +} +static void resetD3D11(void) +{ +#if 0 + HRESULT res; + res = IDirect3DDevice9_Reset(pD3DDev9, &d3dpp); + if (FAILED(res)) + { + Con_Printf("IDirect3DDevice9_Reset failed (%u)\n", res&0xffff); + return; + } + + + /*clear the screen to black as soon as we start up, so there's no lingering framebuffer state*/ + IDirect3DDevice9_BeginScene(pD3DDev9); + IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); + IDirect3DDevice9_EndScene(pD3DDev9); + IDirect3DDevice9_Present(pD3DDev9, NULL, NULL, NULL, NULL); + + + + + + + + //IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRENDERSTATE_DITHERENABLE, FALSE); + //IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRENDERSTATE_SPECULARENABLE, FALSE); + //IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE); + IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_LIGHTING, FALSE); +#endif +} + +#if (WINVER < 0x500) && !defined(__GNUC__) +typedef struct tagMONITORINFO +{ + DWORD cbSize; + RECT rcMonitor; + RECT rcWork; + DWORD dwFlags; +} MONITORINFO, *LPMONITORINFO; +#endif + +static void released3dbackbuffer(void) +{ + if (d3ddevctx) + ID3D11DeviceContext_OMSetRenderTargets(d3ddevctx, 0, NULL, NULL); + if (fb_backbuffer) + ID3D11RenderTargetView_Release(fb_backbuffer); + fb_backbuffer = NULL; + if (fb_backdepthstencil) + ID3D11DepthStencilView_Release(fb_backdepthstencil); + fb_backdepthstencil = NULL; +} + +static qboolean resetd3dbackbuffer(int width, int height) +{ + D3D11_TEXTURE2D_DESC t2ddesc; + D3D11_DEPTH_STENCIL_VIEW_DESC dsvd; + ID3D11Texture2D *backbuftex, *depthtex; + + released3dbackbuffer(); + + //get a proper handle to the backbuffer (silly hurdles) + if (FAILED(IDXGISwapChain_GetBuffer(d3dswapchain, 0, &qIID_ID3D11Texture2D, (LPVOID*)&backbuftex))) + return false; + if (FAILED(ID3D11Device_CreateRenderTargetView(pD3DDev11, (ID3D11Resource*)backbuftex, NULL, &fb_backbuffer))) + return false; + ID3D11Texture2D_Release(backbuftex); + + //set up a depth buffer. + memset(&t2ddesc, 0, sizeof(t2ddesc)); + t2ddesc.Width = width; + t2ddesc.Height = height; + t2ddesc.MipLevels = 1; + t2ddesc.ArraySize = 1; + t2ddesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; + t2ddesc.SampleDesc.Count = 1; + t2ddesc.SampleDesc.Quality = 0; + t2ddesc.Usage = D3D11_USAGE_DEFAULT; + t2ddesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + t2ddesc.CPUAccessFlags = 0; + t2ddesc.MiscFlags = 0; + if(FAILED(ID3D11Device_CreateTexture2D(pD3DDev11, &t2ddesc, NULL, &depthtex))) + return false; + dsvd.Format = t2ddesc.Format; + dsvd.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + dsvd.Texture2D.MipSlice = 0; + if(FAILED(ID3D11Device_CreateDepthStencilView(pD3DDev11, (ID3D11Resource*)depthtex, NULL/*&dsvd*/, &fb_backdepthstencil))) + return false; + ID3D11Texture2D_Release(depthtex); + + //now tell d3d which render targets to use. + ID3D11DeviceContext_OMSetRenderTargets(d3ddevctx, 1, &fb_backbuffer, fb_backdepthstencil); + + return true; +} + +static qboolean initD3D11Device(HWND hWnd, rendererstate_t *info, PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN func) +{ + int flags = D3D11_CREATE_DEVICE_SINGLETHREADED; + DXGI_SWAP_CHAIN_DESC scd; + D3D_FEATURE_LEVEL flevel, flevels[] = + { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + D3D_FEATURE_LEVEL_9_3, + D3D_FEATURE_LEVEL_9_2, + D3D_FEATURE_LEVEL_9_1 + }; + memset(&scd, 0, sizeof(scd)); + + scd.BufferDesc.Width = info->width; + scd.BufferDesc.Height = info->height; + scd.BufferDesc.RefreshRate.Numerator = 0; + scd.BufferDesc.RefreshRate.Denominator = 0; + scd.BufferCount = 1; //back buffer count + scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; //32bit colour + scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + scd.OutputWindow = hWnd; + scd.SampleDesc.Count = 1+info->multisample; + scd.Windowed = TRUE; + scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;// | DXGI_SWAP_CHAIN_FLAG_NONPREROTATED; + +#ifdef _DEBUG +// flags |= D3D11_CREATE_DEVICE_DEBUG; +#endif + + if (FAILED(func(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, + flevels, sizeof(flevels)/sizeof(flevels[0]), + D3D11_SDK_VERSION, + &scd, + &d3dswapchain, + &pD3DDev11, + &flevel, + &d3ddevctx))) + return false; + + if (!pD3DDev11) + return false; + + Con_Printf("D3D11 Feature level: %i_%i\n", flevel>>12, (flevel>>8) & 0xf); + + if (!resetd3dbackbuffer(info->width, info->height)) + return false; + + if (info->fullscreen) + { + } + + vid.numpages = scd.BufferCount; + D3D11Shader_Init(); + return true; +} + +static void initD3D11(HWND hWnd, rendererstate_t *info) +{ + static dllhandle_t *d3d11dll; + static PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN fnc; + dllfunction_t funcs[] = + { + {(void**)&fnc, "D3D11CreateDeviceAndSwapChain"}, + {NULL} + }; + + if (!d3d11mod) + d3d11mod = Sys_LoadLibrary("d3d11", funcs); + + if (!d3d11mod) + return; + + initD3D11Device(hWnd, info, fnc); +} + +static qboolean D3D11_VID_Init(rendererstate_t *info, unsigned char *palette) +{ + DWORD width = info->width; + DWORD height = info->height; + //DWORD bpp = info->bpp; + //DWORD zbpp = 16; + //DWORD flags = 0; + DWORD wstyle; + RECT rect; + MSG msg; + + extern cvar_t vid_conwidth; + //extern cvar_t vid_conheight; + + //DDGAMMARAMP gammaramp; + //int i; + + char *CLASSNAME = "FTED3D11QUAKE"; + WNDCLASS wc = { + 0, + &D3D11_WindowProc, + 0, + 0, + NULL, + NULL, + NULL, + NULL, + NULL, + CLASSNAME + }; + + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.hCursor = LoadCursor (NULL,IDC_ARROW); + wc.hInstance = global_hInstance; + + vid_initializing = true; + + RegisterClass(&wc); + + if (info->fullscreen) + wstyle = 0; + else + wstyle = WS_OVERLAPPEDWINDOW; + + rect.left = (GetSystemMetrics(SM_CXSCREEN) - info->width) / 2; + rect.top = (GetSystemMetrics(SM_CYSCREEN) - info->height) / 2; + rect.right = rect.left+info->width; + rect.bottom = rect.top+info->height; + AdjustWindowRectEx(&rect, wstyle, FALSE, 0); + mainwindow = CreateWindow(CLASSNAME, "Direct3D11", wstyle, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, NULL, NULL, NULL, NULL); + + // Try as specified. + + initD3D11(mainwindow, info); + if (!pD3DDev11) + { + Con_Printf("No suitable D3D11 device found\n"); + return false; + } + + if (info->fullscreen) + IDXGISwapChain_SetFullscreenState(d3dswapchain, true, NULL); + + + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + CL_UpdateWindowTitle(); + + ShowWindow(mainwindow, SW_SHOWNORMAL); + +// IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); +// IDirect3DDevice9_BeginScene(pD3DDev9); +// IDirect3DDevice9_EndScene(pD3DDev9); +// IDirect3DDevice9_Present(pD3DDev9, NULL, NULL, NULL, NULL); + + + +// pD3DX->lpVtbl->GetBufferSize((void*)pD3DX, &width, &height); + vid.pixelwidth = width; + vid.pixelheight = height; + vid.recalc_refdef = true; + + vid.width = width; + vid.height = height; + + vid_initializing = false; + +// IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_LIGHTING, FALSE); + + GetWindowRect(mainwindow, &window_rect); + + + D3D11_VID_GenPaletteTables(palette); + + { + extern qboolean mouseactive; + mouseactive = false; + } + + { + void GLV_Gamma_Callback(struct cvar_s *var, char *oldvalue); + Cvar_Hook(&v_gamma, GLV_Gamma_Callback); + Cvar_Hook(&v_contrast, GLV_Gamma_Callback); + + Cvar_ForceCallback(&v_gamma); + } + + return true; +} + +/*a new model has been loaded*/ +static void (D3D11_R_NewMap) (void) +{ + r_worldentity.model = cl.worldmodel; + +#ifdef MAP_PROC + if (cl.worldmodel && cl.worldmodel->fromgame == fg_doom3) + D3_GenerateAreas(cl.worldmodel); +#endif + + /*wipe any lingering particles*/ + P_ClearParticles(); + CL_RegisterParticles(); + + R_AnimateLight(); + Surf_DeInit(); + Surf_WipeStains(); + Surf_BuildLightmaps(); + + TP_NewMap(); + R_SetSky(cl.skyname); + +#ifdef RTLIGHTS + if (r_shadow_realtime_dlight.ival || r_shadow_realtime_world.ival) + { + R_LoadRTLights(); + if (rtlights_first == rtlights_max) + R_ImportRTLights(cl.worldmodel->entities); + } + Sh_PreGenerateLights(); +#endif +} + +extern mleaf_t *r_viewleaf, *r_oldviewleaf; +extern mleaf_t *r_viewleaf2, *r_oldviewleaf2; +static void (D3D11_R_PreNewMap) (void) +{ + r_viewleaf = NULL; + r_oldviewleaf = NULL; + r_viewleaf2 = NULL; + r_oldviewleaf2 = NULL; +} + +static void (D3D11_VID_DeInit) (void) +{ + D3D11BE_Shutdown(); + + /*we cannot shut down cleanly while in fullscreen, supposedly*/ + if(d3dswapchain) + IDXGISwapChain_SetFullscreenState(d3dswapchain, false, NULL); + + released3dbackbuffer(); + if(d3dswapchain) + IDXGISwapChain_Release(d3dswapchain); + d3dswapchain = NULL; + if (pD3DDev11) + pD3DDev11->lpVtbl->Release(pD3DDev11); + pD3DDev11 = NULL; + if (d3ddevctx) + d3ddevctx->lpVtbl->Release(d3ddevctx); + d3ddevctx = NULL; + + if (mainwindow) + { + DestroyWindow(mainwindow); + mainwindow = NULL; + } + + Cvar_Unhook(&v_gamma); + Cvar_Unhook(&v_contrast); +} + +static void (D3D11_VID_SetPalette) (unsigned char *palette) +{ + D3D11_VID_GenPaletteTables(palette); +} +static void (D3D11_VID_ShiftPalette) (unsigned char *palette) +{ + D3D11_VID_GenPaletteTables(palette); +} +static char *(D3D11_VID_GetRGBInfo) (int prepad, int *truevidwidth, int *truevidheight) +{ + return NULL; +#if 0 + IDirect3DSurface9 *backbuf, *surf; + D3DLOCKED_RECT rect; + D3DSURFACE_DESC desc; + int i, j, c; + qbyte *ret = NULL; + qbyte *p; + + /*DON'T read the front buffer. + this function can be used by the quakeworld remote screenshot 'snap' feature, + so DO NOT read the frontbuffer because it can show other information than just quake to third parties*/ + + if (!FAILED(IDirect3DDevice9_GetRenderTarget(pD3DDev9, 0, &backbuf))) + { + if (!FAILED(IDirect3DSurface9_GetDesc(backbuf, &desc))) + if (desc.Format == D3DFMT_X8R8G8B8 || desc.Format == D3DFMT_A8R8G8B8) + if (!FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(pD3DDev9, + desc.Width, desc.Height, desc.Format, + D3DPOOL_SYSTEMMEM, &surf, NULL)) + ) + { + + if (!FAILED(IDirect3DDevice9_GetRenderTargetData(pD3DDev9, backbuf, surf))) + if (!FAILED(IDirect3DSurface9_LockRect(surf, &rect, NULL, D3DLOCK_NO_DIRTY_UPDATE|D3DLOCK_READONLY|D3DLOCK_NOSYSLOCK))) + { + ret = BZ_Malloc(prepad + desc.Width*desc.Height*3); + if (ret) + { + // read surface rect and convert 32 bgra to 24 rgb and flip + c = prepad+desc.Width*desc.Height*3; + p = (qbyte *)rect.pBits; + + for (i=c-(3*desc.Width); i>=prepad; i-=(3*desc.Width)) + { + for (j=0; jlpVtbl->RSSetViewports(d3ddevctx, 1, &vport); + D3D11BE_SetupViewCBuffer(); +} + +/* +static int d3d11error(int i) +{ + if (FAILED(i))// != D3D_OK) + Con_Printf("D3D error: %i\n", i); + return i; +} +*/ +static void (D3D11_SCR_UpdateScreen) (void) +{ + extern cvar_t _vid_wait_override; + //extern int keydown[]; + //extern cvar_t vid_conheight; + int uimenu; +#ifdef TEXTEDITOR + //extern qboolean editormodal; +#endif + qboolean nohud, noworld; + RSpeedMark(); + + if (r_clear.ival) + { + float colours[4] = {1, 0, 0, 0}; + ID3D11DeviceContext_ClearRenderTargetView(d3ddevctx, fb_backbuffer, colours); + } + +#if 1 + if (d3d_resized) + { + extern cvar_t vid_conautoscale, vid_conwidth; + d3d_resized = false; + + // force width/height to be updated + //vid.pixelwidth = window_rect.right - window_rect.left; + //vid.pixelheight = window_rect.bottom - window_rect.top; +/* D3DVID_UpdateWindowStatus(mainwindow); + + released3dbackbuffer(); + IDXGISwapChain_ResizeBuffers(d3dswapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0); + + D3D11BE_Reset(true); + vid.pixelwidth = window_rect.right - window_rect.left; + vid.pixelheight = window_rect.bottom - window_rect.top; + resetd3dbackbuffer(vid.pixelwidth, vid.pixelheight); + resetD3D11(); + D3D11BE_Reset(false); +*/ + Cvar_ForceCallback(&vid_conautoscale); + Cvar_ForceCallback(&vid_conwidth); + } +#endif + + if (scr_disabled_for_loading) + { + extern float scr_disabled_time; + if (Sys_DoubleTime() - scr_disabled_time > 60 || key_dest != key_game) + { + scr_disabled_for_loading = false; + } + else + { +// IDirect3DDevice9_BeginScene(pD3DDev9); + scr_drawloading = true; + SCR_DrawLoading (); + scr_drawloading = false; +// IDirect3DDevice9_EndScene(pD3DDev9); + IDXGISwapChain_Present(d3dswapchain, _vid_wait_override.ival, 0); + RSpeedEnd(RSPEED_TOTALREFRESH); + return; + } + } + + if (!scr_initialized || !con_initialized) + { + RSpeedEnd(RSPEED_TOTALREFRESH); + return; // not initialized yet + } + + Shader_DoReload(); + +#ifdef VM_UI + uimenu = UI_MenuState(); +#else + uimenu = 0; +#endif + +// d3d11error(IDirect3DDevice9_BeginScene(pD3DDev9)); +/* +#ifdef TEXTEDITOR + if (editormodal) + { + Editor_Draw(); + V_UpdatePalette (false); +#if defined(_WIN32) && defined(GLQUAKE) + Media_RecordFrame(); +#endif + R2D_BrightenScreen(); + + if (key_dest == key_console) + Con_DrawConsole(vid_conheight.value/2, false); + GL_EndRendering (); + GL_DoSwap(); + RSpeedEnd(RSPEED_TOTALREFRESH); + return; + } +#endif +*/ + if (Media_ShowFilm()) + { + M_Draw(0); +// V_UpdatePalette (false); +#if defined(_WIN32) + Media_RecordFrame(); +#endif +// R2D_BrightenScreen(); +// IDirect3DDevice9_EndScene(pD3DDev9); + IDXGISwapChain_Present(d3dswapchain, _vid_wait_override.ival, 0); + RSpeedEnd(RSPEED_TOTALREFRESH); + return; + } + + // + // determine size of refresh window + // + if (vid.recalc_refdef) + SCR_CalcRefdef (); + +// +// do 3D refresh drawing, and then update the screen +// + SCR_SetUpToDrawConsole (); + + noworld = false; + nohud = false; + +#ifdef VM_CG + if (CG_Refresh()) + nohud = true; + else +#endif +#ifdef CSQC_DAT + if (cls.state == ca_active && CSQC_DrawView()) + nohud = true; + else +#endif + if (uimenu != 1) + { + if (r_worldentity.model && cls.state == ca_active) + V_RenderView (); + else + { + noworld = true; + } + } + + D3D11_Set2D(); + + if (!noworld) + { + R2D_PolyBlend (); + R2D_BrightenScreen(); + } + + scr_con_forcedraw = false; + if (noworld) + { + if ((key_dest == key_console || key_dest == key_game) && SCR_GetLoadingStage() == LS_NONE) + scr_con_current = vid.height; + + if (scr_con_current != vid.height) + R2D_ConsoleBackground(0, vid.height, true); + else + scr_con_forcedraw = true; + + nohud = true; + } + else if (!nohud) + SCR_TileClear (); + + SCR_DrawTwoDimensional(uimenu, nohud); + + V_UpdatePalette (false); +#if defined(_WIN32) && defined(GLQUAKE) + Media_RecordFrame(); +#endif + + RSpeedEnd(RSPEED_TOTALREFRESH); + RSpeedShow(); + + +// d3d11error(IDirect3DDevice9_EndScene(pD3DDev9)); + + IDXGISwapChain_Present(d3dswapchain, _vid_wait_override.ival, 0); + + window_center_x = (window_rect.left + window_rect.right)/2; + window_center_y = (window_rect.top + window_rect.bottom)/2; + + + IN_UpdateGrabs(modestate != MS_WINDOWED, ActiveApp); + + VID_ShiftPalette (NULL); +} + + + + + + + +static void (D3D11_Draw_Init) (void) +{ + R2D_Init(); +} +static void (D3D11_Draw_Shutdown) (void) +{ + R2D_Shutdown(); +} + +static void (D3D11_R_Init) (void) +{ +} +static void (D3D11_R_DeInit) (void) +{ + Surf_DeInit(); + Shader_Shutdown(); + D3D11_Image_Shutdown(); +} + + + +static void D3D11_SetupViewPort(void) +{ + extern cvar_t gl_mindist; + float screenaspect; + int x, x2, y2, y, w, h; + + float fov_x, fov_y; + +// D3DVIEWPORT9 vport; + + AngleVectors (r_refdef.viewangles, vpn, vright, vup); + VectorCopy (r_refdef.vieworg, r_origin); + + // + // set up viewpoint + // + x = r_refdef.vrect.x * vid.pixelwidth/(int)vid.width; + x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * vid.pixelwidth/(int)vid.width; + y = (r_refdef.vrect.y) * vid.pixelheight/(int)vid.height; + y2 = ((int)(r_refdef.vrect.y + r_refdef.vrect.height)) * vid.pixelheight/(int)vid.height; + + // fudge around because of frac screen scale + if (x > 0) + x--; + if (x2 < vid.pixelwidth) + x2++; + if (y < 0) + y--; + if (y2 < vid.pixelheight) + y2++; + + w = x2 - x; + h = y2 - y; + +// vport.X = x; +// vport.Y = y; +// vport.Width = w; +// vport.Height = h; +// vport.MinZ = 0; +// vport.MaxZ = 1; +// IDirect3DDevice9_SetViewport(pD3DDev9, &vport); + + fov_x = r_refdef.fov_x;//+sin(cl.time)*5; + fov_y = r_refdef.fov_y;//-sin(cl.time+1)*5; + + if (r_waterwarp.value<0 && r_viewcontents & FTECONTENTS_FLUID) + { + 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); + } + + screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height; + + /*view matrix*/ + Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_refdef.vieworg); +// d3d11error(IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_VIEW, (D3DMATRIX*)r_refdef.m_view)); + + /*d3d projection matricies scale depth to 0 to 1*/ + Matrix4x4_CM_Projection_Inf(d3d_trueprojection, fov_x, fov_y, gl_mindist.value/2); +// d3d11error(IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_PROJECTION, (D3DMATRIX*)d3d_trueprojection)); + /*ogl projection matricies scale depth to -1 to 1, and I would rather my code used consistant culling*/ + Matrix4x4_CM_Projection_Inf(r_refdef.m_projection, fov_x, fov_y, gl_mindist.value); +} + +static void (D3D11_R_RenderView) (void) +{ + D3D11_SetupViewPort(); + //unlike gl, we clear colour beforehand, because that seems more sane. + //always clear depth + ID3D11DeviceContext_ClearDepthStencilView(d3ddevctx, fb_backdepthstencil, D3D11_CLEAR_DEPTH, 1, 0); //is it faster to clear the stencil too? + + R_SetFrustum (r_refdef.m_projection, r_refdef.m_view); + RQ_BeginFrame(); + if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL)) + { + if (cl.worldmodel) + P_DrawParticles (); + } + Surf_DrawWorld(); + RQ_RenderBatchClear(); + + D3D11_Set2D (); +} + +void (D3D11_R_NewMap) (void); +void (D3D11_R_PreNewMap) (void); + +void (D3D11_R_PushDlights) (void); +void (D3D11_R_AddStain) (vec3_t org, float red, float green, float blue, float radius); +void (D3D11_R_LessenStains) (void); + +qboolean (D3D11_VID_Init) (rendererstate_t *info, unsigned char *palette); +void (D3D11_VID_DeInit) (void); +void (D3D11_VID_SetPalette) (unsigned char *palette); +void (D3D11_VID_ShiftPalette) (unsigned char *palette); +char *(D3D11_VID_GetRGBInfo) (int prepad, int *truevidwidth, int *truevidheight); +void (D3D11_VID_SetWindowCaption) (char *msg); + +void (D3D11_SCR_UpdateScreen) (void); + + + + + + + +rendererinfo_t d3d11rendererinfo = +{ + "Direct3D11", + { + "D3D11", + "Direct3d11", + "DirectX11", + "DX11" + }, + QR_DIRECT3D11, + + D3D11_Draw_Init, + D3D11_Draw_Shutdown, + + D3D11_LoadTexture, + D3D11_LoadTexture8Pal24, + D3D11_LoadTexture8Pal32, + D3D11_LoadCompressed, + D3D11_FindTexture, + D3D11_AllocNewTexture, + D3D11_Upload, + D3D11_DestroyTexture, + + D3D11_R_Init, + D3D11_R_DeInit, + D3D11_R_RenderView, + + D3D11_R_NewMap, + D3D11_R_PreNewMap, + + Surf_AddStain, + Surf_LessenStains, + + RMod_Init, + RMod_Shutdown, + RMod_ClearAll, + RMod_ForName, + RMod_FindName, + RMod_Extradata, + RMod_TouchModel, + + RMod_NowLoadExternal, + RMod_Think, + Mod_GetTag, + Mod_TagNumForName, + Mod_SkinNumForName, + Mod_FrameNumForName, + Mod_FrameDuration, + + + D3D11_VID_Init, + D3D11_VID_DeInit, + D3D11_VID_SetPalette, + D3D11_VID_ShiftPalette, + D3D11_VID_GetRGBInfo, + D3D11_VID_SetWindowCaption, + + D3D11_SCR_UpdateScreen, + + D3D11BE_SelectMode, + D3D11BE_DrawMesh_List, + D3D11BE_DrawMesh_Single, + D3D11BE_SubmitBatch, + D3D11BE_GetTempBatch, + D3D11BE_DrawWorld, + D3D11BE_Init, + D3D11BE_GenBrushModelVBO, + D3D11BE_ClearVBO, + D3D11BE_UploadAllLightmaps, + D3D11BE_SelectEntity, + D3D11BE_SelectDLight, + D3D11BE_LightCullModel, + + "no more" +}; +#endif diff --git a/engine/dotnet2005/ftequake.vcproj b/engine/dotnet2005/ftequake.vcproj index 10308c913..fe20858a0 100644 --- a/engine/dotnet2005/ftequake.vcproj +++ b/engine/dotnet2005/ftequake.vcproj @@ -4535,210 +4535,6 @@ /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -33790,6 +33586,210 @@ /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/engine/dotnet2010/ftequake.sln b/engine/dotnet2010/ftequake.sln index d3f93af1d..66aa9e919 100644 --- a/engine/dotnet2010/ftequake.sln +++ b/engine/dotnet2010/ftequake.sln @@ -1,8 +1,8 @@ Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 +# Visual C++ Express 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftequake", "ftequake.vcxproj", "{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftequake_SDL", "ftequake_SDL.vcxproj", "{F384725A-62D4-4063-9941-6D8D2D6C2A47}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftequake", "ftequake_SDL.vcxproj", "{F384725A-62D4-4063-9941-6D8D2D6C2A47}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "npfte", "npfte.vcxproj", "{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}" EndProject diff --git a/engine/dotnet2010/ftequake.vcxproj b/engine/dotnet2010/ftequake.vcxproj index a59160e66..f2cf2f46a 100644 --- a/engine/dotnet2010/ftequake.vcxproj +++ b/engine/dotnet2010/ftequake.vcxproj @@ -392,6 +392,9 @@ fteqwsv + fteglqw_dbg + fted3dqw + fteqw_dbg @@ -503,7 +506,7 @@ Disabled ../libs/speex;..\client;../libs/freetype2/include;../common;../server;../gl;../sw;../qclib;../libs;../d3d9;../libs/dxsdk9/include;../libs/dxsdk7/include;%(AdditionalIncludeDirectories) - _DEBUG;D3DQUAKE;WIN32;_WINDOWS;%(PreprocessorDefinitions) + _DEBUG;D3D11QUAKE;WIN32;_WINDOWS;%(PreprocessorDefinitions) MultiThreadedDebug Fast Use @@ -523,7 +526,6 @@ comctl32.lib;wsock32.lib;winmm.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - ../../fted3dqw_dbg.exe true ../libs/dxsdk7/lib;%(AdditionalLibraryDirectories) libc.lib;msvcrt.lib;%(IgnoreSpecificDefaultLibraries) @@ -717,6 +719,7 @@ EditAndContinue FastCall CompileAsC + EnableFastChecks _DEBUG;%(PreprocessorDefinitions) @@ -724,7 +727,6 @@ comctl32.lib;wsock32.lib;winmm.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - ../../fteglqw_dbg.exe true ../libs/dxsdk7/lib;%(AdditionalLibraryDirectories) libc.lib;msvcrt.lib;%(IgnoreSpecificDefaultLibraries) @@ -893,7 +895,7 @@ MaxSpeed OnlyExplicitInline ../libs/speex;..\client;../libs/freetype2/include;../common;../server;../gl;../sw;../qclib;../libs;../libs/dxsdk7/include;%(AdditionalIncludeDirectories) - NDEBUG;WIN32;_WINDOWS;GLQUAKE;D3DQUAKE;%(PreprocessorDefinitions) + NDEBUG;WIN32;_WINDOWS;GLQUAKE;D3D9QUAKE;D3D11QUAKE;%(PreprocessorDefinitions) true MultiThreaded true @@ -1092,7 +1094,7 @@ Disabled ../libs/speex;..\client;../libs/freetype2/include;../common;../server;../gl;../sw;../qclib;../libs;../libs/dxsdk9/include;../libs/dxsdk7/include;%(AdditionalIncludeDirectories) - _DEBUG;WIN32;_WINDOWS;GLQUAKE;D3DQUAKE;%(PreprocessorDefinitions) + USE_MSVCRT_DEBUG;_DEBUG;WIN32;_WINDOWS;GLQUAKE;D3D9QUAKE;D3D11QUAKE;%(PreprocessorDefinitions) MultiThreadedDebug Fast Use @@ -1114,7 +1116,6 @@ comctl32.lib;wsock32.lib;odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies) - ../../fteqw_dbg.exe true ../libs/dxsdk7/lib;%(AdditionalLibraryDirectories) libc.lib;msvcrt.lib;%(IgnoreSpecificDefaultLibraries) @@ -1216,6 +1217,7 @@ CompileAsC 4996;%(DisableSpecificWarnings) MultiThreaded + true NDEBUG;%(PreprocessorDefinitions) @@ -1391,6 +1393,23 @@ + + + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing + + + + + %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -8914,750 +8933,6 @@ - - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - diff --git a/engine/dotnet2010/npfte.vcxproj b/engine/dotnet2010/npfte.vcxproj index 451063eb4..175e92a18 100644 --- a/engine/dotnet2010/npfte.vcxproj +++ b/engine/dotnet2010/npfte.vcxproj @@ -308,6 +308,8 @@ + + diff --git a/engine/droid/AndroidManifest.xml b/engine/droid/AndroidManifest.xml index 20dc4c94c..8cf63283c 100644 --- a/engine/droid/AndroidManifest.xml +++ b/engine/droid/AndroidManifest.xml @@ -11,7 +11,8 @@ + android:label="@string/app_name" + android:configChanges="keyboardHidden|orientation"> diff --git a/engine/droid/src/com/fteqw/FTEDroidActivity.java b/engine/droid/src/com/fteqw/FTEDroidActivity.java index 586d41f4a..ba11fa511 100644 --- a/engine/droid/src/com/fteqw/FTEDroidActivity.java +++ b/engine/droid/src/com/fteqw/FTEDroidActivity.java @@ -15,6 +15,8 @@ import android.view.WindowManager; import android.opengl.GLSurfaceView; import android.view.KeyEvent; import android.view.MotionEvent; +import android.app.AlertDialog; +import android.content.DialogInterface; import android.hardware.SensorManager; import android.hardware.Sensor; @@ -137,6 +139,71 @@ public class FTEDroidActivity extends Activity }; act.runOnUiThread(r); } + if (((flags ^ notifiedflags) & 8) != 0) + { + //8 means sys error + Runnable r = new Runnable() + { + public void run() + { + theview.setVisibility(theview.GONE); + AlertDialog ad = new AlertDialog.Builder(act).create(); + ad.setTitle("FTE ERROR"); + ad.setMessage(FTEDroidEngine.geterrormessage()); + ad.setCancelable(false); + ad.setButton("Ok", new DialogInterface.OnClickListener() + { + public void onClick(DialogInterface dialog, int which) + { + finish(); + System.exit(0); + } + } + ); + ad.show(); + } + }; + act.runOnUiThread(r); + } + if (((flags ^ notifiedflags) & 16) != 0) + { + Runnable r = new Runnable() + { + public void run() + { + String ors = FTEDroidEngine.getpreferedorientation(); + int ori = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR; + if (ors.equalsIgnoreCase("unspecified")) + ori = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; + else if (ors.equalsIgnoreCase("landscape")) + ori = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; + else if (ors.equalsIgnoreCase("portrait")) + ori = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; + else if (ors.equalsIgnoreCase("user")) + ori = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER; + else if (ors.equalsIgnoreCase("behind")) + ori = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; + else if (ors.equalsIgnoreCase("sensor")) + ori = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR; + else if (ors.equalsIgnoreCase("nosensor")) + ori = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; + //the following are api level 9+ + else if (ors.equalsIgnoreCase("sensorlandscape")) + ori = 6;//android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE; + else if (ors.equalsIgnoreCase("sensorportrait")) + ori = 7;//android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT; + else if (ors.equalsIgnoreCase("reverselandscape")) + ori = 8;//android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; + else if (ors.equalsIgnoreCase("reverseportrait")) + ori = 9;//android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT; + else if (ors.equalsIgnoreCase("fullsensor")) + ori = 10;//android.content.pm.ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR; + android.util.Log.i("FTEDroid", "Orientation changed to " + ori + " (" + ors + ")."); + act.setRequestedOrientation(ori); + } + }; + act.runOnUiThread(r); + } //clear anything which is an impulse notifiedflags = flags; @@ -153,6 +220,7 @@ public class FTEDroidActivity extends Activity @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { + FTEDroidEngine.newglcontext(); } } @@ -550,7 +618,6 @@ public class FTEDroidActivity extends Activity android.util.Log.i("FTEDroid", "create view"); view = new FTEView(this); setContentView(view); - // setContentView(R.layout.main); if (runningintheemulator()) diff --git a/engine/droid/src/com/fteqw/FTEDroidEngine.java b/engine/droid/src/com/fteqw/FTEDroidEngine.java index 2e1ce26e0..e551d4cf3 100644 --- a/engine/droid/src/com/fteqw/FTEDroidEngine.java +++ b/engine/droid/src/com/fteqw/FTEDroidEngine.java @@ -1,16 +1,19 @@ -package com.fteqw; - -public class FTEDroidEngine -{ - public static native void init(int w, int h, int gles2, String apkpath, String usrpath); /* init/reinit */ - public static native int frame(float ax, float ay, float az); - public static native int getvibrateduration(); //in ms - public static native void keypress(int down, int qkey, int unicode); - public static native void motion(int act, int pointerid, float x, float y, float size); - public static native int paintaudio(byte[] stream, int len); - - static - { - System.loadLibrary("ftedroid"); - } -} +package com.fteqw; + +public class FTEDroidEngine +{ + public static native void init(int w, int h, int gles2, String apkpath, String usrpath); /* init/reinit */ + public static native int frame(float ax, float ay, float az); + public static native int getvibrateduration(); //in ms + public static native void keypress(int down, int qkey, int unicode); + public static native void motion(int act, int pointerid, float x, float y, float size); + public static native int paintaudio(byte[] stream, int len); + public static native String geterrormessage(); + public static native String getpreferedorientation(); + public static native void newglcontext(); + + static + { + System.loadLibrary("ftedroid"); + } +} diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 888d0dcde..9c9b97ac4 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -15,7 +15,7 @@ #include "quakedef.h" #include "glquake.h" -#if defined(GLQUAKE) || defined(D3DQUAKE) +#ifndef SERVERONLY #ifdef _WIN32 #include @@ -25,6 +25,13 @@ #include "com_mesh.h" +#if defined(RTLIGHTS) +static int numProjectedShadowVerts; +static vec3_t *ProjectedShadowVerts; +static int numFacing; +static qbyte *triangleFacing; +#endif + //FIXME typedef struct { @@ -168,6 +175,16 @@ void GL_GAliasFlushSkinCache(void) BZ_Free(skincolourmapped.bucket); skincolourmapped.bucket = NULL; skincolourmapped.numbuckets = 0; + +#ifdef RTLIGHTS + BZ_Free(ProjectedShadowVerts); + ProjectedShadowVerts = NULL; + numProjectedShadowVerts = 0; + + BZ_Free(triangleFacing); + triangleFacing = NULL; + numFacing = 0; +#endif } static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, entity_t *e, texnums_t **forcedtex) @@ -507,7 +524,7 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e } if (qrenderer == QR_OPENGL) { - cm->texnum.base = R_AllocNewTexture(cm->name, scaled_width, scaled_height); + cm->texnum.base = R_AllocNewTexture(cm->name, scaled_width, scaled_height, IF_NOMIPMAP); R_Upload(cm->texnum.base, cm->name, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, NULL, scaled_width, scaled_height, IF_NOMIPMAP); } else @@ -533,7 +550,7 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e } if (qrenderer == QR_OPENGL) { - cm->texnum.fullbright = R_AllocNewTexture(cm->name, scaled_width, scaled_height); + cm->texnum.fullbright = R_AllocNewTexture(cm->name, scaled_width, scaled_height, IF_NOMIPMAP); R_Upload(cm->texnum.fullbright, cm->name, TF_RGBA32, pixels, NULL, scaled_width, scaled_height, IF_NOMIPMAP); } else @@ -573,8 +590,6 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e } #if defined(RTLIGHTS) -static int numFacing; -static qbyte *triangleFacing; static void R_CalcFacing(mesh_t *mesh, vec3_t lightpos) { float *v1, *v2, *v3; @@ -609,8 +624,6 @@ static void R_CalcFacing(mesh_t *mesh, vec3_t lightpos) } #define PROJECTION_DISTANCE 30000 -static int numProjectedShadowVerts; -static vec3_t *ProjectedShadowVerts; static void R_ProjectShadowVolume(mesh_t *mesh, vec3_t lightpos) { int numverts = mesh->numvertexes; diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 173217216..37a9a9cb0 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -4,7 +4,7 @@ #ifdef GLQUAKE -#define r_refract_fboival 0 +#define r_refract_fboival 1 #include "glquake.h" #include "shader.h" @@ -901,7 +901,7 @@ void R_IBrokeTheArrays(void) #ifdef RTLIGHTS //called from gl_shadow -void BE_SetupForShadowMap(texid_t shadowmaptex) +void GLBE_SetupForShadowMap(texid_t shadowmaptex) { shaderstate.curshadowmap = shadowmaptex; while(shaderstate.lastpasstmus>0) @@ -946,7 +946,7 @@ static void T_Gen_CurrentRender(int tmu) } // copy the scene to texture if (!TEXVALID(shaderstate.temptexture)) - TEXASSIGN(shaderstate.temptexture, GL_AllocNewTexture("***$currentrender***", vwidth, vheight)); + TEXASSIGN(shaderstate.temptexture, GL_AllocNewTexture("***$currentrender***", vwidth, vheight, 0)); GL_MTBind(tmu, GL_TEXTURE_2D, shaderstate.temptexture); qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, vwidth, vheight, 0); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -978,10 +978,13 @@ static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass) t = lightmap[shaderstate.curbatch->lightmap[0]]->lightmap_texture; break; case T_GEN_DELUXMAP: - if (shaderstate.curbatch->lightmap[0] < 0) - t = r_nulltex; //fixme - else - t = lightmap[shaderstate.curbatch->lightmap[0]]->deluxmap_texture; + { + int lmi = shaderstate.curbatch->lightmap[0]; + if (lmi < 0 || !lightmap[lmi]->hasdeluxe) + t = r_nulltex; //fixme + else + t = lightmap[lmi+1]->lightmap_texture; + } break; case T_GEN_DIFFUSE: if (shaderstate.curtexnums && TEXVALID(shaderstate.curtexnums->base)) @@ -1186,7 +1189,7 @@ void GenerateFogTexture(texid_t *tex, float density, float zscale) } if (!TEXVALID(*tex)) - *tex = R_AllocNewTexture("***fog***", FOGS, FOGT); + *tex = R_AllocNewTexture("***fog***", FOGS, FOGT, 0); R_Upload(*tex, "fog", TF_RGBA32, fogdata, NULL, FOGS, FOGT, IF_CLAMP|IF_NOMIPMAP); } @@ -2255,7 +2258,7 @@ static void BE_SendPassBlendDepthMask(unsigned int sbits) else if (shaderstate.flags & BEF_FORCETRANSPARENT) { if ((sbits & SBITS_BLEND_BITS) == (SBITS_SRCBLEND_ONE| SBITS_DSTBLEND_ZERO) || !(sbits & SBITS_BLEND_BITS)) /*if transparency is forced, clear alpha test bits*/ - sbits = (sbits & ~(SBITS_MISC_DEPTHWRITE|SBITS_BLEND_BITS|SBITS_ATEST_BITS)) + sbits = (sbits & ~(SBITS_BLEND_BITS|SBITS_ATEST_BITS)) | (SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA); } @@ -2928,8 +2931,8 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas perm |= PERMUTATION_UPPERLOWER; if (r_refdef.gfog_rgbd[3] && p->handle[perm|PERMUTATION_FOG].glsl) perm |= PERMUTATION_FOG; - if (r_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_OFFSET].glsl) - perm |= PERMUTATION_OFFSET; + if (p->handle[perm|PERMUTATION_DELUXE].glsl && TEXVALID(shaderstate.curtexnums->bump) && shaderstate.curbatch->lightmap[0] >= 0 && lightmap[shaderstate.curbatch->lightmap[0]]->hasdeluxe) + perm |= PERMUTATION_DELUXE; if (shaderstate.curbatch->lightmap[1] >= 0 && p->handle[perm|PERMUTATION_LIGHTSTYLES].glsl) perm |= PERMUTATION_LIGHTSTYLES; @@ -3056,7 +3059,7 @@ void GLBE_SelectMode(backendmode_t mode) #ifdef RTLIGHTS case BEM_STENCIL: /*BEM_STENCIL doesn't support mesh writing*/ - BE_PushOffsetShadow(false); + GLBE_PushOffsetShadow(false); if (gl_config.nofixedfunc && !shaderstate.allblackshader) { @@ -3185,7 +3188,7 @@ void GLBE_SelectEntity(entity_t *ent) shaderstate.curtime = shaderstate.updatetime - shaderstate.curentity->shaderTime; } -void BE_SelectFog(vec3_t colour, float alpha, float density) +static void BE_SelectFog(vec3_t colour, float alpha, float density) { float zscale; @@ -3228,7 +3231,7 @@ void GLBE_SelectDLight(dlight_t *dl, vec3_t colour) shaderstate.lastuniform = 0; } -void BE_PushOffsetShadow(qboolean pushdepth) +void GLBE_PushOffsetShadow(qboolean pushdepth) { extern cvar_t r_polygonoffset_stencil_offset, r_polygonoffset_stencil_factor; polyoffset_t po; @@ -3777,17 +3780,19 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist) if ((batch->shader->flags & (SHADER_HASREFLECT | SHADER_HASREFRACT | SHADER_HASRIPPLEMAP)) && shaderstate.mode != BEM_WIREFRAME) { + int oldbem; //these flags require rendering some view as an fbo if (r_refdef.recurse) continue; if (shaderstate.mode != BEM_STANDARD && shaderstate.mode != BEM_DEPTHDARK) continue; + oldbem = shaderstate.mode; if (batch->shader->flags & SHADER_HASREFLECT) { if (!shaderstate.tex_reflection.num) { - shaderstate.tex_reflection = GL_AllocNewTexture("***tex_reflection***", vid.pixelwidth/2, vid.pixelheight/2); + shaderstate.tex_reflection = GL_AllocNewTexture("***tex_reflection***", vid.pixelwidth/2, vid.pixelheight/2, 0); GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_reflection); qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vid.pixelwidth/2, vid.pixelheight/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -3811,7 +3816,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist) { if (!shaderstate.tex_refraction.num) { - shaderstate.tex_refraction = GL_AllocNewTexture("***tex_refraction***", vid.pixelwidth/2, vid.pixelheight/2); + shaderstate.tex_refraction = GL_AllocNewTexture("***tex_refraction***", vid.pixelwidth/2, vid.pixelheight/2, 0); GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_refraction); qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vid.pixelwidth/2, vid.pixelheight/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -3837,7 +3842,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist) { if (!shaderstate.tex_ripplemap.num) { - shaderstate.tex_ripplemap = GL_AllocNewTexture("***tex_ripplemap***", vid.pixelwidth/2, vid.pixelheight/2); + shaderstate.tex_ripplemap = GL_AllocNewTexture("***tex_ripplemap***", vid.pixelwidth/2, vid.pixelheight/2, 0); GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_ripplemap); qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, vid.pixelwidth/2, vid.pixelheight/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -3859,6 +3864,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist) qglViewport (0, 0, vid.pixelwidth, vid.pixelheight); } + BE_SelectMode(oldbem); } GLBE_SubmitBatch(batch); @@ -3887,6 +3893,22 @@ static void BE_UpdateLightmaps(void) { lightmapinfo_t *lm; int lmidx; + int glformat, gltype; + switch (lightmap_bytes) + { + case 4: + glformat = lightmap_bgra?GL_BGRA_EXT:GL_RGBA; + gltype = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + case 3: + glformat = lightmap_bgra?GL_BGR_EXT:GL_RGB; + gltype = GL_UNSIGNED_BYTE; + break; + default: + glformat = GL_LUMINANCE; + gltype = GL_UNSIGNED_BYTE; + break; + } for (lmidx = 0; lmidx < numlightmaps; lmidx++) { lm = lightmap[lmidx]; @@ -3894,46 +3916,28 @@ static void BE_UpdateLightmaps(void) continue; if (lm->modified) { - glRect_t *theRect; lm->modified = false; - theRect = &lm->rectchange; - GL_MTBind(0, GL_TEXTURE_2D, lm->lightmap_texture); - switch (lightmap_bytes) + if (!TEXVALID(lm->lightmap_texture)) { - case 4: - qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, - LMBLOCK_WIDTH, theRect->h, (lightmap_bgra?GL_BGRA_EXT:GL_RGBA), GL_UNSIGNED_INT_8_8_8_8_REV, - lm->lightmaps+(theRect->t) *LMBLOCK_WIDTH*4); - break; - case 3: - qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, - LMBLOCK_WIDTH, theRect->h, (lightmap_bgra?GL_BGR_EXT:GL_RGB), GL_UNSIGNED_BYTE, - lm->lightmaps+(theRect->t) *LMBLOCK_WIDTH*3); - break; - case 1: - qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, - LMBLOCK_WIDTH, theRect->h, GL_LUMINANCE, GL_UNSIGNED_BYTE, - lm->lightmaps+(theRect->t) *LMBLOCK_WIDTH); - break; + TEXASSIGN(lm->lightmap_texture, R_AllocNewTexture("***lightmap***", lm->width, lm->height, 0)); + GL_MTBind(0, GL_TEXTURE_2D, lm->lightmap_texture); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + lm->width, lm->height, 0, glformat, gltype, + lm->lightmaps); } - theRect->l = LMBLOCK_WIDTH; - theRect->t = LMBLOCK_HEIGHT; - theRect->h = 0; - theRect->w = 0; - - if (lm->deluxmodified) + else { - lm->deluxmodified = false; - theRect = &lm->deluxrectchange; - GL_MTBind(0, GL_TEXTURE_2D, lm->deluxmap_texture); - qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, - LMBLOCK_WIDTH, theRect->h, GL_RGB, GL_UNSIGNED_BYTE, - lm->deluxmaps+(theRect->t) *LMBLOCK_WIDTH*3); - theRect->l = LMBLOCK_WIDTH; - theRect->t = LMBLOCK_HEIGHT; - theRect->h = 0; - theRect->w = 0; + GL_MTBind(0, GL_TEXTURE_2D, lm->lightmap_texture); + qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, lm->rectchange.t, + lm->width, lm->rectchange.h, glformat, gltype, + lm->lightmaps+(lm->rectchange.t) *lm->width*lightmap_bytes); } + lm->rectchange.l = LMBLOCK_WIDTH; + lm->rectchange.t = LMBLOCK_HEIGHT; + lm->rectchange.h = 0; + lm->rectchange.w = 0; } } } @@ -4045,7 +4049,7 @@ void GLBE_DrawLightPrePass(qbyte *vis) if (!TEXVALID(shaderstate.tex_normals)) { - shaderstate.tex_normals = GL_AllocNewTexture("***prepass normals***", vid.pixelwidth, vid.pixelheight); + shaderstate.tex_normals = GL_AllocNewTexture("***prepass normals***", vid.pixelwidth, vid.pixelheight, 0); r_lightprepass.modified = true; } if (r_lightprepass.modified) @@ -4061,7 +4065,7 @@ void GLBE_DrawLightPrePass(qbyte *vis) { int drb; - shaderstate.tex_diffuse = GL_AllocNewTexture("***prepass diffuse***", vid.pixelwidth, vid.pixelheight); + shaderstate.tex_diffuse = GL_AllocNewTexture("***prepass diffuse***", vid.pixelwidth, vid.pixelheight, 0); GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_diffuse); qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vid.pixelwidth, vid.pixelheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -4190,7 +4194,7 @@ void GLBE_DrawWorld (qboolean drawworld, qbyte *vis) GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex); } #ifdef RTLIGHTS - Sh_Shutdown(); + Sh_Reset(); #endif } BE_GenModelBatches(batches); diff --git a/engine/gl/gl_bloom.c b/engine/gl/gl_bloom.c index afad8d481..9cbcd8d5b 100644 --- a/engine/gl/gl_bloom.c +++ b/engine/gl/gl_bloom.c @@ -96,7 +96,7 @@ static void R_SetupBloomTextures(int w, int h) /*we should be doing this outside of this code*/ if (!TEXVALID(scrtex)) - scrtex = GL_AllocNewTexture("", scrwidth, scrheight); + scrtex = GL_AllocNewTexture("", scrwidth, scrheight, 0); GL_MTBind(0, GL_TEXTURE_2D, scrtex); qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, scrwidth, scrheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); /*top level uses nearest sampling*/ @@ -113,7 +113,7 @@ static void R_SetupBloomTextures(int w, int h) if (!TEXVALID(pingtex[i][j])) { sprintf(name, "***bloom*%c*%i***", 'a'+i, j); - TEXASSIGN(pingtex[i][j], GL_AllocNewTexture(name, texwidth[j], texheight[j])); + TEXASSIGN(pingtex[i][j], GL_AllocNewTexture(name, texwidth[j], texheight[j], 0)); } GL_MTBind(0, GL_TEXTURE_2D, pingtex[i][j]); qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, texwidth[j], texheight[j], 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 7e0518b70..bd2af7dab 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -198,7 +198,7 @@ static gltexture_t *GL_AllocNewGLTexture(char *ident, int w, int h) return glt; } -texid_t GL_AllocNewTexture(char *name, int w, int h) +texid_t GL_AllocNewTexture(char *name, int w, int h, unsigned int flags) { gltexture_t *glt = GL_AllocNewGLTexture(name, w, h); return glt->texnum; @@ -426,10 +426,6 @@ void GLDraw_Init (void) memset(gltexturetablebuckets, 0, sizeof(gltexturetablebuckets)); Hash_InitTable(&gltexturetable, sizeof(gltexturetablebuckets)/sizeof(gltexturetablebuckets[0]), gltexturetablebuckets); -// GL_FlushSkinCache(); - TRACE(("dbg: GLDraw_ReInit: GL_GAliasFlushSkinCache\n")); - GL_GAliasFlushSkinCache(); - qglGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxtexsize); if (gl_max_size.value > maxtexsize) { @@ -506,12 +502,7 @@ void GLDraw_DeInit (void) R2D_Shutdown(); - if (font_conchar) - Font_Free(font_conchar); - font_conchar = NULL; - if (font_tiny) - Font_Free(font_tiny); - font_tiny = NULL; + GL_GAliasFlushSkinCache(); draw_disc = NULL; diff --git a/engine/gl/gl_font.c b/engine/gl/gl_font.c index ce8d9d1cb..b25b6f322 100644 --- a/engine/gl/gl_font.c +++ b/engine/gl/gl_font.c @@ -254,7 +254,7 @@ void Font_Init(void) for (i = 0; i < FONTPLANES; i++) { - TEXASSIGN(fontplanes.texnum[i], R_AllocNewTexture("***fontplane***", PLANEWIDTH, PLANEHEIGHT)); + TEXASSIGN(fontplanes.texnum[i], R_AllocNewTexture("***fontplane***", PLANEWIDTH, PLANEHEIGHT, IF_NOMIPMAP)); } fontplanes.shader = R_RegisterShader("ftefont", @@ -265,7 +265,7 @@ void Font_Init(void) "]\n" "nomipmaps\n" "{\n" - "map $diffuse\n" + "map $nearest:$diffuse\n" "rgbgen vertex\n" "alphagen vertex\n" "blendfunc blend\n" @@ -609,6 +609,8 @@ qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, char *fontfilename) FT_Error error; flocation_t loc; void *fbase = NULL; + if (!*fontfilename) + return false; if (!fontlib) { dllfunction_t ft2funcs[] = diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index 498bce192..0bdec8586 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -19,7 +19,7 @@ //we get 20->130 //perhaps we should build it with multitexture? (no - slower on ati) -int Surf_NewLightmaps(int count, int width, int height); +int Surf_NewLightmaps(int count, int width, int height, qboolean deluxe); #define MAXSECTIONS 64 //this many sections max in each direction #define SECTTEXSIZE 64 //this many texture samples per section @@ -134,6 +134,7 @@ typedef struct heightmap_s hmcluster_t *cluster[MAXSECTIONS*MAXSECTIONS]; shader_t *skyshader; shader_t *shader; + shader_t *watershader; mesh_t skymesh; mesh_t *askymesh; unsigned int exteriorcontents; @@ -225,12 +226,11 @@ static void Terr_InitLightmap(hmsection_t *s) { int lm; int i; - lm = Surf_NewLightmaps(1, SECTTEXSIZE*LMCHUNKS, SECTTEXSIZE*LMCHUNKS); + lm = Surf_NewLightmaps(1, SECTTEXSIZE*LMCHUNKS, SECTTEXSIZE*LMCHUNKS, false); for (i = 0; i < LMCHUNKS*LMCHUNKS; i++) { lms = malloc(sizeof(*lms)); lms->lm = lm; - BE_UploadAllLightmaps(); lms->x = (i & (LMCHUNKS-1))*SECTTEXSIZE; lms->y = (i / LMCHUNKS)*SECTTEXSIZE; lms->next = hm->unusedlmsects; @@ -428,6 +428,29 @@ static hmsection_t *Terr_LoadSection(heightmap_t *hm, hmsection_t *s, int sx, in { s->flags |= TSF_RELIGHT; + if (s->lightmap >= 0) + { + lm = lightmap[s->lightmap]->lightmaps; + lm += (s->lmy * HMLMSTRIDE + s->lmx) * lightmap_bytes; + for (i = 0; i < SECTTEXSIZE; i++) + { + memset(lm, 0, sizeof(byte_vec4_t)*SECTTEXSIZE); + lm += (HMLMSTRIDE)*lightmap_bytes; + } + lightmap[s->lightmap]->modified = true; + lightmap[s->lightmap]->rectchange.l = 0; + lightmap[s->lightmap]->rectchange.t = 0; + lightmap[s->lightmap]->rectchange.w = HMLMSTRIDE; + lightmap[s->lightmap]->rectchange.h = HMLMSTRIDE; + } + for (i = 0; i < SECTHEIGHTSIZE*SECTHEIGHTSIZE; i++) + { + s->colours[i][0] = 1; + s->colours[i][1] = 1; + s->colours[i][2] = 1; + s->colours[i][3] = 1; + } + #if 0//def DEBUG void *f; if (lightmap_bytes == 4 && lightmap_bgra && FS_LoadFile(va("maps/%s/splatt.png", hm->path), &f) >= 0) @@ -807,26 +830,11 @@ void Terr_PurgeTerrainModel(model_t *mod, qboolean lightmapsonly, qboolean light #endif } #ifndef SERVERONLY -void Terr_DrawTerrainWater(float *mins, float *maxs, float waterz, float r, float g, float b, float a) +void Terr_DrawTerrainWater(heightmap_t *hm, float *mins, float *maxs, float waterz, float r, float g, float b, float a) { scenetris_t *t; - shader_t *s = R_RegisterCustom ("warp/terrain", Shader_DefaultBSPQ2, NULL); - - if (!TEXVALID(s->defaulttextures.base)) - s->defaulttextures.base = R_LoadHiResTexture("terwater", NULL, IF_NOALPHA); - if (!TEXVALID(s->defaulttextures.bump)) - s->defaulttextures.bump = R_LoadBumpmapTexture("terwater_bump", NULL); - if (!TEXVALID(s->defaulttextures.bump)) - { - unsigned char dat[64*64] = {0}; - int i; - for (i = 0; i < 64*64; i++) - dat[i] = rand()&15; - s->defaulttextures.bump = R_LoadTexture8BumpPal("terwater_bump", 64, 64, dat, 0); - } - - - if (cl_numstris && cl_stris[cl_numstris-1].shader == s) + + if (cl_numstris && cl_stris[cl_numstris-1].shader == hm->watershader) { t = &cl_stris[cl_numstris-1]; } @@ -838,7 +846,7 @@ void Terr_DrawTerrainWater(float *mins, float *maxs, float waterz, float r, floa cl_stris = BZ_Realloc(cl_stris, sizeof(*cl_stris)*cl_maxstris); } t = &cl_stris[cl_numstris++]; - t->shader = s; + t->shader = hm->watershader; t->firstidx = cl_numstrisidx; t->firstvert = cl_numstrisvert; t->numvert = 0; @@ -935,6 +943,7 @@ void Terr_RebuildMesh(hmsection_t *s, int x, int y) BZ_Free(mesh->indexes); mesh->indexes = BZ_Malloc(sizeof(index_t) * SECTHEIGHTSIZE*SECTHEIGHTSIZE*6*3); mesh->numindexes = 0; + mesh->colors4f_array = NULL; for (vy = 0; vy < SECTHEIGHTSIZE-1; vy++) { @@ -1124,6 +1133,7 @@ void Terr_RebuildMesh(hmsection_t *s, int x, int y) mesh->st_array = (void*) (mesh->xyz_array + (SECTHEIGHTSIZE)*(SECTHEIGHTSIZE)); mesh->lmst_array[0] = (void*) (mesh->st_array + (SECTHEIGHTSIZE)*(SECTHEIGHTSIZE)); } + mesh->colors4f_array = s->colours; mesh->numvertexes = 0; /*64 quads across requires 65 verticies*/ for (vy = 0; vy < SECTHEIGHTSIZE; vy++) @@ -1206,7 +1216,7 @@ void Terr_RebuildMesh(hmsection_t *s, int x, int y) #ifdef GLQUAKE if (qrenderer == QR_OPENGL) { - if (qrenderer == QR_OPENGL) + if (s->vbo.coord.gl.vbo) { qglDeleteBuffersARB(1, &s->vbo.coord.gl.vbo); qglDeleteBuffersARB(1, &s->vbo.indicies.gl.vbo); @@ -1224,7 +1234,7 @@ void Terr_RebuildMesh(hmsection_t *s, int x, int y) GL_SelectVBO(s->vbo.coord.gl.vbo); qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, (sizeof(vecV_t)+sizeof(vec2_t)+sizeof(vec2_t)) * mesh->numvertexes, mesh->xyz_array); - if (!hm->tiled) + if (mesh->colors4f_array) qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, (sizeof(vecV_t)+sizeof(vec2_t)+sizeof(vec2_t)) * mesh->numvertexes, sizeof(vec4_t)*mesh->numvertexes, mesh->colors4f_array); GL_SelectVBO(0); s->vbo.coord.gl.addr = 0; @@ -1249,6 +1259,21 @@ void Terr_RebuildMesh(hmsection_t *s, int x, int y) // mesh->indexes = NULL; } #endif +#ifdef D3D11QUAKE + if (qrenderer == QR_DIRECT3D11) + { + void D3D11BE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch); + batch_t batch = {0}; + mesh_t *meshes = &s->mesh; + vbo_t *vbo = NULL; + batch.maxmeshes = 1; + batch.mesh = &meshes; + + //BE_ClearVBO(&s->vbo); + D3D11BE_GenBatchVBOs(&vbo, &batch, NULL); + s->vbo = *vbo; + } +#endif } void Terr_DrawTerrainModel (batch_t **batches, entity_t *e) @@ -1381,7 +1406,7 @@ void Terr_DrawTerrainModel (batch_t **batches, entity_t *e) maxs[2] = s->waterheight; if (!R_CullBox(mins, maxs)) { - Terr_DrawTerrainWater(mins, maxs, s->waterheight, 1, 1, 1, 1); + Terr_DrawTerrainWater(hm, mins, maxs, s->waterheight, 1, 1, 1, 1); } } @@ -1404,7 +1429,7 @@ void Terr_DrawTerrainModel (batch_t **batches, entity_t *e) b->buildmeshes = NULL; b->skin = &s->textures; b->texture = NULL; - b->vbo = &s->vbo; + b->vbo = NULL;//&s->vbo; b->lightmap[0] = s->lightmap; b->lightmap[1] = -1; b->lightmap[2] = -1; @@ -2002,7 +2027,7 @@ qboolean Heightmap_Trace(struct model_s *model, int hulloverride, int frame, vec npos[axis] -= nudge[axis]; } else - frac[axis] = 1000000000000000; + frac[axis] = 1000000000000000.0; } //which side are we going down? @@ -2137,6 +2162,9 @@ static void ted_dorelight(heightmap_t *hm) s->flags &= ~TSF_RELIGHT; hm->relight = NULL; + if (s->lightmap < 0) + return; + for (y = -EXPAND; y < SECTTEXSIZE+EXPAND; y++) for (x = -EXPAND; x < SECTTEXSIZE+EXPAND; x++) { @@ -2172,6 +2200,12 @@ static void ted_dorelight(heightmap_t *hm) // lm[2] = norm[2]*127 + 128; lm[3] = d*255; } + + lightmap[s->lightmap]->modified = true; + lightmap[s->lightmap]->rectchange.l = 0; + lightmap[s->lightmap]->rectchange.t = 0; + lightmap[s->lightmap]->rectchange.w = HMLMSTRIDE; + lightmap[s->lightmap]->rectchange.h = HMLMSTRIDE; } static void ted_sethole(void *ctx, hmsection_t *s, int idx, float wx, float wy, float w) { @@ -2845,6 +2879,21 @@ void Terr_FinishTerrain(heightmap_t *hm, char *shadername, char *skyname) "]\n" "}\n" ); + + + hm->watershader = R_RegisterCustom ("warp/terrain", Shader_DefaultBSPQ2, NULL); + if (!TEXVALID(hm->watershader->defaulttextures.base)) + hm->watershader->defaulttextures.base = R_LoadHiResTexture("terwater", NULL, IF_NOALPHA); + if (!TEXVALID(hm->watershader->defaulttextures.bump)) + hm->watershader->defaulttextures.bump = R_LoadBumpmapTexture("terwater_bump", NULL); + if (!TEXVALID(hm->watershader->defaulttextures.bump)) + { + unsigned char dat[64*64] = {0}; + int i; + for (i = 0; i < 64*64; i++) + dat[i] = rand()&15; + hm->watershader->defaulttextures.bump = R_LoadTexture8BumpPal("terwater_bump", 64, 64, dat, 0); + } } #endif } diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 6c870181c..8f0fedd01 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -25,7 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -#if defined(GLQUAKE) || defined(D3DQUAKE) +#ifndef SERVERONLY //FIXME #include "glquake.h" #include "com_mesh.h" @@ -45,7 +45,9 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer); #ifdef Q2BSPS qboolean Mod_LoadQ2BrushModel (model_t *mod, void *buffer); #endif +#ifdef HALFLIFEMODELS qboolean Mod_LoadHLModel (model_t *mod, void *buffer); +#endif model_t *RMod_LoadModel (model_t *mod, qboolean crash); #ifdef MAP_DOOM @@ -596,15 +598,20 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash) loadmodel = mod; -#ifdef Q2BSPS if (!*mod->name) { - if (!Mod_LoadQ2BrushModel (mod, buf)) - goto couldntload; + mod->type = mod_dummy; + mod->mins[0] = -16; + mod->mins[1] = -16; + mod->mins[2] = -16; + mod->maxs[0] = 16; + mod->maxs[1] = 16; + mod->maxs[2] = 16; mod->needload = false; + mod->engineflags = 0; + P_LoadedModel(mod); return mod; } -#endif // // load the file @@ -808,7 +815,8 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash) case 30: //hl case 29: //q1 case 28: //prerel - case BSPVERSION_LONG: + case BSPVERSION_LONG1: + case BSPVERSION_LONG2: TRACE(("RMod_LoadModel: hl/q1 bsp\n")); if (!RMod_LoadBrushModel (mod, buf)) continue; @@ -865,9 +873,6 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash) return mod; } -#ifdef Q2BSPS -couldntload: -#endif if (crash) Host_EndGame ("Mod_NumForName: %s not found or couldn't load", mod->name); @@ -1626,7 +1631,7 @@ void RMod_LoadLighting (lump_t *l) } if (!luxdata) //dp... { - COM_StripExtension(COM_SkipPath(loadmodel->name), luxname+5, sizeof(luxname)-5); + COM_StripExtension(loadmodel->name, luxname, sizeof(luxname)); COM_DefaultExtension(luxname, ".dlit", sizeof(luxname)); luxdata = COM_LoadHunkFile(luxname); luxtmp = false; @@ -2540,15 +2545,25 @@ typedef struct { int allocated[LMBLOCK_WIDTH]; int lmnum; + qboolean deluxe; } lmalloc_t; -static void RMod_LightmapAllocInit(lmalloc_t *lmallocator) +static void RMod_LightmapAllocInit(lmalloc_t *lmallocator, qboolean hasdeluxe) { memset(lmallocator, 0, sizeof(*lmallocator)); + lmallocator->deluxe = hasdeluxe; } static void RMod_LightmapAllocDone(lmalloc_t *lmallocator, model_t *mod) { mod->lightmaps.first = 1; mod->lightmaps.count = lmallocator->lmnum; + if (lmallocator->deluxe) + { + mod->lightmaps.first*=2; + mod->lightmaps.count*=2; + mod->lightmaps.deluxemapping = true; + } + else + mod->lightmaps.deluxemapping = false; } static void RMod_LightmapAllocBlock(lmalloc_t *lmallocator, int w, int h, unsigned short *x, unsigned short *y, int *tnum) { @@ -2590,7 +2605,10 @@ static void RMod_LightmapAllocBlock(lmalloc_t *lmallocator, int w, int h, unsign for (i=0; i < w; i++) lmallocator->allocated[*x + i] = best + h; - *tnum = lmallocator->lmnum; + if (lmallocator->deluxe) + *tnum = lmallocator->lmnum*2; + else + *tnum = lmallocator->lmnum; break; } } @@ -2687,7 +2705,7 @@ static void RMod_Batches_AllocLightmaps(model_t *mod) msurface_t *surf; int sty; - RMod_LightmapAllocInit(&lmallocator); + RMod_LightmapAllocInit(&lmallocator, mod->deluxdata != NULL); for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++) for (batch = mod->batches[sortid]; batch != NULL; batch = batch->next) @@ -2827,14 +2845,53 @@ void RMod_SetParent (mnode_t *node, mnode_t *parent) Mod_LoadNodes ================= */ -qboolean RMod_LoadNodes (lump_t *l, qboolean lm) +qboolean RMod_LoadNodes (lump_t *l, int lm) { int i, j, count, p; mnode_t *out; - if (lm) + if (lm == 2) { - dlnode_t *in; + dl2node_t *in; + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + { + Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); + return false; + } + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->nodes = out; + loadmodel->numnodes = count; + + for ( i=0 ; iminmaxs[j] = LittleFloat (in->mins[j]); + out->minmaxs[3+j] = LittleFloat (in->maxs[j]); + } + + p = LittleLong(in->planenum); + out->plane = loadmodel->planes + p; + + out->firstsurface = LittleLong (in->firstface); + out->numsurfaces = LittleLong (in->numfaces); + + for (j=0 ; j<2 ; j++) + { + p = LittleLong (in->children[j]); + if (p >= 0) + out->children[j] = loadmodel->nodes + p; + else + out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p)); + } + } + } + else if (lm) + { + dl1node_t *in; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) { @@ -2897,8 +2954,8 @@ qboolean RMod_LoadNodes (lump_t *l, qboolean lm) p = LittleLong(in->planenum); out->plane = loadmodel->planes + p; - out->firstsurface = LittleShort (in->firstface); - out->numsurfaces = LittleShort (in->numfaces); + out->firstsurface = (unsigned short)LittleShort (in->firstface); + out->numsurfaces = (unsigned short)LittleShort (in->numfaces); for (j=0 ; j<2 ; j++) { @@ -2920,14 +2977,71 @@ qboolean RMod_LoadNodes (lump_t *l, qboolean lm) Mod_LoadLeafs ================= */ -qboolean RMod_LoadLeafs (lump_t *l, qboolean lm) +qboolean RMod_LoadLeafs (lump_t *l, int lm) { mleaf_t *out; int i, j, count, p; - if (lm) + if (lm==2) { - dlleaf_t *in; + dl2leaf_t *in; + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + { + Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); + return false; + } + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->leafs = out; + loadmodel->numleafs = count; + + for ( i=0 ; iminmaxs[j] = LittleFloat (in->mins[j]); + out->minmaxs[3+j] = LittleFloat (in->maxs[j]); + } + + p = LittleLong(in->contents); + out->contents = p; + + out->firstmarksurface = loadmodel->marksurfaces + + LittleLong(in->firstmarksurface); + out->nummarksurfaces = LittleLong(in->nummarksurfaces); + + p = LittleLong(in->visofs); + if (p == -1) + out->compressed_vis = NULL; + else + out->compressed_vis = loadmodel->visdata + p; + + for (j=0 ; j<4 ; j++) + out->ambient_sound_level[j] = in->ambient_level[j]; + + #ifndef CLIENTONLY + if (!isDedicated) + #endif + { + // gl underwater warp + if (out->contents != Q1CONTENTS_EMPTY) + { + for (j=0 ; jnummarksurfaces ; j++) + out->firstmarksurface[j]->flags |= SURF_UNDERWATER; + } + if (isnotmap) + { + for (j=0 ; jnummarksurfaces ; j++) + out->firstmarksurface[j]->flags |= SURF_DONTWARP; + } + } + } + } + else if (lm) + { + dl1leaf_t *in; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) { @@ -3751,7 +3865,7 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer) unsigned int chksum; int start; qboolean noerrors; - qboolean longm = false; + int longm = false; mesh_t *meshlist = NULL; #if (defined(ODE_STATIC) || defined(ODE_DYNAMIC)) qboolean ode = true; @@ -3781,12 +3895,18 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer) loadmodel->fromgame = fg_quake; loadmodel->engineflags |= MDLF_NEEDOVERBRIGHT; } - else if (i == BSPVERSION_LONG) + else if (i == BSPVERSION_LONG1) { longm = true; loadmodel->fromgame = fg_quake; loadmodel->engineflags |= MDLF_NEEDOVERBRIGHT; } + else if (i == BSPVERSION_LONG2) + { + longm = 2; + loadmodel->fromgame = fg_quake; + loadmodel->engineflags |= MDLF_NEEDOVERBRIGHT; + } else if (i == BSPVERSIONHL) //halflife support loadmodel->fromgame = fg_halflife; else diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index a23393475..0dc48d14b 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -180,6 +180,8 @@ BRUSH MODELS ============================================================================== */ +struct mnode_s; + typedef struct { //model is being purged from memory. void (*PurgeModel) (struct model_s *mod); @@ -254,7 +256,7 @@ typedef struct vboarray_s } gl; #endif -#ifdef D3DQUAKE +#if defined(D3D9QUAKE) || defined(D3D11QUAKE) struct { void *buff; @@ -965,6 +967,7 @@ typedef struct model_s int count; int width; int height; + qboolean deluxemapping; } lightmaps; unsigned checksum; diff --git a/engine/gl/gl_ngraph.c b/engine/gl/gl_ngraph.c index c5cecfed0..bf6bd8270 100644 --- a/engine/gl/gl_ngraph.c +++ b/engine/gl/gl_ngraph.c @@ -170,7 +170,7 @@ void R_FrameTimeGraph (int frametime) void R_NetgraphInit(void) { - TEXASSIGN(netgraphtexture, R_AllocNewTexture("***netgraph***", NET_TIMINGS, NET_GRAPHHEIGHT)); + TEXASSIGN(netgraphtexture, R_AllocNewTexture("***netgraph***", NET_TIMINGS, NET_GRAPHHEIGHT, IF_NOMIPMAP)); netgraphshader = R_RegisterShader("netgraph", "{\n" "program default2d\n" diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index 84ca9cd8f..8f18f90bf 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -1452,11 +1452,13 @@ void GLQ1BSP_LightPointValues(model_t *model, vec3_t point, vec3_t res_diffuse, VectorNormalize(res_dir); } +#ifdef RTLIGHTS if (r_shadow_realtime_world.ival) { VectorScale(res_diffuse, r_shadow_realtime_world_lightmaps.value, res_diffuse); VectorScale(res_ambient, r_shadow_realtime_world_lightmaps.value, res_ambient); } +#endif } #endif diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index f21d369ee..119dfc989 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -69,6 +69,8 @@ cvar_t gl_affinemodels = SCVAR("gl_affinemodels","0"); cvar_t gl_reporttjunctions = SCVAR("gl_reporttjunctions","0"); cvar_t gl_finish = SCVAR("gl_finish","0"); cvar_t gl_dither = SCVAR("gl_dither", "1"); +extern cvar_t r_stereo_separation; +extern cvar_t r_stereo_method; extern cvar_t r_postprocshader; extern cvar_t gl_screenangle; @@ -149,13 +151,13 @@ void GL_SetupSceneProcessingTextures (void) scenepp_postproc_cube = r_nulltex; - TEXASSIGN(sceneblur_texture, GL_AllocNewTexture("***postprocess_blur***", 0, 0)); + TEXASSIGN(sceneblur_texture, GL_AllocNewTexture("***postprocess_blur***", 0, 0, 0)); if (!gl_config.arb_shader_objects) return; - TEXASSIGN(scenepp_texture_warp, GL_AllocNewTexture("***postprocess_warp***", 0, 0)); - TEXASSIGN(scenepp_texture_edge, GL_AllocNewTexture("***postprocess_edge***", 0, 0)); + TEXASSIGN(scenepp_texture_warp, GL_AllocNewTexture("***postprocess_warp***", PP_WARP_TEX_SIZE, PP_WARP_TEX_SIZE, 0)); + TEXASSIGN(scenepp_texture_edge, GL_AllocNewTexture("***postprocess_edge***", PP_WARP_TEX_SIZE, PP_WARP_TEX_SIZE, 0)); // init warp texture - this specifies offset in for (y=0; ynodes && cl.worldmodel->type != mod_heightmap)) r_refdef.flags |= Q2RDF_NOWORLDMODEL; - TRACE(("dbg: calling R_SetupGL\n")); - R_SetupGL (); - - TRACE(("dbg: calling R_SetFrustrum\n")); - R_SetFrustum (r_refdef.m_projection, r_refdef.m_view); - - RQ_BeginFrame(); - - if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL)) + stereomode = r_stereo_method.ival; + if (stereomode == 1) { - TRACE(("dbg: calling R_DrawWorld\n")); - Surf_DrawWorld (); // adds static entities to the list +#ifdef GL_STEREO + GLint glb; + qglGetIntegerv(GL_STEREO, &glb); + if (!glb) +#endif + stereomode = 0; //we are not a stereo context, so no stereoscopic rendering (this encourages it to otherwise be left enabled, which means the user is more likely to spot that they asked it to give a slower context. } - else - BE_DrawWorld(false, NULL); - S_ExtraUpdate (); // don't let sound get messed up if going slow -// R_DrawDecals(); + if (r_refdef.recurse || !stereomode || !r_stereo_separation.value) + { + stereooffset[0] = 0; + stereoframes = 1; + stereomode = 0; + } + else + { + stereooffset[0] = -r_stereo_separation.value; + stereooffset[1] = r_stereo_separation.value; + stereoframes = 2; + } - TRACE(("dbg: calling R_RenderDlights\n")); - R_RenderDlights (); + for (i = 0; i < stereoframes; i++) + { + switch (stereomode) + { + default: + case 0: //off + if (i) + return; + break; +#ifdef GL_STEREO + case 1: //proper gl stereo rendering + if (stereooffset[i] < 0) + qglDrawBuffer(GL_BACK_LEFT); + else + qglDrawBuffer(GL_BACK_RIGHT); + break; +#endif + case 2: //red/cyan + if (stereooffset[i] < 0) + qglColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE); + else + qglColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE); + break; + case 3: //red/blue + if (stereooffset[i] < 0) + qglColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE); + else + qglColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE); + break; + case 4: //red/green + if (stereooffset[i] < 0) + qglColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE); + else + qglColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE); + break; - RQ_RenderBatchClear(); + } + if (i) + qglClear (GL_DEPTH_BUFFER_BIT); - cl_numvisedicts = tmpvisents; + TRACE(("dbg: calling R_SetupGL\n")); + R_SetupGL (stereooffset[i]); + + TRACE(("dbg: calling R_SetFrustrum\n")); + R_SetFrustum (r_refdef.m_projection, r_refdef.m_view); + + RQ_BeginFrame(); + + if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL)) + { + TRACE(("dbg: calling R_DrawWorld\n")); + Surf_DrawWorld (); // adds static entities to the list + } + else + BE_DrawWorld(false, NULL); + + S_ExtraUpdate (); // don't let sound get messed up if going slow + + // R_DrawDecals(); + + TRACE(("dbg: calling R_RenderDlights\n")); + R_RenderDlights (); + + RQ_RenderBatchClear(); + + cl_numvisedicts = tmpvisents; + } + + switch (stereomode) + { + default: + case 0: + break; + case 1: + qglDrawBuffer(GL_BACK); + break; + case 2: + case 3: + case 4: + qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + break; + + } } /*generates a new modelview matrix, as well as vpn vectors*/ static void R_MirrorMatrix(plane_t *plane) @@ -1087,7 +1176,7 @@ qboolean R_RenderScene_Cubemap(void) if (!TEXVALID(scenepp_postproc_cube)) { - scenepp_postproc_cube = GL_AllocNewTexture("***fish***", cmapsize, cmapsize); + scenepp_postproc_cube = GL_AllocNewTexture("***fish***", cmapsize, cmapsize, 0); GL_MTBind(0, GL_TEXTURE_CUBE_MAP_ARB, scenepp_postproc_cube); for (i = 0; i < 6; i++) diff --git a/engine/gl/gl_rmisc.c b/engine/gl/gl_rmisc.c index 4f8caa1db..46f5cc49a 100644 --- a/engine/gl/gl_rmisc.c +++ b/engine/gl/gl_rmisc.c @@ -81,7 +81,7 @@ texid_t GenerateNormalisationCubeMap(void) int i, j; - normalisationCubeMap = R_AllocNewTexture("normalisationcubemap", 32, 32); + normalisationCubeMap = R_AllocNewTexture("normalisationcubemap", 32, 32, 0); GL_MTBind(0, GL_TEXTURE_CUBE_MAP_ARB, normalisationCubeMap); //positive x diff --git a/engine/gl/gl_rsurf.c b/engine/gl/gl_rsurf.c index 05c1c0640..716175864 100644 --- a/engine/gl/gl_rsurf.c +++ b/engine/gl/gl_rsurf.c @@ -489,6 +489,10 @@ void GLBE_UploadAllLightmaps(void) if (!lm->modified) continue; lm->modified = false; + if (!TEXVALID(lm->lightmap_texture)) + { + TEXASSIGN(lm->lightmap_texture, R_AllocNewTexture("***lightmap***", lm->width, lm->height, 0)); + } GL_MTBind(0, GL_TEXTURE_2D, lm->lightmap_texture); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -510,20 +514,6 @@ void GLBE_UploadAllLightmaps(void) lightmap[i]->lightmaps); break; } - if (r_deluxemapping.ival) - { - lightmap[i]->deluxmodified = false; - lightmap[i]->deluxrectchange.l = lm->width; - lightmap[i]->deluxrectchange.t = lm->height; - lightmap[i]->deluxrectchange.w = 0; - lightmap[i]->deluxrectchange.h = 0; - GL_MTBind(0, GL_TEXTURE_2D, lm->deluxmap_texture); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - qglTexImage2D (GL_TEXTURE_2D, 0, 3 - , lm->width, lm->height, 0, - GL_RGB, GL_UNSIGNED_BYTE, lightmap[i]->deluxmaps); - } } } diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 327c14355..8933c2d23 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -31,7 +31,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include -#ifdef D3DQUAKE +#ifdef D3D9QUAKE #include extern LPDIRECT3DDEVICE9 pD3DDev9; #endif @@ -241,6 +241,12 @@ static qboolean Shader_EvaluateCondition(char **ptr) else if (!Q_stricmp(token, "normalmap") ) conditiontrue = conditiontrue == r_loadbumpmapping; + else if (!Q_stricmp(token, "opengl") ) + conditiontrue = conditiontrue == (qrenderer == QR_OPENGL); + else if (!Q_stricmp(token, "d3d9") ) + conditiontrue = conditiontrue == (qrenderer == QR_DIRECT3D9); + else if (!Q_stricmp(token, "d3d11") ) + conditiontrue = conditiontrue == (qrenderer == QR_DIRECT3D11); else if (!Q_stricmp(token, "gles") ) { #ifdef GLQUAKE @@ -251,11 +257,22 @@ static qboolean Shader_EvaluateCondition(char **ptr) } else if (!Q_stricmp(token, "nofixed") ) { + switch(qrenderer) + { #ifdef GLQUAKE - conditiontrue = conditiontrue == ((qrenderer == QR_OPENGL) && !!gl_config.nofixedfunc); -#else - conditiontrue = conditiontrue == false; + case QR_OPENGL: + conditiontrue = conditiontrue == ((qrenderer == QR_OPENGL) && !!gl_config.nofixedfunc); + break; #endif +#ifdef D3D11QUAKE + case QR_DIRECT3D11: + conditiontrue = conditiontrue == true; + break; +#endif + default: + conditiontrue = conditiontrue == false; + break; + } } else if (!Q_stricmp(token, "glsl") ) { @@ -267,15 +284,22 @@ static qboolean Shader_EvaluateCondition(char **ptr) } else if (!Q_stricmp(token, "hlsl") ) { -#ifdef D3DQUAKE - conditiontrue = conditiontrue == false;//((qrenderer == QR_DIRECT3D) && gl_config.arb_shader_objects); -#else - conditiontrue = conditiontrue == false; + switch(qrenderer) + { +#ifdef D3D9QUAKE + case QR_DIRECT3D9: + conditiontrue = conditiontrue == true; //FIXME + break; #endif - - - -// GCC hates these within if statements "error: expected '}' before 'else'" +#ifdef D3D11QUAKE + case QR_DIRECT3D11: + conditiontrue = conditiontrue == true; + break; +#endif + default: + conditiontrue = conditiontrue == false; + break; + } #ifdef warningmsg #pragma warningmsg("shader fixme") #endif @@ -545,7 +569,7 @@ static void Shader_ParseFunc ( char **ptr, shaderfunc_t *func ) //=========================================================================== -static int Shader_SetImageFlags(shader_t *shader, char **name) +static int Shader_SetImageFlags(shader_t *shader, shaderpass_t *pass, char **name) { int flags = 0; @@ -556,6 +580,12 @@ static int Shader_SetImageFlags(shader_t *shader, char **name) *name+=4; flags|= IF_3DMAP; } + else if (!Q_strnicmp(*name, "$nearest:", 9)) + { + *name+=9; + flags|= IF_NEAREST; + pass->flags |= SHADER_PASS_NEAREST; + } else name = NULL; } @@ -807,7 +837,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip "#define SPECULAR\n", "#define FULLBRIGHT\n", "#define UPPERLOWER\n", - "#define OFFSETMAPPING\n", + "#define DELUXE\n", "#define SKELETAL\n", "#define FOG\n", "#define FRAMEBLEND\n", @@ -825,6 +855,11 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip int cvarcount = 0; qboolean onefailed = false; + if (qrenderer != qrtype) + { + return false; + } + cvarnames[cvarcount] = NULL; prog->nofixedcompat = true; @@ -940,16 +975,25 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip if (p & (1u<handle[p].glsl) + qglDeleteProgramObject_(prog->handle[p].glsl); prog->handle[p].glsl = GLSlang_CreateProgram(name, (((p & PERMUTATION_SKELETAL) && ver < 120)?120:ver), permutationdefines, script, script, onefailed); if (!prog->handle[p].glsl) onefailed = true; @@ -957,10 +1001,17 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip break; } #endif -#ifdef D3DQUAKE - else if (qrenderer == QR_DIRECT3D) +#ifdef D3D9QUAKE + else if (qrenderer == QR_DIRECT3D9) { - if (!D3DShader_CreateProgram(prog, p, permutationdefines, script, script)) + if (!D3D9Shader_CreateProgram(prog, p, permutationdefines, script, script)) + break; + } +#endif +#ifdef D3D11QUAKE + else if (qrenderer == QR_DIRECT3D11) + { + if (!D3D11Shader_CreateProgram(prog, name, p, permutationdefines, script, script)) break; } #endif @@ -1242,8 +1293,8 @@ struct sbuiltin_s "#endif\n" }, #endif -#ifdef D3DQUAKE - {QR_DIRECT3D, 9, "rtlight", +#ifdef D3D9QUAKE + {QR_DIRECT3D9, 9, "rtlight", /* texture units: s0=diffuse, s1=normal, s2=specular, s3=shadowmap @@ -1305,7 +1356,7 @@ struct sbuiltin_s "#endif\n" }, - {QR_DIRECT3D, 9, "defaultsky", + {QR_DIRECT3D9, 9, "defaultsky", "struct a2v {\n" "float4 pos: POSITION;\n" @@ -1359,7 +1410,7 @@ struct sbuiltin_s "#endif\n" }, - {QR_DIRECT3D, 9, "defaultwarp", + {QR_DIRECT3D9, 9, "defaultwarp", "!!cvarf r_wateralpha\n" "struct a2v {\n" "float4 pos: POSITION;\n" @@ -1403,34 +1454,29 @@ struct sbuiltin_s }; void Shader_UnloadProg(program_t *prog) { - if (prog->refs == 1) - { #ifdef GLQUAKE - if (qrenderer == QR_OPENGL) + if (qrenderer == QR_OPENGL) + { + int p; + for (p = 0; p < PERMUTATIONS; p++) { - int p; - for (p = 0; p < PERMUTATIONS; p++) - { - if (prog->handle[p].glsl) - qglDeleteProgramObject_(prog->handle[p].glsl); - } + if (prog->handle[p].glsl) + qglDeleteProgramObject_(prog->handle[p].glsl); } + } #endif -#ifdef D3DQUAKE - if (qrenderer == QR_DIRECT3D) +#ifdef D3D9QUAKE + if (qrenderer == QR_DIRECT3D9) + { + int p; + for (p = 0; p < PERMUTATIONS; p++) { - int p; - for (p = 0; p < PERMUTATIONS; p++) - { // if (prog->handle[p].hlsl.vert || prog->handle[p].hlsl.frag) // D3DShader_DeleteProgram(&prog->handle[p].hlsl); - } } -#endif - free(prog); } - else - prog->refs--; +#endif + free(prog); } static void Shader_FlushGenerics(void) { @@ -1449,44 +1495,26 @@ static void Shader_FlushGenerics(void) Con_Printf("generic shader still used\n"); } } -static program_t *Shader_LoadGeneric(char *name, int qrtype) +static void Shader_LoadGeneric(sgeneric_t *g, int qrtype) { unsigned int i; void *file; char basicname[MAX_QPATH]; char *h; - sgeneric_t *g; - - for (g = sgenerics; g; g = g->next) - { - if (!strcmp(name, g->name)) - { - if (g->failed) - return NULL; - g->prog.refs++; - return &g->prog; - } - } - - g = malloc(sizeof(*g) + strlen(name)+1); - memset(g, 0, sizeof(*g)); - g->name = (char*)(g+1); - strcpy(g->name, name); - g->next = sgenerics; - sgenerics = g; - - g->prog.refs = 1; + g->failed = true; basicname[1] = 0; - Q_strncpyz(basicname, name, sizeof(basicname)); + Q_strncpyz(basicname, g->name, sizeof(basicname)); h = strchr(basicname+1, '#'); if (h) *h = '\0'; if (strchr(basicname, '/') || strchr(basicname, '.')) FS_LoadFile(basicname, &file); - else if (qrenderer == QR_DIRECT3D) + else if (qrenderer == QR_DIRECT3D9) + FS_LoadFile(va("hlsl/%s.hlsl", basicname), &file); + else if (qrenderer == QR_DIRECT3D11) FS_LoadFile(va("hlsl/%s.hlsl", basicname), &file); else if (qrenderer == QR_OPENGL) { @@ -1502,13 +1530,9 @@ static program_t *Shader_LoadGeneric(char *name, int qrtype) if (file) { Con_DPrintf("Loaded %s from disk\n", basicname); - g->failed = !Shader_LoadPermutations(name, &g->prog, file, qrtype, 0); + g->failed = !Shader_LoadPermutations(g->name, &g->prog, file, qrtype, 0); FS_FreeFile(file); - - g->prog.refs++; - if (g->failed) - return NULL; - return &g->prog; + return; } else { @@ -1535,18 +1559,53 @@ static program_t *Shader_LoadGeneric(char *name, int qrtype) } } #endif - g->failed = !Shader_LoadPermutations(name, &g->prog, sbuiltins[i].body, sbuiltins[i].qrtype, ver); + g->failed = !Shader_LoadPermutations(g->name, &g->prog, sbuiltins[i].body, sbuiltins[i].qrtype, ver); if (g->failed) continue; - g->prog.refs++; - return &g->prog; + return; } } } - g->failed = true; - return NULL; +} +static void Shader_ReloadGenerics(void) +{ + sgeneric_t *g; + for (g = sgenerics; g; g = g->next) + { + Shader_LoadGeneric(g, qrenderer); + } +} +static program_t *Shader_FindGeneric(char *name, int qrtype) +{ + sgeneric_t *g; + + for (g = sgenerics; g; g = g->next) + { + if (!strcmp(name, g->name)) + { + if (g->failed) + return NULL; + g->prog.refs++; + return &g->prog; + } + } + + g = malloc(sizeof(*g) + strlen(name)+1); + memset(g, 0, sizeof(*g)); + g->name = (char*)(g+1); + strcpy(g->name, name); + g->next = sgenerics; + sgenerics = g; + + g->prog.refs = 1; + + Shader_LoadGeneric(g, qrtype); + if (g->failed) + return NULL; + g->prog.refs++; + return &g->prog; } void Shader_WriteOutGenerics_f(void) @@ -1563,7 +1622,9 @@ void Shader_WriteOutGenerics_f(void) else name = va("glsl/%s.glsl", sbuiltins[i].name); } - else if (sbuiltins[i].qrtype == QR_DIRECT3D) + else if (sbuiltins[i].qrtype == QR_DIRECT3D9) + name = va("hlsl/%s.hlsl", sbuiltins[i].name); + else if (sbuiltins[i].qrtype == QR_DIRECT3D11) name = va("hlsl/%s.hlsl", sbuiltins[i].name); if (name) @@ -1768,8 +1829,8 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvarty return; } #endif -#ifdef D3DQUAKE - if (qrenderer == QR_DIRECT3D) +#ifdef D3D9QUAKE + if (qrenderer == QR_DIRECT3D9) { prog->nofixedcompat = true; @@ -1787,14 +1848,14 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvarty { if (!prog->handle[p].glsl) continue; - uniformloc = D3DShader_FindUniform(&prog->handle[p], 1, va("cvar_%s", tmpname)); + uniformloc = D3D9Shader_FindUniform(&prog->handle[p], 1, va("cvar_%s", tmpname)); if (uniformloc != -1) { vec4_t v = {cvar->value, 0, 0, 0}; IDirect3DDevice9_SetVertexShader(pD3DDev9, prog->handle[0].hlsl.vert); IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, 0, v, 1); } - uniformloc = D3DShader_FindUniform(&prog->handle[p], 2, va("cvar_%s", tmpname)); + uniformloc = D3D9Shader_FindUniform(&prog->handle[p], 2, va("cvar_%s", tmpname)); if (uniformloc != -1) { vec4_t v = {cvar->value, 0, 0, 0}; @@ -1808,7 +1869,7 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvarty found = false; for (p = 0; p < PERMUTATIONS; p++) { - uniformloc = D3DShader_FindUniform(&prog->handle[p], 0, shader_unif_names[i].name); + uniformloc = D3D9Shader_FindUniform(&prog->handle[p], 0, shader_unif_names[i].name); if (uniformloc != -1) found = true; prog->parm[prog->numparams].handle[p] = uniformloc; @@ -1824,7 +1885,7 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvarty { for (i = 0; i < 8; i++) { - uniformloc = D3DShader_FindUniform(&prog->handle[p], 2, va("s_t%i", i)); + uniformloc = D3D9Shader_FindUniform(&prog->handle[p], 2, va("s_t%i", i)); if (uniformloc != -1) { int v[4] = {i}; @@ -1901,7 +1962,7 @@ static void Shader_SLProgramName (shader_t *shader, shaderpass_t *pass, char **p return; } - shader->prog = Shader_LoadGeneric(Shader_ParseString(ptr), qrtype); + shader->prog = Shader_FindGeneric(Shader_ParseString(ptr), qrtype); } static void Shader_GLSLProgramName (shader_t *shader, shaderpass_t *pass, char **ptr) @@ -1914,7 +1975,7 @@ static void Shader_ProgramName (shader_t *shader, shaderpass_t *pass, char **ptr } static void Shader_HLSLProgramName (shader_t *shader, shaderpass_t *pass, char **ptr) { - Shader_SLProgramName(shader,pass,ptr,QR_DIRECT3D); + Shader_SLProgramName(shader,pass,ptr,QR_DIRECT3D9); } static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **ptr ) @@ -2087,6 +2148,11 @@ static void Shader_Translucent(shader_t *shader, shaderpass_t *pass, char **ptr) shader->flags |= SHADER_BLEND; } +static void Shader_DP_Camera(shader_t *shader, shaderpass_t *pass, char **ptr) +{ + shader->sort = SHADER_SORT_PORTAL; +} + static shaderkey_t shaderkeys[] = { {"cull", Shader_Cull}, @@ -2107,6 +2173,9 @@ static shaderkey_t shaderkeys[] = {"hlslprogram", Shader_HLSLProgramName}, //for d3d {"param", Shader_ProgramParam}, + //dp compat + {"dp_camera", Shader_DP_Camera}, + /*doom3 compat*/ {"diffusemap", Shader_DiffuseMap}, {"bumpmap", NULL}, @@ -2123,7 +2192,7 @@ static shaderkey_t shaderkeys[] = // =============================================================== -static qboolean ShaderPass_MapGen (shader_t *shader, shaderpass_t *pass, char *tname) +static qboolean Shaderpass_MapGen (shader_t *shader, shaderpass_t *pass, char *tname) { if (!Q_stricmp (tname, "$lightmap")) { @@ -2233,9 +2302,9 @@ static void Shaderpass_Map (shader_t *shader, shaderpass_t *pass, char **ptr) pass->anim_frames[0] = r_nulltex; token = Shader_ParseString (ptr); - if (!ShaderPass_MapGen(shader, pass, token)) + flags = Shader_SetImageFlags (shader, pass, &token); + if (!Shaderpass_MapGen(shader, pass, token)) { - flags = Shader_SetImageFlags (shader, &token); if (flags & IF_3DMAP) pass->texgen = T_GEN_3DMAP; else @@ -2252,7 +2321,7 @@ static void Shaderpass_AnimMap (shader_t *shader, shaderpass_t *pass, char **ptr char *token; texid_t image; - flags = Shader_SetImageFlags (shader, NULL); + flags = Shader_SetImageFlags (shader, pass, NULL); pass->tcgen = TC_GEN_BASE; pass->flags |= SHADER_PASS_ANIMMAP; @@ -2292,10 +2361,9 @@ static void Shaderpass_ClampMap (shader_t *shader, shaderpass_t *pass, char **pt token = Shader_ParseString (ptr); - if (!ShaderPass_MapGen(shader, pass, token)) + flags = Shader_SetImageFlags (shader, pass, &token); + if (!Shaderpass_MapGen(shader, pass, token)) { - flags = Shader_SetImageFlags (shader, &token); - pass->tcgen = TC_GEN_BASE; pass->anim_frames[0] = Shader_FindImage (token, flags | IF_CLAMP); if (flags & IF_3DMAP) @@ -2933,7 +3001,10 @@ void Shader_Free (shader_t *shader) shader->bucket.data = NULL; if (shader->prog) - Shader_UnloadProg(shader->prog); + { + if (shader->prog->refs-- == 1) + Shader_UnloadProg(shader->prog); + } shader->prog = NULL; if (shader->skydome) @@ -3972,6 +4043,37 @@ void Shader_DefaultBSPLM(char *shortname, shader_t *s, const void *args) "}\n" "}\n" ); +#ifdef D3D11QUAKE + if (qrenderer == QR_DIRECT3D11) + { + if (!builtin) + builtin = ( + "{\n" + "program defaultwall\n" + /*"param texture 0 tex_diffuse\n" + "param texture 1 tex_lightmap\n" + "param texture 2 tex_normalmap\n" + "param texture 3 tex_deluxmap\n" + "param texture 4 tex_fullbright\n"*/ + "{\n" + "map $diffuse\n" + "}\n" + "{\n" + "map $lightmap\n" + "}\n" + "{\n" + "map $normalmap\n" + "}\n" + "{\n" + "map $deluxmap\n" + "}\n" + "{\n" + "map $fullbright\n" + "}\n" + "}\n" + ); + } +#endif #ifdef GLQUAKE if (qrenderer == QR_OPENGL) { @@ -4792,8 +4894,8 @@ static int R_LoadShader ( char *name, shader_gen_t *defaultgen, const char *gena } } #endif -#ifdef D3DQUAKE - if (qrenderer == QR_DIRECT3D) +#ifdef D3D9QUAKE + if (qrenderer == QR_DIRECT3D9) { { if (Shader_ParseShader(va("%s_hlsl", shortname), shortname, s)) @@ -4802,6 +4904,17 @@ static int R_LoadShader ( char *name, shader_gen_t *defaultgen, const char *gena } } } +#endif +#ifdef D3D11QUAKE + if (qrenderer == QR_DIRECT3D11) + { + { + if (Shader_ParseShader(va("%s_hlsl11", shortname), shortname, s)) + { + return f; + } + } + } #endif if (Shader_ParseShader(shortname, shortname, s)) { @@ -4853,6 +4966,7 @@ void Shader_DoReload(void) return; shader_reload_needed = false; Font_InvalidateColour(); + Shader_ReloadGenerics(); for (s = r_shaders, i = 0; i < MAX_SHADERS; i++, s++) { diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index bb1adee1f..32247c109 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -9,13 +9,13 @@ model meshes are interpolated multiple times per frame //#define DBG_COLOURNOTDEPTH -#if defined(GLQUAKE) || defined(D3DQUAKE) +#if defined(GLQUAKE) || defined(D3D9QUAKE) #ifdef RTLIGHTS #include "glquake.h" #include "shader.h" -#ifdef D3DQUAKE +#ifdef D3D9QUAKE #include "shader.h" #if !defined(HMONITOR_DECLARED) && (WINVER < 0x0500) #define HMONITOR_DECLARED @@ -23,8 +23,8 @@ model meshes are interpolated multiple times per frame #endif #include extern LPDIRECT3DDEVICE9 pD3DDev9; -void D3DBE_Cull(unsigned int sflags); -void D3DBE_RenderShadowBuffer(unsigned int numverts, IDirect3DVertexBuffer9 *vbuf, unsigned int numindicies, IDirect3DIndexBuffer9 *ibuf); +void D3D9BE_Cull(unsigned int sflags); +void D3D9BE_RenderShadowBuffer(unsigned int numverts, IDirect3DVertexBuffer9 *vbuf, unsigned int numindicies, IDirect3DIndexBuffer9 *ibuf); #endif void GLBE_RenderShadowBuffer(unsigned int numverts, int vbo, vecV_t *verts, unsigned numindicies, int ibo, index_t *indicies); @@ -55,8 +55,11 @@ struct { } bench; - -void Sh_Shutdown(void) +/* +called on framebuffer resize. +flushes textures so they can be regenerated at the real size +*/ +void Sh_Reset(void) { #ifdef GLQUAKE if (shadow_fbo_id) @@ -85,13 +88,15 @@ void Sh_Shutdown(void) crepuscular_fbo_id = 0; } #endif - +} +void Sh_Shutdown(void) +{ + Sh_Reset(); SHM_Shutdown(); } - typedef struct { unsigned int count; unsigned int max; @@ -119,7 +124,7 @@ typedef struct shadowmesh_s { #ifdef GLQUAKE GLuint vebo[2]; #endif -#ifdef D3DQUAKE +#ifdef D3D9QUAKE IDirect3DVertexBuffer9 *d3d_vbuffer; IDirect3DIndexBuffer9 *d3d_ibuffer; #endif @@ -268,14 +273,18 @@ static void SHM_Shadow_Cache_Leaf(mleaf_t *leaf) sh_shmesh->litleaves[i>>3] |= 1<<(i&7); } -void SH_FreeShadowMesh(shadowmesh_t *sm) +static void SH_FreeShadowMesh_(shadowmesh_t *sm) { unsigned int i; for (i = 0; i < sm->numbatches; i++) Z_Free(sm->batches[i].s); + sm->numbatches = 0; Z_Free(sm->batches); + sm->batches = NULL; Z_Free(sm->indicies); + sm->indicies = NULL; Z_Free(sm->verts); + sm->verts = NULL; switch (qrenderer) { @@ -286,8 +295,8 @@ void SH_FreeShadowMesh(shadowmesh_t *sm) sm->vebo[1] = 0; break; #endif -#ifdef D3DQUAKE - case QR_DIRECT3D: +#ifdef D3D9QUAKE + case QR_DIRECT3D9: if (sm->d3d_ibuffer) IDirect3DIndexBuffer9_Release(sm->d3d_ibuffer); sm->d3d_ibuffer = NULL; @@ -297,7 +306,10 @@ void SH_FreeShadowMesh(shadowmesh_t *sm) break; #endif } - +} +void SH_FreeShadowMesh(shadowmesh_t *sm) +{ + SH_FreeShadowMesh_(sm); Z_Free(sm); } @@ -424,8 +436,8 @@ static struct shadowmesh_s *SHM_FinishShadowMesh(dlight_t *dl) qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(*sh_shmesh->indicies) * sh_shmesh->numindicies, sh_shmesh->indicies, GL_STATIC_DRAW_ARB); break; #endif -#ifdef D3DQUAKE - case QR_DIRECT3D: +#ifdef D3D9QUAKE + case QR_DIRECT3D9: if (sh_shmesh->numindicies && sh_shmesh->numverts) { void *map; @@ -988,6 +1000,7 @@ static struct { static void SHM_Shutdown(void) { + SH_FreeShadowMesh_(&sh_tempshmesh); free(cv.tris); free(cv.edges); free(cv.points); @@ -1413,6 +1426,7 @@ static void Sh_Scissor (srect_t r) #ifdef GLQUAKE case QR_OPENGL: qglScissor(r.x, r.y, r.width, r.height); + qglEnable(GL_SCISSOR_TEST); if (qglDepthBoundsEXT) { @@ -1421,8 +1435,8 @@ static void Sh_Scissor (srect_t r) } break; #endif -#ifdef D3DQUAKE - case QR_DIRECT3D: +#ifdef D3D9QUAKE + case QR_DIRECT3D9: { RECT rect; rect.left = r.x; @@ -1435,6 +1449,23 @@ static void Sh_Scissor (srect_t r) #endif } } +static void Sh_ScissorOff (void) +{ + switch(qrenderer) + { +#ifdef GLQUAKE + case QR_OPENGL: + qglDisable(GL_SCISSOR_TEST); + if (qglDepthBoundsEXT) + qglDisable(GL_DEPTH_BOUNDS_TEST_EXT); + break; +#endif +#ifdef D3D9QUAKE + case QR_DIRECT3D9: + break; +#endif + } +} #if 0 static qboolean Sh_ScissorForSphere(vec3_t center, float radius, vrect_t *rect) @@ -1924,6 +1955,7 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, float p r_refdef.flipcull = false; break; } + //fixme GL_CullFace(0); R_SetFrustum(proj, r_refdef.m_view); @@ -1955,9 +1987,9 @@ GL_CullFace(0); GLBE_BaseEntTextures(); break; #endif -#ifdef D3DQUAKE - case QR_DIRECT3D: - D3DBE_BaseEntTextures(); +#ifdef D3D9QUAKE + case QR_DIRECT3D9: + D3D9BE_BaseEntTextures(); break; #endif } @@ -2002,7 +2034,7 @@ void Sh_GenShadowMap (dlight_t *l, qbyte *lvis) { if (isspot) { - shadowmap[isspot] = GL_AllocNewTexture("***shadowmap***", smsize, smsize); + shadowmap[isspot] = GL_AllocNewTexture("***shadowmap***", smsize, smsize, 0); GL_MTBind(0, GL_TEXTURE_2D, shadowmap[isspot]); #ifdef DBG_COLOURNOTDEPTH qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, smsize, smsize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); @@ -2012,7 +2044,7 @@ void Sh_GenShadowMap (dlight_t *l, qbyte *lvis) } else { - shadowmap[isspot] = GL_AllocNewTexture("***shadowmap***", smsize*3, smsize*2); + shadowmap[isspot] = GL_AllocNewTexture("***shadowmap***", smsize*3, smsize*2, 0); GL_MTBind(0, GL_TEXTURE_2D, shadowmap[isspot]); #ifdef DBG_COLOURNOTDEPTH qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, smsize*3, smsize*2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); @@ -2041,7 +2073,7 @@ void Sh_GenShadowMap (dlight_t *l, qbyte *lvis) /*set framebuffer*/ GL_BeginRenderBuffer_DepthOnly(shadowmap[isspot]); - BE_SetupForShadowMap(shadowmap[isspot]); + GLBE_SetupForShadowMap(shadowmap[isspot]); qglViewport(0, 0, smsize*3, smsize*2); qglClear (GL_DEPTH_BUFFER_BIT); @@ -2146,6 +2178,8 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis) } } } + else + lvis = NULL; qglDisable(GL_SCISSOR_TEST); @@ -2155,7 +2189,6 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis) //may as well use scissors Sh_Scissor(rect); - qglEnable(GL_SCISSOR_TEST); ve = 0; @@ -2232,9 +2265,9 @@ static void Sh_DrawEntLighting(dlight_t *light, vec3_t colour) GLBE_BaseEntTextures(); break; #endif -#ifdef D3DQUAKE - case QR_DIRECT3D: - D3DBE_BaseEntTextures(); +#ifdef D3D9QUAKE + case QR_DIRECT3D9: + D3D9BE_BaseEntTextures(); break; #endif } @@ -2268,7 +2301,7 @@ static void Sh_DrawBrushModelShadow(dlight_t *dl, entity_t *e) GL_SelectEBO(0); qglEnableClientState(GL_VERTEX_ARRAY); - BE_PushOffsetShadow(true); + GLBE_PushOffsetShadow(true); model = e->model; surf = model->surfaces+model->firstmodelsurface; @@ -2345,7 +2378,7 @@ static void Sh_DrawBrushModelShadow(dlight_t *dl, entity_t *e) qglEnd(); } - BE_PushOffsetShadow(false); + GLBE_PushOffsetShadow(false); #endif } @@ -2367,9 +2400,9 @@ static void Sh_DrawStencilLightShadows(dlight_t *dl, qbyte *lvis, qbyte *vvis, q { switch (qrenderer) { -#ifdef D3DQUAKE - case QR_DIRECT3D: - D3DBE_RenderShadowBuffer(sm->numverts, sm->d3d_vbuffer, sm->numindicies, sm->d3d_ibuffer); +#ifdef D3D9QUAKE + case QR_DIRECT3D9: + D3D9BE_RenderShadowBuffer(sm->numverts, sm->d3d_vbuffer, sm->numindicies, sm->d3d_ibuffer); break; #endif #ifdef GLQUAKE @@ -2654,8 +2687,8 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis) } break; #endif -#ifdef D3DQUAKE - case QR_DIRECT3D: +#ifdef D3D9QUAKE + case QR_DIRECT3D9: sref = (1<<8)-1; sref/=2; @@ -2663,7 +2696,7 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis) IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_STENCIL, D3DCOLOR_XRGB(0, 0, 0), 1.0f, sref); /*set up 2-sided stenciling*/ - D3DBE_Cull(0); + D3D9BE_Cull(0); IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_STENCILENABLE, true); IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_STENCILFUNC, D3DCMP_ALWAYS); IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_TWOSIDEDSTENCILMODE, true); @@ -2753,17 +2786,8 @@ static void Sh_DrawShadowlessLight(dlight_t *dl, vec3_t colour, qbyte *vvis) return; //was culled. } - switch(qrenderer) - { -#ifdef GLQUAKE - case QR_OPENGL: - //so state doesn't linger - qglDisable(GL_SCISSOR_TEST); - if (qglDepthBoundsEXT) - qglDisable(GL_DEPTH_BOUNDS_TEST_EXT); - break; -#endif - } + //should we actually scissor here? there's not really much point I suppose. + Sh_ScissorOff(); bench.numlights++; @@ -2819,6 +2843,8 @@ void Sh_DrawCrepuscularLight(dlight_t *dl, float *colours) if (!gl_config.ext_framebuffer_objects) return; + //fixme: we should add an extra few pixels each side to the fbo, to avoid too much weirdness at screen edges. + if (!crepuscular_texture_id.num) { /*FIXME: requires npot*/ @@ -2832,7 +2858,7 @@ void Sh_DrawCrepuscularLight(dlight_t *dl, float *colours) "}\n" ); - crepuscular_texture_id = GL_AllocNewTexture("***crepusculartexture***", vid.pixelwidth, vid.pixelheight); + crepuscular_texture_id = GL_AllocNewTexture("***crepusculartexture***", vid.pixelwidth, vid.pixelheight, 0); GL_MTBind(0, GL_TEXTURE_2D, crepuscular_texture_id); qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vid.pixelwidth, vid.pixelheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -2841,6 +2867,8 @@ void Sh_DrawCrepuscularLight(dlight_t *dl, float *colours) qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); } + Sh_ScissorOff(); + GLBE_RenderToTexture(r_nulltex, r_nulltex, crepuscular_texture_id, false); BE_SelectMode(BEM_CREPUSCULAR); @@ -2947,8 +2975,8 @@ void Sh_DrawLights(qbyte *vis) }*/ break; #endif -#ifdef D3DQUAKE - case QR_DIRECT3D: +#ifdef D3D9QUAKE + case QR_DIRECT3D9: #ifdef GLQUAKE //the code still has a lot of ifdefs, so will crash if you try it in a merged build. //its not really usable in d3d-only builds either, so no great loss. @@ -3043,16 +3071,7 @@ void Sh_DrawLights(qbyte *vis) } } - switch(qrenderer) - { -#ifdef GLQUAKE - case QR_OPENGL: - qglDisable(GL_SCISSOR_TEST); - if (qglDepthBoundsEXT) - qglDisable(GL_DEPTH_BOUNDS_TEST_EXT); - break; -#endif - } + Sh_ScissorOff(); BE_SelectMode(BEM_STANDARD); diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index d6f543397..18ab5dd5b 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -39,6 +39,7 @@ void (APIENTRY *qglFlush) (void); void (APIENTRY *qglFrustum) (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); GLuint (APIENTRY *qglGenLists) (GLsizei range); void (APIENTRY *qglGenTextures) (GLsizei n, GLuint *textures); +void (APIENTRY *qglGetBooleanv) (GLenum pname, GLboolean *params); GLenum (APIENTRY *qglGetError) (void); void (APIENTRY *qglGetFloatv) (GLenum pname, GLfloat *params); void (APIENTRY *qglGetIntegerv) (GLenum pname, GLint *params); @@ -208,16 +209,16 @@ typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source, GLsizei length, const GLchar* message, GLvoid* userParam); -void (APIENTRY *qglDebugMessageControlARB)(enum source, - enum type, - enum severity, +void (APIENTRY *qglDebugMessageControlARB)(GLenum source, + GLenum type, + GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled); -void (APIENTRY *qglDebugMessageInsertARB)(enum source, - enum type, +void (APIENTRY *qglDebugMessageInsertARB)(GLenum source, + GLenum type, GLuint id, - enum severity, + GLenum severity, GLsizei length, const char* buf); void (APIENTRY *qglDebugMessageCallbackARB)(GLDEBUGPROCARB callback, @@ -320,13 +321,19 @@ qboolean GL_CheckExtension(char *extname) int i; cvar_t *v = Cvar_Get(va("gl_ext_%s", extname), "1", 0, "GL Extensions"); if (v && !v->ival) + { + Con_Printf("Cvar %s is 0\n", v->name); return false; + } if (gl_num_extensions && qglGetStringi) { for (i = 0; i < gl_num_extensions; i++) if (!strcmp(qglGetStringi(GL_EXTENSIONS, i), extname)) + { + Con_DPrintf("Detected GL extension %s\n", extname); return true; + } } if (!gl_extensions) @@ -1046,7 +1053,7 @@ qboolean GLSlang_GenerateIncludes(int maxstrings, int *strings, const GLchar *pr } if (!glsl_hdrs[i]) { - if (FS_LoadFile(incname, &inc) >= 0) + if (FS_LoadFile(incname, (void**)&inc) >= 0) { if (!GLSlang_GenerateIncludes(maxstrings, strings, prstrings, length, inc)) { @@ -1194,7 +1201,7 @@ GLhandleARB GLSlang_CreateShader (char *name, int ver, char **precompilerconstan this patch makes the submission more mainstream if ati can feck it up so much on a system with no real system memory issues, I wouldn't be surprised if embedded systems also mess it up. */ - char *combined; + GLcharARB *combined; int totallen = 1; for (i = 0; i < strings; i++) totallen += length[i]; @@ -1207,7 +1214,7 @@ GLhandleARB GLSlang_CreateShader (char *name, int ver, char **precompilerconstan totallen += length[i]; combined[totallen] = 0; } - qglShaderSourceARB(shader, 1, &combined, NULL); + qglShaderSourceARB(shader, 1, (const GLcharARB**)&combined, NULL); free(combined); } else @@ -1427,6 +1434,7 @@ void GL_Init(void *(*getglfunction) (char *name)) qglVertex3fv = (void *)getglcore("glVertex3fv"); qglViewport = (void *)getglcore("glViewport"); + qglGetBooleanv = (void *)getglcore("glGetBooleanv"); qglGetError = (void *)getglcore("glGetError"); qglDeleteTextures = (void *)getglcore("glDeleteTextures"); diff --git a/engine/gl/gl_vidnt.c b/engine/gl/gl_vidnt.c index d26e7c1ab..ce1ee05e4 100644 --- a/engine/gl/gl_vidnt.c +++ b/engine/gl/gl_vidnt.c @@ -96,7 +96,7 @@ extern cvar_t vid_wndalpha; typedef enum {MS_WINDOWED, MS_FULLSCREEN, MS_FULLDIB, MS_UNINIT} modestate_t; -BOOL bSetupPixelFormat(HDC hDC); +BOOL bSetupPixelFormat(HDC hDC, rendererstate_t *info); //qboolean VID_SetWindowedMode (int modenum); //qboolean VID_SetFullDIBMode (int modenum); @@ -631,6 +631,9 @@ qboolean VID_SetWindowedMode (rendererstate_t *info) return false; } + SendMessage (dibwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon); + SendMessage (dibwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon); + if (!sys_parentwindow) { #ifdef WS_EX_LAYERED @@ -702,8 +705,7 @@ qboolean VID_SetWindowedMode (rendererstate_t *info) mainwindow = dibwindow; vid_isfullscreen=false; - SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon); - SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon); + CL_UpdateWindowTitle(); return true; } @@ -783,6 +785,9 @@ qboolean VID_SetFullDIBMode (rendererstate_t *info) if (!dibwindow) Sys_Error ("Couldn't create DIB window"); + SendMessage (dibwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon); + SendMessage (dibwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon); + ShowWindow (dibwindow, SW_SHOWDEFAULT); UpdateWindow (dibwindow); @@ -827,9 +832,6 @@ qboolean VID_SetFullDIBMode (rendererstate_t *info) mainwindow = dibwindow; - SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon); - SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon); - return true; } @@ -1094,7 +1096,7 @@ qboolean VID_AttachGL (rendererstate_t *info) { maindc = GetDC(mainwindow); TRACE(("dbg: VID_AttachGL: bSetupPixelFormat\n")); - if (bSetupPixelFormat(maindc)) + if (bSetupPixelFormat(maindc, info)) break; ReleaseDC(mainwindow, maindc); } @@ -1113,7 +1115,7 @@ qboolean VID_AttachGL (rendererstate_t *info) { maindc = GetDC(mainwindow); TRACE(("dbg: VID_AttachGL: bSetupPixelFormat\n")); - if (bSetupPixelFormat(maindc)) + if (bSetupPixelFormat(maindc, info)) break; ReleaseDC(mainwindow, maindc); } @@ -1243,6 +1245,14 @@ qboolean VID_AttachGL (rendererstate_t *info) TRACE(("dbg: VID_AttachGL: GL_Init\n")); GL_Init(getglfunc); + if (info->stereo) + { + GLboolean ster = false; + qglGetBooleanv(GL_STEREO, &ster); + if (!ster) + Con_Printf("Unable to create stereoscopic/quad-buffered OpenGL context. Please use a different stereoscopic method.\n"); + } + qwglChoosePixelFormatARB = getglfunc("wglChoosePixelFormatARB"); qwglSwapIntervalEXT = getglfunc("wglSwapIntervalEXT"); @@ -1488,15 +1498,16 @@ void GLVID_Shutdown (void) //========================================================================== -#define WGL_DRAW_TO_WINDOW_ARB 0x2001 -#define WGL_SUPPORT_OPENGL_ARB 0x2010 -#define WGL_ACCELERATION_ARB 0x2003 -#define WGL_FULL_ACCELERATION_ARB 0x2027 -#define WGL_COLOR_BITS_ARB 0x2014 -#define WGL_ALPHA_BITS_ARB 0x201B -#define WGL_DEPTH_BITS_ARB 0x2022 -#define WGL_STENCIL_BITS_ARB 0x2023 -#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_STEREO_ARB 0x2012 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_FULL_ACCELERATION_ARB 0x2027 qboolean shouldforcepixelformat; int forcepixelformat; @@ -1519,6 +1530,7 @@ BOOL CheckForcePixelFormat(rendererstate_t *info) WGL_DOUBLE_BUFFER_ARB,GL_TRUE, WGL_SAMPLE_BUFFERS_ARB,GL_TRUE, WGL_SAMPLES_ARB, info->multisample, // Check For 4x Multisampling + WGL_STEREO_ARB, info->stereo, 0,0}; TRACE(("dbg: bSetupPixelFormat: attempting wglChoosePixelFormatARB (multisample 4)\n")); @@ -1608,7 +1620,7 @@ void FixPaletteInDescriptor(HDC hDC, PIXELFORMATDESCRIPTOR *pfd) } } -BOOL bSetupPixelFormat(HDC hDC) +BOOL bSetupPixelFormat(HDC hDC, rendererstate_t *info) { static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd @@ -1639,6 +1651,11 @@ BOOL bSetupPixelFormat(HDC hDC) TRACE(("dbg: bSetupPixelFormat: ChoosePixelFormat\n")); + if (info->stereo) + pfd.dwFlags |= PFD_STEREO; + if (info->bpp == 15 || info->bpp == 16) + pfd.cColorBits = 16; + if (shouldforcepixelformat && qwglChoosePixelFormatARB) //the extra && is paranoia { shouldforcepixelformat = false; @@ -2066,13 +2083,15 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette) memset(&devmode, 0, sizeof(devmode)); + hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON1)); + /* Register the frame class */ wc.style = 0; wc.lpfnWndProc = (WNDPROC)GLMainWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = global_hInstance; - wc.hIcon = 0; + wc.hIcon = hIcon; wc.hCursor = LoadCursor (NULL,IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = 0; @@ -2081,8 +2100,6 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette) if (!RegisterClass (&wc)) //this isn't really fatal, we'll let the CreateWindow fail instead. MessageBox(NULL, "RegisterClass failed", "GAH", 0); - hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON1)); - vid_initialized = false; vid_initializing = true; diff --git a/engine/gl/r_bishaders.h b/engine/gl/r_bishaders.h index 0e4285309..fd7fbd517 100644 --- a/engine/gl/r_bishaders.h +++ b/engine/gl/r_bishaders.h @@ -63,7 +63,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "ntc.t = tc.t + sin(tc.s+e_time)*0.125;\n" //generate the two wave patterns from the normalmap -"n = (texture2D(s_t1, TXSCALE*tc + vec2(e_time*0.1, 0)).xyz);\n" +"n = (texture2D(s_t1, TXSCALE*tc + vec2(e_time*0.1, 0.0)).xyz);\n" "n += (texture2D(s_t1, TXSCALE*tc - vec2(0, e_time*0.097)).xyz);\n" "n -= 1.0 - 4.0/256.0;\n" @@ -312,11 +312,12 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND //beware that a few things use this, including apparently fonts and bloom rescaling. //its really not meant to do anything special. +"varying vec2 tc;\n" +"varying vec4 vc;\n" + "#ifdef VERTEX_SHADER\n" "attribute vec2 v_texcoord;\n" "attribute vec4 v_colour;\n" -"varying vec2 tc;\n" -"varying vec4 vc;\n" "void main ()\n" "{\n" "tc = v_texcoord;\n" @@ -326,8 +327,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#endif\n" "#ifdef FRAGMENT_SHADER\n" "uniform sampler2D s_t0;\n" -"in vec2 tc;\n" -"varying vec4 vc;\n" "void main ()\n" "{\n" "gl_FragColor = texture2D(s_t0, tc) * vc;\n" diff --git a/engine/gl/shader.h b/engine/gl/shader.h index ca8b5a45c..68e583c1d 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -113,23 +113,23 @@ enum #define SBITS_BLEND_BITS (SBITS_SRCBLEND_BITS|SBITS_DSTBLEND_BITS) + SBITS_MASK_RED = 0x00000100, + SBITS_MASK_GREEN = 0x00000200, + SBITS_MASK_BLUE = 0x00000400, + SBITS_MASK_ALPHA = 0x00000800, +#define SBITS_MASK_BITS 0x00000f00 + SBITS_ATEST_NONE = 0x00000000, - SBITS_ATEST_GT0 = 0x00000100, - SBITS_ATEST_LT128 = 0x00000200, - SBITS_ATEST_GE128 = 0x00000300, -#define SBITS_ATEST_BITS 0x00000f00 + SBITS_ATEST_GT0 = 0x00001000, + SBITS_ATEST_LT128 = 0x00002000, + SBITS_ATEST_GE128 = 0x00003000, +#define SBITS_ATEST_BITS 0x0000f000 - SBITS_MISC_DEPTHWRITE = 0x00001000, - SBITS_MISC_NODEPTHTEST = 0x00002000, - SBITS_MISC_DEPTHEQUALONLY = 0x00004000, - SBITS_MISC_DEPTHCLOSERONLY = 0x00008000, -#define SBITS_MISC_BITS 0x0000f000 - - SBITS_MASK_RED = 0x00010000, - SBITS_MASK_GREEN = 0x00020000, - SBITS_MASK_BLUE = 0x00040000, - SBITS_MASK_ALPHA = 0x00080000, -#define SBITS_MASK_BITS 0x000f0000 + SBITS_MISC_DEPTHWRITE = 0x00010000, + SBITS_MISC_NODEPTHTEST = 0x00020000, + SBITS_MISC_DEPTHEQUALONLY = 0x00040000, + SBITS_MISC_DEPTHCLOSERONLY = 0x00080000, +#define SBITS_MISC_BITS 0x000f0000 SBITS_TRUFORM = 0x00100000, }; @@ -239,8 +239,9 @@ typedef struct shaderpass_s { } texgen; enum { - SHADER_PASS_NOMIPMAP = 1<<1, - SHADER_PASS_CLAMP = 1<<2, + SHADER_PASS_CLAMP = 1<<0, //needed for d3d's sampler states, infects image flags + SHADER_PASS_NEAREST = 1<<1, //needed for d3d's sampler states, infects image flags + SHADER_PASS_NOMIPMAP = 1<<2, //infects image flags SHADER_PASS_NOCOLORARRAY = 1<< 3, //FIXME: remove these @@ -264,7 +265,7 @@ enum{ PERMUTATION_SPECULAR = 2, PERMUTATION_FULLBRIGHT = 4, PERMUTATION_UPPERLOWER = 8, - PERMUTATION_OFFSET = 16, + PERMUTATION_DELUXE = 16, PERMUTATION_SKELETAL = 32, PERMUTATION_FOG = 64, PERMUTATION_FRAMEBLEND = 128, @@ -366,6 +367,7 @@ union programhandle_u void *frag; void *ctabf; void *ctabv; + void *layout; } hlsl; #endif }; @@ -506,29 +508,30 @@ void GLBE_SelectEntity(entity_t *ent); void GLBE_SelectDLight(dlight_t *dl, vec3_t colour); void GLBE_SubmitMeshes (qboolean drawworld, int start, int stop); #endif -#ifdef D3DQUAKE -void D3DBE_Init(void); -void D3DBE_SelectMode(backendmode_t mode); -void D3DBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **mesh, vbo_t *vbo, texnums_t *texnums, unsigned int beflags); -void D3DBE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums, unsigned int beflags); -void D3DBE_SubmitBatch(batch_t *batch); -batch_t *D3DBE_GetTempBatch(void); -void D3DBE_GenBrushModelVBO(model_t *mod); -void D3DBE_ClearVBO(vbo_t *vbo); -void D3DBE_UploadAllLightmaps(void); -void D3DBE_DrawWorld (qboolean drawworld, qbyte *vis); -qboolean D3DBE_LightCullModel(vec3_t org, model_t *model); -void D3DBE_SelectEntity(entity_t *ent); -void D3DBE_SelectDLight(dlight_t *dl, vec3_t colour); - -qboolean D3DShader_CreateProgram (program_t *prog, int permu, char **precompilerconstants, char *vert, char *frag); -int D3DShader_FindUniform(union programhandle_u *h, int type, char *name); -void D3DShader_Init(void); -void D3DBE_Reset(qboolean before); - - +#ifdef D3D9QUAKE +void D3D9BE_Init(void); +void D3D9BE_Shutdown(void); +void D3D9BE_SelectMode(backendmode_t mode); +void D3D9BE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **mesh, vbo_t *vbo, texnums_t *texnums, unsigned int beflags); +void D3D9BE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums, unsigned int beflags); +void D3D9BE_SubmitBatch(batch_t *batch); +batch_t *D3D9BE_GetTempBatch(void); +void D3D9BE_GenBrushModelVBO(model_t *mod); +void D3D9BE_ClearVBO(vbo_t *vbo); +void D3D9BE_UploadAllLightmaps(void); +void D3D9BE_DrawWorld (qboolean drawworld, qbyte *vis); +qboolean D3D9BE_LightCullModel(vec3_t org, model_t *model); +void D3D9BE_SelectEntity(entity_t *ent); +void D3D9BE_SelectDLight(dlight_t *dl, vec3_t colour); +qboolean D3D9Shader_CreateProgram (program_t *prog, int permu, char **precompilerconstants, char *vert, char *frag); +int D3D9Shader_FindUniform(union programhandle_u *h, int type, char *name); +void D3D9Shader_Init(void); +void D3D9BE_Reset(qboolean before); +#endif +#ifdef D3D11QUAKE void D3D11BE_Init(void); +void D3D11BE_Shutdown(void); void D3D11BE_SelectMode(backendmode_t mode); void D3D11BE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **mesh, vbo_t *vbo, texnums_t *texnums, unsigned int beflags); void D3D11BE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums, unsigned int beflags); @@ -537,15 +540,17 @@ batch_t *D3D11BE_GetTempBatch(void); void D3D11BE_GenBrushModelVBO(model_t *mod); void D3D11BE_ClearVBO(vbo_t *vbo); void D3D11BE_UploadAllLightmaps(void); -void D3D11BE_DrawWorld (qbyte *vis); +void D3D11BE_DrawWorld (qboolean drawworld, qbyte *vis); qboolean D3D11BE_LightCullModel(vec3_t org, model_t *model); void D3D11BE_SelectEntity(entity_t *ent); void D3D11BE_SelectDLight(dlight_t *dl, vec3_t colour); -qboolean D3D11Shader_CreateProgram (program_t *prog, int permu, char **precompilerconstants, char *vert, char *frag); +qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, int permu, char **precompilerconstants, char *vert, char *frag); int D3D11Shader_FindUniform(union programhandle_u *h, int type, char *name); void D3D11Shader_Init(void); void D3D11BE_Reset(qboolean before); +void D3D11BE_SetupViewCBuffer(void); +void D3D11_UploadLightmap(lightmapinfo_t *lm); #endif //Asks the backend to invoke DrawMeshChain for each surface, and to upload lightmaps as required @@ -555,20 +560,22 @@ void BE_DrawNonWorld (void); void BE_GenerateProgram(shader_t *shader); #ifdef RTLIGHTS -void BE_PushOffsetShadow(qboolean foobar); +// +void GLBE_PushOffsetShadow(qboolean foobar); //sets up gl for depth-only FIXME -void BE_SetupForShadowMap(texid_t shadowmaptex); +void GLBE_SetupForShadowMap(texid_t shadowmaptex); //Called from shadowmapping code into backend void GLBE_BaseEntTextures(void); -void D3DBE_BaseEntTextures(void); +void D3D9BE_BaseEntTextures(void); //prebuilds shadow volumes void Sh_PreGenerateLights(void); //Draws lights, called from the backend void Sh_DrawLights(qbyte *vis); void SH_FreeShadowMesh(struct shadowmesh_s *sm); +//frees all memory void Sh_Shutdown(void); -//Draws the depth of ents in the world near the current light -void BE_BaseEntShadowDepth(void); +//resize any textures to match new screen resize +void Sh_Reset(void); #endif struct shader_field_names_s diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c index 366986159..1719277f6 100644 --- a/engine/qclib/initlib.c +++ b/engine/qclib/initlib.c @@ -870,7 +870,7 @@ char *ASMCALL PR_StringToNative (progfuncs_t *progfuncs, string_t str) } -string_t PR_AllocTempString (progfuncs_t *progfuncs, char *str) +string_t PR_AllocTempString (progfuncs_t *progfuncs, const char *str) { char **ntable; int newmax; diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index 292e764bd..9a750dcbc 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -110,7 +110,7 @@ struct edict_s *ED_Alloc (progfuncs_t *progfuncs) char *buf; buf = progfuncs->save_ents(progfuncs, NULL, &size, 0); progfuncs->parms->WriteFile("edalloc.dump", buf, size); - Sys_Error ("ED_Alloc: no free edicts"); + Sys_Error ("ED_Alloc: no free edicts (max is %i)", sv_num_edicts); } } diff --git a/engine/qclib/progslib.h b/engine/qclib/progslib.h index ae36e1ee7..543f64ab1 100644 --- a/engine/qclib/progslib.h +++ b/engine/qclib/progslib.h @@ -128,7 +128,7 @@ struct progfuncs_s { char *tempstringbase; //for engine's use. Store your base tempstring pointer here. int tempstringnum; //for engine's use. - string_t (*TempString) (progfuncs_t *prinst, char *str); + string_t (*TempString) (progfuncs_t *prinst, const char *str); string_t (*StringToProgs) (progfuncs_t *prinst, char *str); char *(ASMCALL *StringToNative) (progfuncs_t *prinst, string_t str); diff --git a/engine/server/net_preparse.c b/engine/server/net_preparse.c index baf46f4a9..caa9c0283 100644 --- a/engine/server/net_preparse.c +++ b/engine/server/net_preparse.c @@ -947,9 +947,9 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) case svcdp_skybox: protocollen = 2;//it's just a string break; - case svc_updatestat: //insta fixup - data = svc_updatestatlong; //ho hum... let it through (should check size later.) - protocollen = 5; + case svcnq_updatestatlong: //insta fixup + data = svcqw_updatestatlong; //ho hum... let it through (should check size later.) + protocollen = 6; break; case svc_stufftext: case svc_centerprint: @@ -1436,7 +1436,7 @@ void NPP_QWFlush(void) if (cl->zquake_extensions & Z_EXT_SERVERTIME) { ClientReliableCheckBlock(cl, 6); - ClientReliableWrite_Byte(cl, svc_updatestatlong); + ClientReliableWrite_Byte(cl, svcqw_updatestatlong); ClientReliableWrite_Byte(cl, STAT_TIME); ClientReliableWrite_Long(cl, (int)(sv.world.physicstime * 1000)); cl->nextservertimeupdate = sv.world.physicstime+10; @@ -1773,7 +1773,7 @@ void NPP_QWWriteByte(int dest, qbyte data) //replacement write func (nq to qw) protocollen = 1; nullterms=1; break; - case svc_updatestat: + case svcqw_updatestatbyte: protocollen = 3; break; case svc_updateping: @@ -1787,7 +1787,7 @@ void NPP_QWWriteByte(int dest, qbyte data) //replacement write func (nq to qw) protocollen = 6; nullterms = 1; break; - case svc_updatestatlong: + case svcqw_updatestatlong: protocollen = 6; break; case svc_setpause: diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index d4a8c5f3b..3d8200ded 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -59,7 +59,7 @@ cvar_t pr_imitatemvdsv = CVARF("pr_imitatemvdsv", "0", CVAR_LATCH); cvar_t pr_fixbrokenqccarrays = CVARF("pr_fixbrokenqccarrays", "1", CVAR_LATCH); /*other stuff*/ -cvar_t pr_maxedicts = CVARF("pr_maxedicts", "2048", CVAR_LATCH); +cvar_t pr_maxedicts = CVARAF("pr_maxedicts", "8192", "max_edicts", CVAR_LATCH); cvar_t pr_no_playerphysics = CVARF("pr_no_playerphysics", "0", CVAR_LATCH); cvar_t pr_no_parsecommand = CVARF("pr_no_parsecommand", "0", 0); @@ -574,6 +574,7 @@ void Q_SetProgsParms(qboolean forcompiler) void PR_Deinit(void) { + int i; #ifdef USEODE World_ODE_End(&sv.world); #endif @@ -590,6 +591,12 @@ void PR_Deinit(void) CloseProgs(svprogfuncs); Z_FreeTags(Z_QC_TAG); + + for (i = 0; i < MAX_LIGHTSTYLES; i++) + { + BZ_Free(sv.strings.lightstyles[i]); + sv.strings.lightstyles[i] = NULL; + } } #ifdef TEXTEDITOR Editor_ProgsKilled(svprogfuncs); @@ -2363,50 +2370,6 @@ static void QCBUILTIN PF_h2set_puzzle_model (progfuncs_t *prinst, struct globalv PF_setmodel_Internal(prinst, e, fullname); } -static void QCBUILTIN PF_frameforname (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - unsigned int modelindex = G_FLOAT(OFS_PARM0); - char *str = PF_VarString(prinst, 1, pr_globals); - model_t *mod = SVPR_GetCModel(&sv.world, modelindex); - - if (mod && Mod_FrameForName) - G_FLOAT(OFS_RETURN) = Mod_FrameForName(mod, str); - else - G_FLOAT(OFS_RETURN) = -1; -} -static void QCBUILTIN PF_frameduration (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - unsigned int modelindex = G_FLOAT(OFS_PARM0); - unsigned int framenum = G_FLOAT(OFS_PARM1); - model_t *mod; - - if (modelindex >= MAX_MODELS) - G_FLOAT(OFS_RETURN) = 0; - else - { - mod = SVPR_GetCModel(&sv.world, modelindex); - - if (mod && Mod_GetFrameDuration) - G_FLOAT(OFS_RETURN) = Mod_GetFrameDuration(mod, framenum); - else - G_FLOAT(OFS_RETURN) = 0; - } -} -static void QCBUILTIN PF_skinforname (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ -#ifndef SERVERONLY - unsigned int modelindex = G_FLOAT(OFS_PARM0); - char *str = PF_VarString(prinst, 1, pr_globals); - model_t *mod = SVPR_GetCModel(&sv.world, modelindex); - - - if (mod && Mod_SkinForName) - G_FLOAT(OFS_RETURN) = Mod_SkinForName(mod, str); - else -#endif - G_FLOAT(OFS_RETURN) = -1; -} - /* ================= PF_bprint @@ -3659,7 +3622,7 @@ int PF_precache_model_Internal (progfuncs_t *prinst, char *s, qboolean queryonly if (s[0] <= ' ') { - Con_Printf ("precache_model: empty string\n"); + Con_DPrintf ("precache_model: empty string\n"); return 0; } @@ -3920,18 +3883,10 @@ void QCBUILTIN PF_applylightstyle(int style, char *val, int col) // change the string in sv - if (!svprogfuncs) - { - if (sv.strings.lightstyles[style]) - BZ_Free(sv.strings.lightstyles[style]); - sv.strings.lightstyles[style] = BZ_Malloc(strlen(val)+1); - } - else - { - if (sv.strings.lightstyles[style]) - PR_AddressableFree(svprogfuncs, sv.strings.lightstyles[style]); - sv.strings.lightstyles[style] = PR_AddressableAlloc(svprogfuncs, strlen(val)+1); - } + if (sv.strings.lightstyles[style]) + BZ_Free(sv.strings.lightstyles[style]); + sv.strings.lightstyles[style] = BZ_Malloc(strlen(val)+1); + strcpy(sv.strings.lightstyles[style], val); // sv.lightstyles[style] = val; #ifdef PEXT_LIGHTSTYLECOL @@ -7828,7 +7783,7 @@ static void QCBUILTIN PF_te_particlerain(progfuncs_t *prinst, struct globalvars_ MSG_WriteCoord(&sv.multicast, velocity[1]); MSG_WriteCoord(&sv.multicast, velocity[2]); // count - MSG_WriteShort(&sv.multicast, max(count, 65535)); + MSG_WriteShort(&sv.multicast, min(count, 65535)); // colour MSG_WriteByte(&sv.multicast, colour); @@ -7848,7 +7803,7 @@ static void QCBUILTIN PF_te_particlerain(progfuncs_t *prinst, struct globalvars_ MSG_WriteCoord(&sv.nqmulticast, velocity[1]); MSG_WriteCoord(&sv.nqmulticast, velocity[2]); // count - MSG_WriteShort(&sv.nqmulticast, max(count, 65535)); + MSG_WriteShort(&sv.nqmulticast, min(count, 65535)); // colour MSG_WriteByte(&sv.nqmulticast, colour); #endif @@ -7882,7 +7837,7 @@ static void QCBUILTIN PF_te_particlesnow(progfuncs_t *prinst, struct globalvars_ MSG_WriteCoord(&sv.multicast, velocity[1]); MSG_WriteCoord(&sv.multicast, velocity[2]); // count - MSG_WriteShort(&sv.multicast, max(count, 65535)); + MSG_WriteShort(&sv.multicast, min(count, 65535)); // colour MSG_WriteByte(&sv.multicast, colour); @@ -7902,7 +7857,7 @@ static void QCBUILTIN PF_te_particlesnow(progfuncs_t *prinst, struct globalvars_ MSG_WriteCoord(&sv.nqmulticast, velocity[1]); MSG_WriteCoord(&sv.nqmulticast, velocity[2]); // count - MSG_WriteShort(&sv.nqmulticast, max(count, 65535)); + MSG_WriteShort(&sv.nqmulticast, min(count, 65535)); // colour MSG_WriteByte(&sv.nqmulticast, colour); #endif @@ -8972,12 +8927,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"skel_ragupdate", PF_skel_ragedit, 0, 0, 0, 281, "float(float skel, string dollname, float parentskel, vector trans, vector fwd, vector rt, vector up)" NYI}, // (FTE_CSQC_RAGDOLL) {"skel_mmap", PF_skel_mmap, 0, 0, 0, 282, "float*(float skel)"},// (FTE_QC_RAGDOLL) {"skel_set_bone_world",PF_skel_set_bone_world,0,0, 0, 283, "void(entity ent, float bonenum, vector org, optional vector angorfwd, optional vector right, optional vector up)"}, - - {"memalloc", PF_memalloc, 0, 0, 0, 384, "void*(int size)"}, - {"memfree", PF_memfree, 0, 0, 0, 385, "void(void *ptr)"}, - {"memcpy", PF_memcpy, 0, 0, 0, 386, "void(void *dst, void *src, int size)"}, - {"memset", PF_memset, 0, 0, 0, 387, "void(void *dst, int val, int size)"}, - + {"frametoname", PF_frametoname, 0, 0, 0, 284, "string(float modidx, float framenum)"}, + {"skintoname", PF_skintoname, 0, 0, 0, 285, "string(float modidx, float skin)"}, // {"cvar_setlatch", PF_cvar_setlatch, 0, 0, 0, 284, "void(string cvarname, optional string value)"}, //72 @@ -9078,6 +9029,12 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"particleeffectquery",PF_Fixme,0, 0, 0, 374, "string(float efnum, float body)"}, //END EXT_CSQC + {"memalloc", PF_memalloc, 0, 0, 0, 384, "void*(int size)"}, + {"memfree", PF_memfree, 0, 0, 0, 385, "void(void *ptr)"}, + {"memcpy", PF_memcpy, 0, 0, 0, 386, "void(void *dst, void *src, int size)"}, + {"memset", PF_memset, 0, 0, 0, 387, "void(void *dst, int val, int size)"}, + + //end fte extras //DP extras @@ -9305,8 +9262,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs //VM_SV_getextresponse, // #624 string getextresponse(void) {"sprintf", PF_sprintf, 0, 0, 0, 627, "string(...)"}, -// {"getsurfacenumpoints",VM_getsurfacenumtriangles,0,0, 0, 628, "float(entity e, float s)" STUB}, -// {"getsurfacepoint",VM_getsurfacenumtriangles,0,0, 0, 629, "vector(entity e, float s, float n)" STUB}, + {"getsurfacenumtriangles",PF_getsurfacenumtriangles,0,0, 0, 628, "float(entity e, float s)"}, + {"getsurfacetriangle",PF_getsurfacetriangle,0,0, 0, 629, "vector(entity e, float s, float n)"}, //VM_digest_hex, // #639 diff --git a/engine/server/savegame.c b/engine/server/savegame.c index 9ef54e079..a5c241863 100644 --- a/engine/server/savegame.c +++ b/engine/server/savegame.c @@ -529,6 +529,7 @@ qboolean SV_LoadLevelCache(char *savename, char *level, char *startspot, qboolea gametype_e gametype; levelcache_t *cache; + int numstyles; if (isloadgame) { @@ -644,7 +645,8 @@ qboolean SV_LoadLevelCache(char *savename, char *level, char *startspot, qboolea // load the light styles VFS_GETS(f, str, sizeof(str)); - if (atoi(str) != MAX_LIGHTSTYLES) + numstyles = atoi(str); + if (numstyles > MAX_LIGHTSTYLES) { VFS_CLOSE (f); Con_Printf ("load failed - invalid number of lightstyles\n"); @@ -663,14 +665,24 @@ qboolean SV_LoadLevelCache(char *savename, char *level, char *startspot, qboolea PR_InitEnts(svprogfuncs, sv.world.max_edicts); } - for (i=0 ; idpflags & RENDER_STEP) bits |= NQU_NOLERP; // don't mess up the step animation - if (baseline->colormap != ent->colormap && ent->colormap>=0) + if (baseline->colormap != ent->colormap) bits |= NQU_COLORMAP; if (baseline->skinnum != ent->skinnum) @@ -3360,7 +3360,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore { if (client->fteprotocolextensions & PEXT_ACCURATETIMINGS && sv.world.physicstime - client->nextservertimeupdate > 0) { //the fte pext causes the server to send out accurate timings, allowing for perfect interpolation. - MSG_WriteByte (msg, svc_updatestatlong); + MSG_WriteByte (msg, svcqw_updatestatlong); MSG_WriteByte (msg, STAT_TIME); MSG_WriteLong (msg, (int)(sv.world.physicstime * 1000)); @@ -3368,7 +3368,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore } else if (client->zquake_extensions & Z_EXT_SERVERTIME && sv.world.physicstime - client->nextservertimeupdate > 0) { //the zquake ext causes the server to send out peridoic timings, allowing for moderatly accurate game time. - MSG_WriteByte (msg, svc_updatestatlong); + MSG_WriteByte (msg, svcqw_updatestatlong); MSG_WriteByte (msg, STAT_TIME); MSG_WriteLong (msg, (int)(sv.world.physicstime * 1000)); diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 1ab869abe..7be9c08ef 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -771,7 +771,8 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us //This fixes a bug where the server advertises cheats, the internal client connects, and doesn't think cheats are allowed. //this applies to a few other things too, but cheats is the only special one (because of the *) Q_strncpyz(cl.serverinfo, svs.info, sizeof(cl.serverinfo)); - CL_CheckServerInfo(); + if (!isDedicated) + CL_CheckServerInfo(); Cvar_ForceCallback(Cvar_FindVar("r_particlesdesc")); #endif diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index e54a8b850..cb134df8f 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -136,12 +136,12 @@ cvar_t sv_maxdrate = CVARAF("sv_maxdrate", "100000", "sv_maxdownloadrate", 0); cvar_t sv_minping = CVARF("sv_minping", "0", CVAR_SERVERINFO); -cvar_t sv_bigcoords = CVARF("sv_bigcoords", "", CVAR_SERVERINFO); -cvar_t sv_calcphs = CVAR("sv_calcphs", "2"); +cvar_t sv_bigcoords = CVARFD("sv_bigcoords", "", CVAR_SERVERINFO, "Uses floats for coordinates instead of 16bit values. Affects clients thusly:\nQW: enforces a mandatory protocol extension\nDP: enables DPP7 protocol support\nNQ: uses RMQ protocol (protocol 999)."); +cvar_t sv_calcphs = CVARFD("sv_calcphs", "2", CVAR_LATCH, "Enables culling of sound effects. 0=always skip phs. Sounds are globally broadcast. 1=always generate phs. Sounds are always culled. On large maps the phs will be dumped to disk. 2=On large single-player maps, generation of phs is skipped. Otherwise like option 1."); -cvar_t sv_cullplayers_trace = CVARF("sv_cullplayers_trace", "", CVAR_SERVERINFO); -cvar_t sv_cullentities_trace = CVARF("sv_cullentities_trace", "", CVAR_SERVERINFO); -cvar_t sv_phs = CVAR("sv_phs", "1"); +cvar_t sv_cullplayers_trace = CVARFD("sv_cullplayers_trace", "", CVAR_SERVERINFO, "Attempt to cull player entities using tracelines as an anti-wallhack."); +cvar_t sv_cullentities_trace = CVARFD("sv_cullentities_trace", "", CVAR_SERVERINFO, "Attempt to cull non-player entities using tracelines as an extreeme anti-wallhack."); +cvar_t sv_phs = CVARD("sv_phs", "1", "If 1, do not use the phs. It is generally better to use sv_calcphs instead, and leave this as 1."); cvar_t sv_resetparms = CVAR("sv_resetparms", "0"); cvar_t sv_pupglow = CVARF("sv_pupglow", "", CVAR_SERVERINFO); @@ -701,9 +701,9 @@ void PIN_LoadMessages(void) void PIN_SaveMessages(void) { pinnedmessages_t *p; - FILE *f; + vfsfile_t *f; - f = COM_WriteFileOpen("pinned.txt"); + f = FS_OpenVFS("pinned.txt", "wt", FS_GAMEONLY); if (!f) { Con_Printf("couldn't write anything\n"); @@ -711,9 +711,9 @@ void PIN_SaveMessages(void) } for (p = pinned; p; p = p->next) - fprintf(f, "%s\r\n\t%s\r\n\n", p->message, p->setby); + VFS_PRINTF(f, "%s\r\n\t%s\r\n\n", p->message, p->setby); - fclose(f); + VFS_CLOSE(f); } void PIN_DeleteOldestMessage(void) { @@ -4500,8 +4500,8 @@ void Master_Shutdown (void) } } -#define iswhite(c) (c == ' ' || c == INVIS_CHAR1 || c == INVIS_CHAR2 || c == INVIS_CHAR3) -#define isinvalid(c) (c == ':' || c == '\r' || c == '\n' || (unsigned char)(c) == '\xff') +#define iswhite(c) ((c) == ' ' || (unsigned char)(c) == (unsigned char)INVIS_CHAR1 || (unsigned char)(c) == (unsigned char)INVIS_CHAR2 || (unsigned char)(c) == (unsigned char)INVIS_CHAR3) +#define isinvalid(c) ((c) == ':' || (c) == '\r' || (c) == '\n' || (unsigned char)(c) == (unsigned char)0xff) //colon is so clients can't get confused while parsing chats //255 is so fuhquake/ezquake don't end up with nameless players diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index aa8a9fbcb..e969f8181 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -1929,6 +1929,7 @@ void WPhys_RunEntity (world_t *w, wedict_t *ent) case MOVETYPE_PHYSICS: if (WPhys_RunThink(w, ent)) World_LinkEdict (w, ent, true); + w->ode.hasodeents = true; break; default: // SV_Error ("SV_Physics: bad movetype %i on %s", (int)ent->v->movetype, PR_GetString(w->progs, ent->v->classname)); diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index fe7d05c93..cf53bb333 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -583,7 +583,14 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int leafnum = CM_PointLeafnum (sv.world.worldmodel, client->q2edict->s.origin); else #endif + { + if (svprogfuncs) + { + if (!((int)client->edict->xv->dimension_see & dimension_mask)) + continue; + } leafnum = CM_PointLeafnum (sv.world.worldmodel, client->edict->v->origin); + } cluster = CM_LeafCluster (sv.world.worldmodel, leafnum); area2 = CM_LeafArea (sv.world.worldmodel, leafnum); if (!CM_AreasConnected (sv.world.worldmodel, area1, area2)) @@ -1631,7 +1638,7 @@ void SV_UpdateClientStats (client_t *client, int pnum) if (statsi[i] != client->statsi[i]) { client->statsi[i] = statsi[i]; - ClientReliableWrite_Begin(client, svc_updatestat, 6); + ClientReliableWrite_Begin(client, svcnq_updatestatlong, 6); ClientReliableWrite_Byte(client, i); ClientReliableWrite_Long(client, statsi[i]); } @@ -1683,13 +1690,13 @@ void SV_UpdateClientStats (client_t *client, int pnum) { ClientReliableWrite_Begin(client->controller, svcfte_choosesplitclient, 5); ClientReliableWrite_Byte(client->controller, pnum); - ClientReliableWrite_Byte(client->controller, svc_updatestat); + ClientReliableWrite_Byte(client->controller, svcqw_updatestatbyte); ClientReliableWrite_Byte(client->controller, i); ClientReliableWrite_Byte(client->controller, statsf[i]); } else { - ClientReliableWrite_Begin(client, svc_updatestat, 3); + ClientReliableWrite_Begin(client, svcqw_updatestatbyte, 3); ClientReliableWrite_Byte(client, i); ClientReliableWrite_Byte(client, statsf[i]); } @@ -1733,13 +1740,13 @@ void SV_UpdateClientStats (client_t *client, int pnum) { ClientReliableWrite_Begin(client->controller, svcfte_choosesplitclient, 5); ClientReliableWrite_Byte(client->controller, pnum); - ClientReliableWrite_Byte(client->controller, svc_updatestat); + ClientReliableWrite_Byte(client->controller, svcqw_updatestatbyte); ClientReliableWrite_Byte(client->controller, i); ClientReliableWrite_Byte(client->controller, statsi[i]); } else { - ClientReliableWrite_Begin(client, svc_updatestat, 3); + ClientReliableWrite_Begin(client, svcqw_updatestatbyte, 3); ClientReliableWrite_Byte(client, i); ClientReliableWrite_Byte(client, statsi[i]); } @@ -1750,13 +1757,13 @@ void SV_UpdateClientStats (client_t *client, int pnum) { ClientReliableWrite_Begin(client->controller, svcfte_choosesplitclient, 8); ClientReliableWrite_Byte(client->controller, pnum); - ClientReliableWrite_Byte(client->controller, svc_updatestatlong); + ClientReliableWrite_Byte(client->controller, svcqw_updatestatlong); ClientReliableWrite_Byte(client->controller, i); ClientReliableWrite_Long(client->controller, statsi[i]); } else { - ClientReliableWrite_Begin(client, svc_updatestatlong, 6); + ClientReliableWrite_Begin(client, svcqw_updatestatlong, 6); ClientReliableWrite_Byte(client, i); ClientReliableWrite_Long(client, statsi[i]); } @@ -2479,7 +2486,7 @@ void SV_SendMVDMessage(void) if (statsf[j] - (float)(int)statsf[j] == 0 && statsf[j] >= 0 && statsf[j] <= 255) { dmsg = MVDWrite_Begin(dem_stats, i, 3); - MSG_WriteByte(dmsg, svc_updatestat); + MSG_WriteByte(dmsg, svcqw_updatestatbyte); MSG_WriteByte(dmsg, j); MSG_WriteByte(dmsg, statsf[j]); } @@ -2507,14 +2514,14 @@ void SV_SendMVDMessage(void) if (statsi[j] >=0 && statsi[j] <= 255) { dmsg = MVDWrite_Begin(dem_stats, i, 3); - MSG_WriteByte(dmsg, svc_updatestat); + MSG_WriteByte(dmsg, svcqw_updatestatbyte); MSG_WriteByte(dmsg, j); MSG_WriteByte(dmsg, statsi[j]); } else { dmsg = MVDWrite_Begin(dem_stats, i, 6); - MSG_WriteByte(dmsg, svc_updatestatlong); + MSG_WriteByte(dmsg, svcqw_updatestatlong); MSG_WriteByte(dmsg, j); MSG_WriteLong(dmsg, statsi[j]); } diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 8c0e6b5bd..d8999b766 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -51,6 +51,7 @@ cvar_t sv_cheatpc = CVAR("sv_cheatpc", "125"); cvar_t sv_cheatspeedchecktime = CVAR("sv_cheatspeedchecktime", "30"); cvar_t sv_playermodelchecks = CVAR("sv_playermodelchecks", "0"); cvar_t sv_ping_ignorepl = CVARD("sv_ping_ignorepl", "0", "If 1, ping times reported for players will ignore the effects of packetloss on ping times. 0 is slightly more honest, but less useful for connection diagnosis."); +cvar_t sv_protocol_nq = CVARD("sv_protocol_nq", "0", "Specifies the default protocol to use for new NQ clients. Supported values are\n0 = autodetect\n15 = vanilla\n666 = fitzquake\n999 = rmq protocol\nThe sv_bigcoords cvar forces upgrades as required."); cvar_t sv_cmdlikercon = SCVAR("sv_cmdlikercon", "0"); //set to 1 to allow a password of username:password instead of the correct rcon password. cvar_t cmd_allowaccess = SCVAR("cmd_allowaccess", "0"); //set to 1 to allow cmd to execute console commands on the server. @@ -276,7 +277,7 @@ void SV_New_f (void) if (svs.netprim.coordsize == 2) //we're not using float orgs on this level. ClientReliableWrite_Long (host_client, host_client->fteprotocolextensions&~PEXT_FLOATCOORDS); else - ClientReliableWrite_Long (host_client, host_client->fteprotocolextensions); + ClientReliableWrite_Long (host_client, host_client->fteprotocolextensions|PEXT_FLOATCOORDS); } if (host_client->fteprotocolextensions2)//let the client know { @@ -521,12 +522,13 @@ void SVNQ_New_f (void) case SCP_NETQUAKE: case SCP_FITZ666: SV_LogPlayer(host_client, "new (NQ)"); - if (sv.nqdatagram.prim.anglesize != 1 || sv.nqdatagram.prim.coordsize != 2) + if (sv.nqdatagram.prim.anglesize != 1 || sv.nqdatagram.prim.coordsize != 2 || sv_protocol_nq.ival == 666) { int rmqfl = ((sv.nqdatagram.prim.coordsize==4)?RMQFL_FLOATCOORD:0) | ((sv.nqdatagram.prim.anglesize==2)?RMQFL_SHORTANGLE:0); host_client->protocol = SCP_FITZ666; /*mneh, close enough, the rmq stuff is just modifiers*/ + host_client->datagram.maxsize = sizeof(host_client->datagram_buf); if (rmqfl) { @@ -542,6 +544,7 @@ void SVNQ_New_f (void) { host_client->protocol = SCP_NETQUAKE; MSG_WriteLong (&host_client->netchan.message, NQ_PROTOCOL_VERSION); + host_client->datagram.maxsize = MAX_NQDATAGRAM; } MSG_WriteByte (&host_client->netchan.message, (sv.allocated_client_slots>16)?16:sv.allocated_client_slots); break; @@ -1466,7 +1469,7 @@ void SVQW_PreSpawn_f (void) SV_Spawn_f ================== */ -void SV_Spawn_f (void) +void SVQW_Spawn_f (void) { int i; client_t *client, *split; @@ -1586,19 +1589,19 @@ void SV_Spawn_f (void) monsters_total = pr_global_struct->total_monsters; monsters_found = pr_global_struct->killed_monsters; } - ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6); + ClientReliableWrite_Begin (host_client, svcqw_updatestatlong, 6); ClientReliableWrite_Byte (host_client, STAT_TOTALSECRETS); ClientReliableWrite_Long (host_client, secret_total); - ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6); + ClientReliableWrite_Begin (host_client, svcqw_updatestatlong, 6); ClientReliableWrite_Byte (host_client, STAT_TOTALMONSTERS); ClientReliableWrite_Long (host_client, monsters_total); - ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6); + ClientReliableWrite_Begin (host_client, svcqw_updatestatlong, 6); ClientReliableWrite_Byte (host_client, STAT_SECRETS); ClientReliableWrite_Long (host_client, secret_found); - ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6); + ClientReliableWrite_Begin (host_client, svcqw_updatestatlong, 6); ClientReliableWrite_Byte (host_client, STAT_MONSTERS); ClientReliableWrite_Long (host_client, monsters_found); // get the client to check and download skins @@ -4458,19 +4461,19 @@ void SVNQ_Spawn_f (void) memset (host_client->statsf, 0, sizeof(host_client->statsf)); memset (host_client->statss, 0, sizeof(host_client->statss)); - ClientReliableWrite_Begin (host_client, svc_updatestat, 6); + ClientReliableWrite_Begin (host_client, svcnq_updatestatlong, 6); ClientReliableWrite_Byte (host_client, STAT_TOTALSECRETS); ClientReliableWrite_Long (host_client, pr_global_struct->total_secrets); - ClientReliableWrite_Begin (host_client, svc_updatestat, 6); + ClientReliableWrite_Begin (host_client, svcnq_updatestatlong, 6); ClientReliableWrite_Byte (host_client, STAT_TOTALMONSTERS); ClientReliableWrite_Long (host_client, pr_global_struct->total_monsters); - ClientReliableWrite_Begin (host_client, svc_updatestat, 6); + ClientReliableWrite_Begin (host_client, svcnq_updatestatlong, 6); ClientReliableWrite_Byte (host_client, STAT_SECRETS); ClientReliableWrite_Long (host_client, pr_global_struct->found_secrets); - ClientReliableWrite_Begin (host_client, svc_updatestat, 6); + ClientReliableWrite_Begin (host_client, svcnq_updatestatlong, 6); ClientReliableWrite_Byte (host_client, STAT_MONSTERS); ClientReliableWrite_Long (host_client, pr_global_struct->killed_monsters); @@ -4893,7 +4896,7 @@ ucmd_t ucmds[] = {"modellist", SV_Modellist_f, true}, {"soundlist", SV_Soundlist_f, true}, {"prespawn", SVQW_PreSpawn_f, true}, - {"spawn", SV_Spawn_f, true}, + {"spawn", SVQW_Spawn_f, true}, {"begin", SV_Begin_f, true}, /*ezquake warning*/ @@ -6920,6 +6923,7 @@ void SV_UserInit (void) Cvar_Register (&sv_realip_timeout, cvargroup_servercontrol); Cvar_Register (&sv_pushplayers, cvargroup_servercontrol); + Cvar_Register (&sv_protocol_nq, cvargroup_servercontrol); Cvar_Register (&sv_pure, cvargroup_servercontrol); Cvar_Register (&sv_floodprotect, cvargroup_servercontrol); diff --git a/engine/sndcodec/g711.c b/engine/sndcodec/g711.c deleted file mode 100644 index d2864cf68..000000000 --- a/engine/sndcodec/g711.c +++ /dev/null @@ -1,288 +0,0 @@ -#include "bothdefs.h" - -#ifdef VOICECHAT -/* - * This source code is a product of Sun Microsystems, Inc. and is provided - * for unrestricted use. Users may copy or modify this source code without - * charge. - * - * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING - * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * - * Sun source code is provided with no support and without any obligation on - * the part of Sun Microsystems, Inc. to assist in its use, correction, - * modification or enhancement. - * - * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE - * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE - * OR ANY PART THEREOF. - * - * In no event will Sun Microsystems, Inc. be liable for any lost revenue - * or profits or other special, indirect and consequential damages, even if - * Sun has been advised of the possibility of such damages. - * - * Sun Microsystems, Inc. - * 2550 Garcia Avenue - * Mountain View, California 94043 - */ - -/* - * g711.c - * - * u-law, A-law and linear PCM conversions. - */ -#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */ -#define QUANT_MASK (0xf) /* Quantization field mask. */ -#define NSEGS (8) /* Number of A-law segments. */ -#define SEG_SHIFT (4) /* Left shift for segment number. */ -#define SEG_MASK (0x70) /* Segment field mask. */ - -static short seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF, - 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF}; - -/* copy from CCITT G.711 specifications */ -unsigned char _u2a[128] = { /* u- to A-law conversions */ - 1, 1, 2, 2, 3, 3, 4, 4, - 5, 5, 6, 6, 7, 7, 8, 8, - 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, - 25, 27, 29, 31, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, - 46, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, - 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, - 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128}; - -unsigned char _a2u[128] = { /* A- to u-law conversions */ - 1, 3, 5, 7, 9, 11, 13, 15, - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, - 32, 32, 33, 33, 34, 34, 35, 35, - 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 48, 49, 49, - 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 64, - 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, 76, 77, 78, 79, 79, - 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127}; - -static int -search( - int val, - short *table, - int size) -{ - int i; - - for (i = 0; i < size; i++) { - if (val <= *table++) - return (i); - } - return (size); -} - -/* - * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law - * - * linear2alaw() accepts an 16-bit integer and encodes it as A-law data. - * - * Linear Input Code Compressed Code - * ------------------------ --------------- - * 0000000wxyza 000wxyz - * 0000001wxyza 001wxyz - * 000001wxyzab 010wxyz - * 00001wxyzabc 011wxyz - * 0001wxyzabcd 100wxyz - * 001wxyzabcde 101wxyz - * 01wxyzabcdef 110wxyz - * 1wxyzabcdefg 111wxyz - * - * For further information see John C. Bellamy's Digital Telephony, 1982, - * John Wiley & Sons, pps 98-111 and 472-476. - */ -unsigned char -linear2alaw( - int pcm_val) /* 2's complement (16-bit range) */ -{ - int mask; - int seg; - unsigned char aval; - - if (pcm_val >= 0) { - mask = 0xD5; /* sign (7th) bit = 1 */ - } else { - mask = 0x55; /* sign bit = 0 */ - pcm_val = -pcm_val - 8; - } - - /* Convert the scaled magnitude to segment number. */ - seg = search(pcm_val, seg_end, 8); - - /* Combine the sign, segment, and quantization bits. */ - - if (seg >= 8) /* out of range, return maximum value. */ - return (0x7F ^ mask); - else { - aval = seg << SEG_SHIFT; - if (seg < 2) - aval |= (pcm_val >> 4) & QUANT_MASK; - else - aval |= (pcm_val >> (seg + 3)) & QUANT_MASK; - return (aval ^ mask); - } -} - -/* - * alaw2linear() - Convert an A-law value to 16-bit linear PCM - * - */ -int -alaw2linear( - unsigned char a_val) -{ - int t; - int seg; - - a_val ^= 0x55; - - t = (a_val & QUANT_MASK) << 4; - seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT; - switch (seg) { - case 0: - t += 8; - break; - case 1: - t += 0x108; - break; - default: - t += 0x108; - t <<= seg - 1; - } - return ((a_val & SIGN_BIT) ? t : -t); -} - -#define BIAS (0x84) /* Bias for linear code. */ - -/* - * linear2ulaw() - Convert a linear PCM value to u-law - * - * In order to simplify the encoding process, the original linear magnitude - * is biased by adding 33 which shifts the encoding range from (0 - 8158) to - * (33 - 8191). The result can be seen in the following encoding table: - * - * Biased Linear Input Code Compressed Code - * ------------------------ --------------- - * 00000001wxyza 000wxyz - * 0000001wxyzab 001wxyz - * 000001wxyzabc 010wxyz - * 00001wxyzabcd 011wxyz - * 0001wxyzabcde 100wxyz - * 001wxyzabcdef 101wxyz - * 01wxyzabcdefg 110wxyz - * 1wxyzabcdefgh 111wxyz - * - * Each biased linear code has a leading 1 which identifies the segment - * number. The value of the segment number is equal to 7 minus the number - * of leading 0's. The quantization interval is directly available as the - * four bits wxyz. * The trailing bits (a - h) are ignored. - * - * Ordinarily the complement of the resulting code word is used for - * transmission, and so the code word is complemented before it is returned. - * - * For further information see John C. Bellamy's Digital Telephony, 1982, - * John Wiley & Sons, pps 98-111 and 472-476. - */ -unsigned char -linear2ulaw( - int pcm_val) /* 2's complement (16-bit range) */ -{ - int mask; - int seg; - unsigned char uval; - - /* Get the sign and the magnitude of the value. */ - if (pcm_val < 0) { - pcm_val = BIAS - pcm_val; - mask = 0x7F; - } else { - pcm_val += BIAS; - mask = 0xFF; - } - - /* Convert the scaled magnitude to segment number. */ - seg = search(pcm_val, seg_end, 8); - - /* - * Combine the sign, segment, quantization bits; - * and complement the code word. - */ - if (seg >= 8) /* out of range, return maximum value. */ - return (0x7F ^ mask); - else { - uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF); - return (uval ^ mask); - } - -} - -/* - * ulaw2linear() - Convert a u-law value to 16-bit linear PCM - * - * First, a biased linear code is derived from the code word. An unbiased - * output can then be obtained by subtracting 33 from the biased code. - * - * Note that this function expects to be passed the complement of the - * original code word. This is in keeping with ISDN conventions. - */ -int -ulaw2linear( - unsigned char u_val) -{ - int t; - - /* Complement to obtain normal u-law value. */ - u_val = ~u_val; - - /* - * Extract and bias the quantization bits. Then - * shift up by the segment number and subtract out the bias. - */ - t = ((u_val & QUANT_MASK) << 3) + BIAS; - t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; - - return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS)); -} - -/* A-law to u-law conversion */ -unsigned char -alaw2ulaw( - unsigned char aval) -{ - aval &= 0xff; - return ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) : - (0x7F ^ _a2u[aval ^ 0x55])); -} - -/* u-law to A-law conversion */ -unsigned char -ulaw2alaw( - unsigned char uval) -{ - uval &= 0xff; - return ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) : - (0x55 ^ (_u2a[0x7F ^ uval] - 1))); -} - -#endif diff --git a/engine/sndcodec/g721.c b/engine/sndcodec/g721.c deleted file mode 100644 index 0d6a9625d..000000000 --- a/engine/sndcodec/g721.c +++ /dev/null @@ -1,178 +0,0 @@ -#include "bothdefs.h" - -#ifdef VOICECHAT -/* - * This source code is a product of Sun Microsystems, Inc. and is provided - * for unrestricted use. Users may copy or modify this source code without - * charge. - * - * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING - * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * - * Sun source code is provided with no support and without any obligation on - * the part of Sun Microsystems, Inc. to assist in its use, correction, - * modification or enhancement. - * - * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE - * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE - * OR ANY PART THEREOF. - * - * In no event will Sun Microsystems, Inc. be liable for any lost revenue - * or profits or other special, indirect and consequential damages, even if - * Sun has been advised of the possibility of such damages. - * - * Sun Microsystems, Inc. - * 2550 Garcia Avenue - * Mountain View, California 94043 - */ - -/* - * g721.c - * - * Description: - * - * g721_encoder(), g721_decoder() - * - * These routines comprise an implementation of the CCITT G.721 ADPCM - * coding algorithm. Essentially, this implementation is identical to - * the bit level description except for a few deviations which - * take advantage of work station attributes, such as hardware 2's - * complement arithmetic and large memory. Specifically, certain time - * consuming operations such as multiplications are replaced - * with lookup tables and software 2's complement operations are - * replaced with hardware 2's complement. - * - * The deviation from the bit level specification (lookup tables) - * preserves the bit level performance specifications. - * - * As outlined in the G.721 Recommendation, the algorithm is broken - * down into modules. Each section of code below is preceded by - * the name of the module which it is implementing. - * - */ -#include "g72x.h" - -static short qtab_721[7] = {-124, 80, 178, 246, 300, 349, 400}; -/* - * Maps G.721 code word to reconstructed scale factor normalized log - * magnitude values. - */ -static short _dqlntab[16] = {-2048, 4, 135, 213, 273, 323, 373, 425, - 425, 373, 323, 273, 213, 135, 4, -2048}; - -/* Maps G.721 code word to log of scale factor multiplier. */ -static short _witab[16] = {-12, 18, 41, 64, 112, 198, 355, 1122, - 1122, 355, 198, 112, 64, 41, 18, -12}; -/* - * Maps G.721 code words to a set of values whose long and short - * term averages are computed and then compared to give an indication - * how stationary (steady state) the signal is. - */ -static short _fitab[16] = {0, 0, 0, 0x200, 0x200, 0x200, 0x600, 0xE00, - 0xE00, 0x600, 0x200, 0x200, 0x200, 0, 0, 0}; - -/* - * g721_encoder() - * - * Encodes the input vale of linear PCM, A-law or u-law data sl and returns - * the resulting code. -1 is returned for unknown input coding value. - */ -int -g721_encoder( - int sl, - int in_coding, - struct g72x_state *state_ptr) -{ - short sezi, se, sez; /* ACCUM */ - short d; /* SUBTA */ - short sr; /* ADDB */ - short y; /* MIX */ - short dqsez; /* ADDC */ - short dq, i; - - switch (in_coding) { /* linearize input sample to 14-bit PCM */ - case AUDIO_ENCODING_ALAW: - sl = alaw2linear((unsigned char)sl) >> 2; - break; - case AUDIO_ENCODING_ULAW: - sl = ulaw2linear((unsigned char)sl) >> 2; - break; - case AUDIO_ENCODING_LINEAR: - sl >>= 2; /* 14-bit dynamic range */ - break; - default: - return (-1); - } - - sezi = predictor_zero(state_ptr); - sez = sezi >> 1; - se = (sezi + predictor_pole(state_ptr)) >> 1; /* estimated signal */ - - d = sl - se; /* estimation difference */ - - /* quantize the prediction difference */ - y = step_size(state_ptr); /* quantizer step size */ - i = quantize(d, y, qtab_721, 7); /* i = ADPCM code */ - - dq = reconstruct(i & 8, _dqlntab[i], y); /* quantized est diff */ - - sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconst. signal */ - - dqsez = sr + sez - se; /* pole prediction diff. */ - - update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr); - - return (i); -} - -/* - * g721_decoder() - * - * Description: - * - * Decodes a 4-bit code of G.721 encoded data of i and - * returns the resulting linear PCM, A-law or u-law value. - * return -1 for unknown out_coding value. - */ -int -g721_decoder( - int i, - int out_coding, - struct g72x_state *state_ptr) -{ - short sezi, sei, sez, se; /* ACCUM */ - short y; /* MIX */ - short sr; /* ADDB */ - short dq; - short dqsez; - - i &= 0x0f; /* mask to get proper bits */ - sezi = predictor_zero(state_ptr); - sez = sezi >> 1; - sei = sezi + predictor_pole(state_ptr); - se = sei >> 1; /* se = estimated signal */ - - y = step_size(state_ptr); /* dynamic quantizer step size */ - - dq = reconstruct(i & 0x08, _dqlntab[i], y); /* quantized diff. */ - - sr = (dq < 0) ? (se - (dq & 0x3FFF)) : se + dq; /* reconst. signal */ - - dqsez = sr - se + sez; /* pole prediction diff. */ - - update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr); - - switch (out_coding) { - case AUDIO_ENCODING_ALAW: - return (tandem_adjust_alaw(sr, se, y, i, 8, qtab_721)); - case AUDIO_ENCODING_ULAW: - return (tandem_adjust_ulaw(sr, se, y, i, 8, qtab_721)); - case AUDIO_ENCODING_LINEAR: - return (sr << 2); /* sr was 14-bit dynamic range */ - default: - return (-1); - } -} - -#endif diff --git a/engine/sndcodec/g723_24.c b/engine/sndcodec/g723_24.c deleted file mode 100644 index 9863a9566..000000000 --- a/engine/sndcodec/g723_24.c +++ /dev/null @@ -1,163 +0,0 @@ -#include "bothdefs.h" - -#ifdef VOICECHAT -/* - * This source code is a product of Sun Microsystems, Inc. and is provided - * for unrestricted use. Users may copy or modify this source code without - * charge. - * - * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING - * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * - * Sun source code is provided with no support and without any obligation on - * the part of Sun Microsystems, Inc. to assist in its use, correction, - * modification or enhancement. - * - * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE - * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE - * OR ANY PART THEREOF. - * - * In no event will Sun Microsystems, Inc. be liable for any lost revenue - * or profits or other special, indirect and consequential damages, even if - * Sun has been advised of the possibility of such damages. - * - * Sun Microsystems, Inc. - * 2550 Garcia Avenue - * Mountain View, California 94043 - */ - -/* - * g723_24.c - * - * Description: - * - * g723_24_encoder(), g723_24_decoder() - * - * These routines comprise an implementation of the CCITT G.723 24 Kbps - * ADPCM coding algorithm. Essentially, this implementation is identical to - * the bit level description except for a few deviations which take advantage - * of workstation attributes, such as hardware 2's complement arithmetic. - * - */ -#include "g72x.h" - -/* - * Maps G.723_24 code word to reconstructed scale factor normalized log - * magnitude values. - */ -static short _dqlntab[8] = {-2048, 135, 273, 373, 373, 273, 135, -2048}; - -/* Maps G.723_24 code word to log of scale factor multiplier. */ -static short _witab[8] = {-128, 960, 4384, 18624, 18624, 4384, 960, -128}; - -/* - * Maps G.723_24 code words to a set of values whose long and short - * term averages are computed and then compared to give an indication - * how stationary (steady state) the signal is. - */ -static short _fitab[8] = {0, 0x200, 0x400, 0xE00, 0xE00, 0x400, 0x200, 0}; - -static short qtab_723_24[3] = {8, 218, 331}; - -/* - * g723_24_encoder() - * - * Encodes a linear PCM, A-law or u-law input sample and returns its 3-bit code. - * Returns -1 if invalid input coding value. - */ -int -g723_24_encoder( - int sl, - int in_coding, - struct g72x_state *state_ptr) -{ - short sei, sezi, se, sez; /* ACCUM */ - short d; /* SUBTA */ - short y; /* MIX */ - short sr; /* ADDB */ - short dqsez; /* ADDC */ - short dq, i; - - switch (in_coding) { /* linearize input sample to 14-bit PCM */ - case AUDIO_ENCODING_ALAW: - sl = alaw2linear((unsigned char)sl) >> 2; - break; - case AUDIO_ENCODING_ULAW: - sl = ulaw2linear((unsigned char)sl) >> 2; - break; - case AUDIO_ENCODING_LINEAR: - sl >>= 2; /* sl of 14-bit dynamic range */ - break; - default: - return (-1); - } - - sezi = predictor_zero(state_ptr); - sez = sezi >> 1; - sei = sezi + predictor_pole(state_ptr); - se = sei >> 1; /* se = estimated signal */ - - d = sl - se; /* d = estimation diff. */ - - /* quantize prediction difference d */ - y = step_size(state_ptr); /* quantizer step size */ - i = quantize(d, y, qtab_723_24, 3); /* i = ADPCM code */ - dq = reconstruct(i & 4, _dqlntab[i], y); /* quantized diff. */ - - sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconstructed signal */ - - dqsez = sr + sez - se; /* pole prediction diff. */ - - update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); - - return (i); -} - -/* - * g723_24_decoder() - * - * Decodes a 3-bit CCITT G.723_24 ADPCM code and returns - * the resulting 16-bit linear PCM, A-law or u-law sample value. - * -1 is returned if the output coding is unknown. - */ -int -g723_24_decoder( - int i, - int out_coding, - struct g72x_state *state_ptr) -{ - short sezi, sei, sez, se; /* ACCUM */ - short y; /* MIX */ - short sr; /* ADDB */ - short dq; - short dqsez; - - i &= 0x07; /* mask to get proper bits */ - sezi = predictor_zero(state_ptr); - sez = sezi >> 1; - sei = sezi + predictor_pole(state_ptr); - se = sei >> 1; /* se = estimated signal */ - - y = step_size(state_ptr); /* adaptive quantizer step size */ - dq = reconstruct(i & 0x04, _dqlntab[i], y); /* unquantize pred diff */ - - sr = (dq < 0) ? (se - (dq & 0x3FFF)) : (se + dq); /* reconst. signal */ - - dqsez = sr - se + sez; /* pole prediction diff. */ - - update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); - - switch (out_coding) { - case AUDIO_ENCODING_ALAW: - return (tandem_adjust_alaw(sr, se, y, i, 4, qtab_723_24)); - case AUDIO_ENCODING_ULAW: - return (tandem_adjust_ulaw(sr, se, y, i, 4, qtab_723_24)); - case AUDIO_ENCODING_LINEAR: - return (sr << 2); /* sr was of 14-bit dynamic range */ - default: - return (-1); - } -} - -#endif diff --git a/engine/sndcodec/g723_40.c b/engine/sndcodec/g723_40.c deleted file mode 100644 index 3786648dc..000000000 --- a/engine/sndcodec/g723_40.c +++ /dev/null @@ -1,183 +0,0 @@ -#include "bothdefs.h" - -#ifdef VOICECHAT -/* - * This source code is a product of Sun Microsystems, Inc. and is provided - * for unrestricted use. Users may copy or modify this source code without - * charge. - * - * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING - * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * - * Sun source code is provided with no support and without any obligation on - * the part of Sun Microsystems, Inc. to assist in its use, correction, - * modification or enhancement. - * - * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE - * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE - * OR ANY PART THEREOF. - * - * In no event will Sun Microsystems, Inc. be liable for any lost revenue - * or profits or other special, indirect and consequential damages, even if - * Sun has been advised of the possibility of such damages. - * - * Sun Microsystems, Inc. - * 2550 Garcia Avenue - * Mountain View, California 94043 - */ - -/* - * g723_40.c - * - * Description: - * - * g723_40_encoder(), g723_40_decoder() - * - * These routines comprise an implementation of the CCITT G.723 40Kbps - * ADPCM coding algorithm. Essentially, this implementation is identical to - * the bit level description except for a few deviations which - * take advantage of workstation attributes, such as hardware 2's - * complement arithmetic. - * - * The deviation from the bit level specification (lookup tables), - * preserves the bit level performance specifications. - * - * As outlined in the G.723 Recommendation, the algorithm is broken - * down into modules. Each section of code below is preceded by - * the name of the module which it is implementing. - * - */ -#include "g72x.h" - -/* - * Maps G.723_40 code word to ructeconstructed scale factor normalized log - * magnitude values. - */ -static short _dqlntab[32] = {-2048, -66, 28, 104, 169, 224, 274, 318, - 358, 395, 429, 459, 488, 514, 539, 566, - 566, 539, 514, 488, 459, 429, 395, 358, - 318, 274, 224, 169, 104, 28, -66, -2048}; - -/* Maps G.723_40 code word to log of scale factor multiplier. */ -static short _witab[32] = {448, 448, 768, 1248, 1280, 1312, 1856, 3200, - 4512, 5728, 7008, 8960, 11456, 14080, 16928, 22272, - 22272, 16928, 14080, 11456, 8960, 7008, 5728, 4512, - 3200, 1856, 1312, 1280, 1248, 768, 448, 448}; - -/* - * Maps G.723_40 code words to a set of values whose long and short - * term averages are computed and then compared to give an indication - * how stationary (steady state) the signal is. - */ -static short _fitab[32] = {0, 0, 0, 0, 0, 0x200, 0x200, 0x200, - 0x200, 0x200, 0x400, 0x600, 0x800, 0xA00, 0xC00, 0xC00, - 0xC00, 0xC00, 0xA00, 0x800, 0x600, 0x400, 0x200, 0x200, - 0x200, 0x200, 0x200, 0, 0, 0, 0, 0}; - -static short qtab_723_40[15] = {-122, -16, 68, 139, 198, 250, 298, 339, - 378, 413, 445, 475, 502, 528, 553}; - -/* - * g723_40_encoder() - * - * Encodes a 16-bit linear PCM, A-law or u-law input sample and retuens - * the resulting 5-bit CCITT G.723 40Kbps code. - * Returns -1 if the input coding value is invalid. - */ -int -g723_40_encoder( - int sl, - int in_coding, - struct g72x_state *state_ptr) -{ - short sei, sezi, se, sez; /* ACCUM */ - short d; /* SUBTA */ - short y; /* MIX */ - short sr; /* ADDB */ - short dqsez; /* ADDC */ - short dq, i; - - switch (in_coding) { /* linearize input sample to 14-bit PCM */ - case AUDIO_ENCODING_ALAW: - sl = alaw2linear((unsigned char)sl) >> 2; - break; - case AUDIO_ENCODING_ULAW: - sl = ulaw2linear((unsigned char)sl) >> 2; - break; - case AUDIO_ENCODING_LINEAR: - sl >>= 2; /* sl of 14-bit dynamic range */ - break; - default: - return (-1); - } - - sezi = predictor_zero(state_ptr); - sez = sezi >> 1; - sei = sezi + predictor_pole(state_ptr); - se = sei >> 1; /* se = estimated signal */ - - d = sl - se; /* d = estimation difference */ - - /* quantize prediction difference */ - y = step_size(state_ptr); /* adaptive quantizer step size */ - i = quantize(d, y, qtab_723_40, 15); /* i = ADPCM code */ - - dq = reconstruct(i & 0x10, _dqlntab[i], y); /* quantized diff */ - - sr = (dq < 0) ? se - (dq & 0x7FFF) : se + dq; /* reconstructed signal */ - - dqsez = sr + sez - se; /* dqsez = pole prediction diff. */ - - update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); - - return (i); -} - -/* - * g723_40_decoder() - * - * Decodes a 5-bit CCITT G.723 40Kbps code and returns - * the resulting 16-bit linear PCM, A-law or u-law sample value. - * -1 is returned if the output coding is unknown. - */ -int -g723_40_decoder( - int i, - int out_coding, - struct g72x_state *state_ptr) -{ - short sezi, sei, sez, se; /* ACCUM */ - short y; /* MIX */ - short sr; /* ADDB */ - short dq; - short dqsez; - - i &= 0x1f; /* mask to get proper bits */ - sezi = predictor_zero(state_ptr); - sez = sezi >> 1; - sei = sezi + predictor_pole(state_ptr); - se = sei >> 1; /* se = estimated signal */ - - y = step_size(state_ptr); /* adaptive quantizer step size */ - dq = reconstruct(i & 0x10, _dqlntab[i], y); /* estimation diff. */ - - sr = (dq < 0) ? (se - (dq & 0x7FFF)) : (se + dq); /* reconst. signal */ - - dqsez = sr - se + sez; /* pole prediction diff. */ - - update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); - - switch (out_coding) { - case AUDIO_ENCODING_ALAW: - return (tandem_adjust_alaw(sr, se, y, i, 0x10, qtab_723_40)); - case AUDIO_ENCODING_ULAW: - return (tandem_adjust_ulaw(sr, se, y, i, 0x10, qtab_723_40)); - case AUDIO_ENCODING_LINEAR: - return (sr << 2); /* sr was of 14-bit dynamic range */ - default: - return (-1); - } -} - -#endif diff --git a/engine/sndcodec/g72x.c b/engine/sndcodec/g72x.c deleted file mode 100644 index 36a693561..000000000 --- a/engine/sndcodec/g72x.c +++ /dev/null @@ -1,573 +0,0 @@ -#include "bothdefs.h" - -#ifdef VOICECHAT - -/* - * This source code is a product of Sun Microsystems, Inc. and is provided - * for unrestricted use. Users may copy or modify this source code without - * charge. - * - * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING - * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * - * Sun source code is provided with no support and without any obligation on - * the part of Sun Microsystems, Inc. to assist in its use, correction, - * modification or enhancement. - * - * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE - * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE - * OR ANY PART THEREOF. - * - * In no event will Sun Microsystems, Inc. be liable for any lost revenue - * or profits or other special, indirect and consequential damages, even if - * Sun has been advised of the possibility of such damages. - * - * Sun Microsystems, Inc. - * 2550 Garcia Avenue - * Mountain View, California 94043 - */ - -/* - * g72x.c - * - * Common routines for G.721 and G.723 conversions. - */ - -#include "g72x.h" -#include -#include - -static short power2[15] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, - 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000}; - -/* - * quan() - * - * quantizes the input val against the table of size short integers. - * It returns i if table[i - 1] <= val < table[i]. - * - * Using linear search for simple coding. - */ -static int -quan( - int val, - short *table, - int size) -{ - int i; - - for (i = 0; i < size; i++) - if (val < *table++) - break; - return (i); -} - -/* - * fmult() - * - * returns the integer product of the 14-bit integer "an" and - * "floating point" representation (4-bit exponent, 6-bit mantessa) "srn". - */ -static int -fmult( - int an, - int srn) -{ - short anmag, anexp, anmant; - short wanexp, wanmant; - short retval; - - anmag = (an > 0) ? an : ((-an) & 0x1FFF); - anexp = quan(anmag, power2, 15) - 6; - anmant = (anmag == 0) ? 32 : - (anexp >= 0) ? anmag >> anexp : anmag << -anexp; - wanexp = anexp + ((srn >> 6) & 0xF) - 13; - - wanmant = (anmant * (srn & 077) + 0x30) >> 4; - retval = (wanexp >= 0) ? ((wanmant << wanexp) & 0x7FFF) : - (wanmant >> -wanexp); - - return (((an ^ srn) < 0) ? -retval : retval); -} - -/* - * g72x_init_state() - * - * This routine initializes and/or resets the g72x_state structure - * pointed to by 'state_ptr'. - * All the initial state values are specified in the CCITT G.721 document. - */ -void -g72x_init_state( - struct g72x_state *state_ptr) -{ - int cnta; - - state_ptr->yl = 34816; - state_ptr->yu = 544; - state_ptr->dms = 0; - state_ptr->dml = 0; - state_ptr->ap = 0; - for (cnta = 0; cnta < 2; cnta++) { - state_ptr->a[cnta] = 0; - state_ptr->pk[cnta] = 0; - state_ptr->sr[cnta] = 32; - } - for (cnta = 0; cnta < 6; cnta++) { - state_ptr->b[cnta] = 0; - state_ptr->dq[cnta] = 32; - } - state_ptr->td = 0; -} - -/* - * predictor_zero() - * - * computes the estimated signal from 6-zero predictor. - * - */ -int -predictor_zero( - struct g72x_state *state_ptr) -{ - int i; - int sezi; - - sezi = fmult(state_ptr->b[0] >> 2, state_ptr->dq[0]); - for (i = 1; i < 6; i++) /* ACCUM */ - sezi += fmult(state_ptr->b[i] >> 2, state_ptr->dq[i]); - return (sezi); -} -/* - * predictor_pole() - * - * computes the estimated signal from 2-pole predictor. - * - */ -int -predictor_pole( - struct g72x_state *state_ptr) -{ - return (fmult(state_ptr->a[1] >> 2, state_ptr->sr[1]) + - fmult(state_ptr->a[0] >> 2, state_ptr->sr[0])); -} -/* - * step_size() - * - * computes the quantization step size of the adaptive quantizer. - * - */ -int -step_size( - struct g72x_state *state_ptr) -{ - int y; - int dif; - int al; - - if (state_ptr->ap >= 256) - return (state_ptr->yu); - else { - y = state_ptr->yl >> 6; - dif = state_ptr->yu - y; - al = state_ptr->ap >> 2; - if (dif > 0) - y += (dif * al) >> 6; - else if (dif < 0) - y += (dif * al + 0x3F) >> 6; - return (y); - } -} - -/* - * quantize() - * - * Given a raw sample, 'd', of the difference signal and a - * quantization step size scale factor, 'y', this routine returns the - * ADPCM codeword to which that sample gets quantized. The step - * size scale factor division operation is done in the log base 2 domain - * as a subtraction. - */ -int -quantize( - int d, /* Raw difference signal sample */ - int y, /* Step size multiplier */ - short *table, /* quantization table */ - int size) /* table size of short integers */ -{ - short dqm; /* Magnitude of 'd' */ - short exp; /* Integer part of base 2 log of 'd' */ - short mant; /* Fractional part of base 2 log */ - short dl; /* Log of magnitude of 'd' */ - short dln; /* Step size scale factor normalized log */ - int i; - - /* - * LOG - * - * Compute base 2 log of 'd', and store in 'dl'. - */ - dqm = abs(d); - exp = quan(dqm >> 1, power2, 15); - mant = ((dqm << 7) >> exp) & 0x7F; /* Fractional portion. */ - dl = (exp << 7) + mant; - - /* - * SUBTB - * - * "Divide" by step size multiplier. - */ - dln = dl - (y >> 2); - - /* - * QUAN - * - * Obtain codword i for 'd'. - */ - i = quan(dln, table, size); - if (d < 0) /* take 1's complement of i */ - return ((size << 1) + 1 - i); - else if (i == 0) /* take 1's complement of 0 */ - return ((size << 1) + 1); /* new in 1988 */ - else - return (i); -} -/* - * reconstruct() - * - * Returns reconstructed difference signal 'dq' obtained from - * codeword 'i' and quantization step size scale factor 'y'. - * Multiplication is performed in log base 2 domain as addition. - */ -int -reconstruct( - int sign, /* 0 for non-negative value */ - int dqln, /* G.72x codeword */ - int y) /* Step size multiplier */ -{ - short dql; /* Log of 'dq' magnitude */ - short dex; /* Integer part of log */ - short dqt; - short dq; /* Reconstructed difference signal sample */ - - dql = dqln + (y >> 2); /* ADDA */ - - if (dql < 0) { - return ((sign) ? -0x8000 : 0); - } else { /* ANTILOG */ - dex = (dql >> 7) & 15; - dqt = 128 + (dql & 127); - dq = (dqt << 7) >> (14 - dex); - return ((sign) ? (dq - 0x8000) : dq); - } -} - - -/* - * update() - * - * updates the state variables for each output code - */ -void -update( - int code_size, /* distinguish 723_40 with others */ - int y, /* quantizer step size */ - int wi, /* scale factor multiplier */ - int fi, /* for long/short term energies */ - int dq, /* quantized prediction difference */ - int sr, /* reconstructed signal */ - int dqsez, /* difference from 2-pole predictor */ - struct g72x_state *state_ptr) /* coder state pointer */ -{ - int cnt; - short mag, exp; /* Adaptive predictor, FLOAT A */ - short a2p; /* LIMC */ - short a1ul; /* UPA1 */ - short pks1; /* UPA2 */ - short fa1; - char tr; /* tone/transition detector */ - short ylint, thr2, dqthr; - short ylfrac, thr1; - short pk0; - - pk0 = (dqsez < 0) ? 1 : 0; /* needed in updating predictor poles */ - - mag = dq & 0x7FFF; /* prediction difference magnitude */ - /* TRANS */ - ylint = (short)(state_ptr->yl >> 15); /* exponent part of yl */ - ylfrac = (state_ptr->yl >> 10) & 0x1F; /* fractional part of yl */ - thr1 = (32 + ylfrac) << ylint; /* threshold */ - thr2 = (ylint > 9) ? 31 << 10 : thr1; /* limit thr2 to 31 << 10 */ - dqthr = (thr2 + (thr2 >> 1)) >> 1; /* dqthr = 0.75 * thr2 */ - if (state_ptr->td == 0) /* signal supposed voice */ - tr = 0; - else if (mag <= dqthr) /* supposed data, but small mag */ - tr = 0; /* treated as voice */ - else /* signal is data (modem) */ - tr = 1; - - /* - * Quantizer scale factor adaptation. - */ - - /* FUNCTW & FILTD & DELAY */ - /* update non-steady state step size multiplier */ - state_ptr->yu = y + ((wi - y) >> 5); - - /* LIMB */ - if (state_ptr->yu < 544) /* 544 <= yu <= 5120 */ - state_ptr->yu = 544; - else if (state_ptr->yu > 5120) - state_ptr->yu = 5120; - - /* FILTE & DELAY */ - /* update steady state step size multiplier */ - state_ptr->yl += state_ptr->yu + ((-state_ptr->yl) >> 6); - - /* - * Adaptive predictor coefficients. - */ - if (tr == 1) { /* reset a's and b's for modem signal */ - state_ptr->a[0] = 0; - state_ptr->a[1] = 0; - state_ptr->b[0] = 0; - state_ptr->b[1] = 0; - state_ptr->b[2] = 0; - state_ptr->b[3] = 0; - state_ptr->b[4] = 0; - state_ptr->b[5] = 0; - } else { /* update a's and b's */ - pks1 = pk0 ^ state_ptr->pk[0]; /* UPA2 */ - - /* update predictor pole a[1] */ - a2p = state_ptr->a[1] - (state_ptr->a[1] >> 7); - if (dqsez != 0) { - fa1 = (pks1) ? state_ptr->a[0] : -state_ptr->a[0]; - if (fa1 < -8191) /* a2p = function of fa1 */ - a2p -= 0x100; - else if (fa1 > 8191) - a2p += 0xFF; - else - a2p += fa1 >> 5; - - if (pk0 ^ state_ptr->pk[1]) - /* LIMC */ - if (a2p <= -12160) - a2p = -12288; - else if (a2p >= 12416) - a2p = 12288; - else - a2p -= 0x80; - else if (a2p <= -12416) - a2p = -12288; - else if (a2p >= 12160) - a2p = 12288; - else - a2p += 0x80; - } - - /* TRIGB & DELAY */ - state_ptr->a[1] = a2p; - - /* UPA1 */ - /* update predictor pole a[0] */ - state_ptr->a[0] -= state_ptr->a[0] >> 8; - if (dqsez != 0) - { - if (pks1 == 0) - state_ptr->a[0] += 192; - else - state_ptr->a[0] -= 192; - } - - /* LIMD */ - a1ul = 15360 - a2p; - if (state_ptr->a[0] < -a1ul) - state_ptr->a[0] = -a1ul; - else if (state_ptr->a[0] > a1ul) - state_ptr->a[0] = a1ul; - - /* UPB : update predictor zeros b[6] */ - for (cnt = 0; cnt < 6; cnt++) { - if (code_size == 5) /* for 40Kbps G.723 */ - state_ptr->b[cnt] -= state_ptr->b[cnt] >> 9; - else /* for G.721 and 24Kbps G.723 */ - state_ptr->b[cnt] -= state_ptr->b[cnt] >> 8; - if (dq & 0x7FFF) { /* XOR */ - if ((dq ^ state_ptr->dq[cnt]) >= 0) - state_ptr->b[cnt] += 128; - else - state_ptr->b[cnt] -= 128; - } - } - } - - for (cnt = 5; cnt > 0; cnt--) - state_ptr->dq[cnt] = state_ptr->dq[cnt-1]; - /* FLOAT A : convert dq[0] to 4-bit exp, 6-bit mantissa f.p. */ - if (mag == 0) { - state_ptr->dq[0] = (dq >= 0) ? 0x20 : 0xFC20; - } else { - exp = quan(mag, power2, 15); - state_ptr->dq[0] = (dq >= 0) ? - (exp << 6) + ((mag << 6) >> exp) : - (exp << 6) + ((mag << 6) >> exp) - 0x400; - } - - state_ptr->sr[1] = state_ptr->sr[0]; - /* FLOAT B : convert sr to 4-bit exp., 6-bit mantissa f.p. */ - if (sr == 0) { - state_ptr->sr[0] = 0x20; - } else if (sr > 0) { - exp = quan(sr, power2, 15); - state_ptr->sr[0] = (exp << 6) + ((sr << 6) >> exp); - } else if (sr > -32768) { - mag = -sr; - exp = quan(mag, power2, 15); - state_ptr->sr[0] = (exp << 6) + ((mag << 6) >> exp) - 0x400; - } else - state_ptr->sr[0] = (short)0xFC20; - - /* DELAY A */ - state_ptr->pk[1] = state_ptr->pk[0]; - state_ptr->pk[0] = pk0; - - /* TONE */ - if (tr == 1) /* this sample has been treated as data */ - state_ptr->td = 0; /* next one will be treated as voice */ - else if (a2p < -11776) /* small sample-to-sample correlation */ - state_ptr->td = 1; /* signal may be data */ - else /* signal is voice */ - state_ptr->td = 0; - - /* - * Adaptation speed control. - */ - state_ptr->dms += (fi - state_ptr->dms) >> 5; /* FILTA */ - state_ptr->dml += (((fi << 2) - state_ptr->dml) >> 7); /* FILTB */ - - if (tr == 1) - state_ptr->ap = 256; - else if (y < 1536) /* SUBTC */ - state_ptr->ap += (0x200 - state_ptr->ap) >> 4; - else if (state_ptr->td == 1) - state_ptr->ap += (0x200 - state_ptr->ap) >> 4; - else if (abs((state_ptr->dms << 2) - state_ptr->dml) >= - (state_ptr->dml >> 3)) - state_ptr->ap += (0x200 - state_ptr->ap) >> 4; - else - state_ptr->ap += (-state_ptr->ap) >> 4; -} - -/* - * tandem_adjust(sr, se, y, i, sign) - * - * At the end of ADPCM decoding, it simulates an encoder which may be receiving - * the output of this decoder as a tandem process. If the output of the - * simulated encoder differs from the input to this decoder, the decoder output - * is adjusted by one level of A-law or u-law codes. - * - * Input: - * sr decoder output linear PCM sample, - * se predictor estimate sample, - * y quantizer step size, - * i decoder input code, - * sign sign bit of code i - * - * Return: - * adjusted A-law or u-law compressed sample. - */ -int -tandem_adjust_alaw( - int sr, /* decoder output linear PCM sample */ - int se, /* predictor estimate sample */ - int y, /* quantizer step size */ - int i, /* decoder input code */ - int sign, - short *qtab) -{ - unsigned char sp; /* A-law compressed 8-bit code */ - short dx; /* prediction error */ - char id; /* quantized prediction error */ - int sd; /* adjusted A-law decoded sample value */ - int im; /* biased magnitude of i */ - int imx; /* biased magnitude of id */ - - if (sr <= -32768) - sr = -1; - sp = linear2alaw((sr >> 1) << 3); /* short to A-law compression */ - dx = (alaw2linear(sp) >> 2) - se; /* 16-bit prediction error */ - id = quantize(dx, y, qtab, sign - 1); - - if (id == i) { /* no adjustment on sp */ - return (sp); - } else { /* sp adjustment needed */ - /* ADPCM codes : 8, 9, ... F, 0, 1, ... , 6, 7 */ - im = i ^ sign; /* 2's complement to biased unsigned */ - imx = id ^ sign; - - if (imx > im) { /* sp adjusted to next lower value */ - if (sp & 0x80) { - sd = (sp == 0xD5) ? 0x55 : - ((sp ^ 0x55) - 1) ^ 0x55; - } else { - sd = (sp == 0x2A) ? 0x2A : - ((sp ^ 0x55) + 1) ^ 0x55; - } - } else { /* sp adjusted to next higher value */ - if (sp & 0x80) - sd = (sp == 0xAA) ? 0xAA : - ((sp ^ 0x55) + 1) ^ 0x55; - else - sd = (sp == 0x55) ? 0xD5 : - ((sp ^ 0x55) - 1) ^ 0x55; - } - return (sd); - } -} - -int -tandem_adjust_ulaw( - int sr, /* decoder output linear PCM sample */ - int se, /* predictor estimate sample */ - int y, /* quantizer step size */ - int i, /* decoder input code */ - int sign, - short *qtab) -{ - unsigned char sp; /* u-law compressed 8-bit code */ - short dx; /* prediction error */ - char id; /* quantized prediction error */ - int sd; /* adjusted u-law decoded sample value */ - int im; /* biased magnitude of i */ - int imx; /* biased magnitude of id */ - - if (sr <= -32768) - sr = 0; - sp = linear2ulaw(sr << 2); /* short to u-law compression */ - dx = (ulaw2linear(sp) >> 2) - se; /* 16-bit prediction error */ - id = quantize(dx, y, qtab, sign - 1); - if (id == i) { - return (sp); - } else { - /* ADPCM codes : 8, 9, ... F, 0, 1, ... , 6, 7 */ - im = i ^ sign; /* 2's complement to biased unsigned */ - imx = id ^ sign; - if (imx > im) { /* sp adjusted to next lower value */ - if (sp & 0x80) - sd = (sp == 0xFF) ? 0x7E : sp + 1; - else - sd = (sp == 0) ? 0 : sp - 1; - - } else { /* sp adjusted to next higher value */ - if (sp & 0x80) - sd = (sp == 0x80) ? 0x80 : sp - 1; - else - sd = (sp == 0x7F) ? 0xFE : sp + 1; - } - return (sd); - } -} - -#endif diff --git a/engine/sndcodec/g72x.h b/engine/sndcodec/g72x.h deleted file mode 100644 index b7e0255b0..000000000 --- a/engine/sndcodec/g72x.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * This source code is a product of Sun Microsystems, Inc. and is provided - * for unrestricted use. Users may copy or modify this source code without - * charge. - * - * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING - * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * - * Sun source code is provided with no support and without any obligation on - * the part of Sun Microsystems, Inc. to assist in its use, correction, - * modification or enhancement. - * - * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE - * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE - * OR ANY PART THEREOF. - * - * In no event will Sun Microsystems, Inc. be liable for any lost revenue - * or profits or other special, indirect and consequential damages, even if - * Sun has been advised of the possibility of such damages. - * - * Sun Microsystems, Inc. - * 2550 Garcia Avenue - * Mountain View, California 94043 - */ - -/* - * g72x.h - * - * Header file for CCITT conversion routines. - * - */ -#ifndef _G72X_H -#define _G72X_H - -#define AUDIO_ENCODING_ULAW (1) /* ISDN u-law */ -#define AUDIO_ENCODING_ALAW (2) /* ISDN A-law */ -#define AUDIO_ENCODING_LINEAR (3) /* PCM 2's-complement (0-center) */ - -/* - * The following is the definition of the state structure - * used by the G.721/G.723 encoder and decoder to preserve their internal - * state between successive calls. The meanings of the majority - * of the state structure fields are explained in detail in the - * CCITT Recommendation G.721. The field names are essentially indentical - * to variable names in the bit level description of the coding algorithm - * included in this Recommendation. - */ -struct g72x_state { - long yl; /* Locked or steady state step size multiplier. */ - short yu; /* Unlocked or non-steady state step size multiplier. */ - short dms; /* Short term energy estimate. */ - short dml; /* Long term energy estimate. */ - short ap; /* Linear weighting coefficient of 'yl' and 'yu'. */ - - short a[2]; /* Coefficients of pole portion of prediction filter. */ - short b[6]; /* Coefficients of zero portion of prediction filter. */ - short pk[2]; /* - * Signs of previous two samples of a partially - * reconstructed signal. - */ - short dq[6]; /* - * Previous 6 samples of the quantized difference - * signal represented in an internal floating point - * format. - */ - short sr[2]; /* - * Previous 2 samples of the quantized difference - * signal represented in an internal floating point - * format. - */ - char td; /* delayed tone detect, new in 1988 version */ -}; - -/* External function definitions. */ - -extern void g72x_init_state(struct g72x_state *); -extern int g721_encoder( - int sample, - int in_coding, - struct g72x_state *state_ptr); -extern int g721_decoder( - int code, - int out_coding, - struct g72x_state *state_ptr); -extern int g723_24_encoder( - int sample, - int in_coding, - struct g72x_state *state_ptr); -extern int g723_24_decoder( - int code, - int out_coding, - struct g72x_state *state_ptr); -extern int g723_40_encoder( - int sample, - int in_coding, - struct g72x_state *state_ptr); -extern int g723_40_decoder( - int code, - int out_coding, - struct g72x_state *state_ptr); - - -//see the function bodies for a description -unsigned char linear2alaw(int pcm_val); -unsigned char linear2ulaw(int pcm_val); -int ulaw2linear(unsigned char u_val); -int alaw2linear(unsigned char a_val); -int predictor_zero(struct g72x_state *state_ptr); -int predictor_pole(struct g72x_state *state_ptr); -int step_size(struct g72x_state *state_ptr); -int quantize(int d, int y, short *table, int size); -int reconstruct(int sign, int dqln, int y); -void update(int code_size, int y, int wi, int fi, int dq, int sr, int dqsez, struct g72x_state *state_ptr); -int tandem_adjust_ulaw(int sr, int se, int y, int i, int sign, short *qtab); -int tandem_adjust_alaw(int sr, int se, int y, int i, int sign, short *qtab); - -#endif /* !_G72X_H */ diff --git a/engine/sndcodec/snd_vc.c b/engine/sndcodec/snd_vc.c deleted file mode 100644 index 2faa2a1b5..000000000 --- a/engine/sndcodec/snd_vc.c +++ /dev/null @@ -1,404 +0,0 @@ -//voice chat routines. - -//needs quite a bit of work. - -//it needs a proper protocol. -//the server needs to be able to shutdown again. -//options about who gets the sound data is also needed. - -#include "bothdefs.h" - -#ifdef VOICECHAT - -#include "quakedef.h" -#ifdef _WIN32 -#include "winquake.h" -#endif - -#include "netinc.h" - -#include "voicechat.h" - -static int CLVS_socket; -static int SVVS_socket; -static qboolean SVVS_inited; - -static qbyte inputbuffer[44100]; -static int readpoint; -static qbyte outputbuffer[44100]; -static int sendpoint; - -/* -Protocol: - Sound chunk: - (char) data begins with codec id. - (short) followed by number of samples - (short) then size in bytes of chunk. -*/ - -#ifndef CLIENTONLY -void SVVC_ServerInit(void) -{ - netadr_t adr; - struct sockaddr_in address; - unsigned long _true = true; - int i; - int port = PORT_SERVER; - - if ((SVVS_socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) - { - Sys_Error ("FTP_TCP_OpenSocket: socket:", strerror(qerrno)); - } - - if (ioctlsocket (SVVS_socket, FIONBIO, &_true) == -1) - { - Sys_Error ("FTP_TCP_OpenSocket: ioctl FIONBIO:", strerror(qerrno)); - } - - address.sin_family = AF_INET; -//ZOID -- check for interface binding option - if ((i = COM_CheckParm("-ip")) != 0 && i < com_argc) { - address.sin_addr.s_addr = inet_addr(com_argv[i+1]); - Con_TPrintf(TL_NETBINDINTERFACE, - inet_ntoa(address.sin_addr)); - } else - address.sin_addr.s_addr = INADDR_ANY; - - if (port == PORT_ANY) - address.sin_port = 0; - else - address.sin_port = htons((short)port); - - if( bind (SVVS_socket, (void *)&address, sizeof(address)) == -1) - { - closesocket(SVVS_socket); - return; - } - - listen(SVVS_socket, 3); - - SVVS_inited = true; - - - Con_Printf("VC server is running\n"); - SockadrToNetadr((struct sockaddr_qstorage*)&address, &adr); - Info_SetValueForKey(svs.info, "voiceaddress", NET_AdrToString(adr), MAX_SERVERINFO_STRING); - return; -} - -//currently a dum forwarding/broadcasting mechanism -void SVVC_Frame (qboolean running) -{ - struct sockaddr_in frm; - int size = sizeof(frm); - int newcl; - int i, j; - char buffer[1400]; - - if (!running) - return; - - if (!SVVS_socket) - { - SVVC_ServerInit(); - return; - } - newcl = accept(SVVS_socket, (struct sockaddr *)&frm, &size); - if (newcl != INVALID_SOCKET) - { - for (i = 0; i < MAX_CLIENTS; i++) - { - if (!svs.clients[i].voicechat.socket) //this really isn't the right way... - { - svs.clients[i].voicechat.socket = newcl; - break; - } - } - } - - for (i = 0; i < MAX_CLIENTS; i++) - { - host_client = &svs.clients[i]; - - if (host_client->voicechat.socket) - { - size = recv(host_client->voicechat.socket, buffer, sizeof(buffer), 0); - if (size > 0) - { - for (j = 0; j < MAX_CLIENTS; j++) - { - if (j != i && svs.clients[j].voicechat.socket) //gotta be capable of receiving, and not the sender (that would be dumb). - send(svs.clients[j].voicechat.socket, buffer, size, 0); - } - } - } - } -} -#endif - -#ifndef SERVERONLY - -sfxcache_t *voicesoundbuffer[2]; -sfx_t recordaudio[2] = { - {"recordaudio1", - {NULL, false}, - NULL}, - {"recordaudio2", - {NULL, false}, - NULL} -}; -int audiobuffer; -void SNDVC_Submit(int codec, qbyte *buffer, int samples, int freq, int width) -{ - S_RawAudio(0, buffer, freq, samples, 1, width); - /* - soundcardinfo_t *cursndcard; - audiobuffer=0; - if (!recordaudio[audiobuffer].cache.data) - { - voicesoundbuffer[audiobuffer] = BZ_Malloc(44100*2+sizeof(sfxcache_t)); - recordaudio[audiobuffer].cache.data = voicesoundbuffer[audiobuffer]; - recordaudio[audiobuffer].cache.fake = true; - } - - cursndcard = sndcardinfo; - if (!cursndcard) - { - Con_Printf("Accepting voice chat with no sound card\n"); - return; - } - voicesoundbuffer[audiobuffer]->length = samples; - voicesoundbuffer[audiobuffer]->stereo = false; - voicesoundbuffer[audiobuffer]->speed = sndcardinfo->sn.speed; - voicesoundbuffer[audiobuffer]->width = width; - voicesoundbuffer[audiobuffer]->loopstart=-1; - -// Con_DPrintf("Submit %i\n", (int)samples); - - if (codec == 0) //codec 0 is special. (A straight copy) - ResampleSfx(&recordaudio[audiobuffer], freq, width, buffer); - else - { - qbyte *temp = BZ_Malloc(samples*width); - audiocodecs[codec].decode(buffer, (short*)temp, samples); - ResampleSfx(&recordaudio[audiobuffer], freq, width, temp); - BZ_Free(temp); - } - - for (cursndcard = sndcardinfo; cursndcard; cursndcard=cursndcard->next) - { - if (0&&cursndcard->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS+1-audiobuffer].sfx == &recordaudio[1-audiobuffer]) //other buffer is playing. - { - cursndcard->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS+audiobuffer].sfx = &recordaudio[audiobuffer]; - cursndcard->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS+audiobuffer].pos = cursndcard->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS+1-audiobuffer].end - voicesoundbuffer[1-audiobuffer]->length- cursndcard->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS+1-audiobuffer].pos; - cursndcard->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS+audiobuffer].end = cursndcard->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS+audiobuffer].end + samples; - - if (cursndcard->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS+audiobuffer].pos >= voicesoundbuffer[audiobuffer]->length) - { - cursndcard->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS+1-audiobuffer].pos = voicesoundbuffer[1-audiobuffer]->length; - cursndcard->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS+audiobuffer].pos = 0; - Con_Printf("Sound out of sync\n"); - } - } - else - { - cursndcard->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS+audiobuffer].sfx = &recordaudio[audiobuffer]; - cursndcard->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS+audiobuffer].pos = 0; - cursndcard->channel[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS+audiobuffer].end = cursndcard->paintedtime + samples; - } - } - audiobuffer = 1-audiobuffer;*/ -} - - - - - - - - - - - - - - - -void CLVC_SetServer (char *addy) -{ - unsigned long _true = true; - struct sockaddr_qstorage from; - - - if ((CLVS_socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) - { - Sys_Error ("FTP_UDP_OpenSocket: socket: %s\n", strerror(qerrno)); - } - - - {//quake routines using dns and stuff (Really, I wanna keep quake and ftp fairly seperate) - netadr_t qaddy; - if (!NET_StringToAdr (addy, &qaddy)) //server doesn't exist. - return; - if (qaddy.type != NA_IP) //Only TCP is supported. - return; - if (!qaddy.port) - qaddy.port = htons(PORT_SERVER); - NetadrToSockadr(&qaddy, &from); - - } - - //not yet non blocking. - if (connect(CLVS_socket, (struct sockaddr*)&from, sizeof(from)) == -1) - { - Con_Printf ("FTP_TCP_OpenSocket: connect: %i %s\n", qerrno, strerror(qerrno)); - closesocket(CLVS_socket); - CLVS_socket = 0; - return; - } - - if (ioctlsocket (CLVS_socket, FIONBIO, &_true) == -1) //now make it non blocking. - { - Sys_Error ("FTP_TCP_OpenSocket: ioctl FIONBIO: %s\n", strerror(qerrno)); - } -} - -void CLVC_Disconnect (void) -{ - closesocket(CLVS_socket); - CLVS_socket = 0; -} - -void CLVC_Poll (void) -{ - int codec; - int size; - - if (!CLVS_socket) - return; - - while (1) - { - size = recv(CLVS_socket, &inputbuffer[readpoint], sizeof(inputbuffer) - readpoint, 0); - if (size>0) - { - int samps; - int bytes; - readpoint+=size; - if (readpoint >= 1) - { - codec = *inputbuffer; - - if (codec >= 0 && codec <= 127 && readpoint>=5) //just in case. - { - samps = LittleLong(*(signed short *)(inputbuffer+1)); - bytes = LittleLong(*(unsigned short *)(inputbuffer+3)); -// Con_DPrintf("read %i\n", size); - if (samps < 0) //something special - { - readpoint=0; - } - else - { - if (readpoint >= bytes+5) - { - if (codec == 1) - Con_Printf("Reading\n"); - if (codec < audionumcodecs && audiocodecs[codec].decode) - { - SNDVC_Submit(codec, ((qbyte *)inputbuffer)+5, samps, 11025, 2); - readpoint -= bytes+5; - memmove(inputbuffer, &inputbuffer[readpoint+bytes+5], readpoint); - } - else - { - Con_Printf("Bad codec %i\n", (int)codec); - readpoint=0; - closesocket(CLVS_socket); - CLVS_socket = 0; - } - } - } - } - } - } - else if (readpoint >= sizeof(inputbuffer) || readpoint < 0) - { - Con_Printf("Too small buffer or extended client %i\n", (int)readpoint); - readpoint=0; - closesocket(CLVS_socket); - CLVS_socket = 0; - } - else - { - break; - } - } -} - -void SNDVC_MicInput(qbyte *buffer, int samples, int freq, int width) //this correctly buffers data ready to be sent. -{ - int sent; - qbyte codec; - unsigned short *sampleswritten; - samples/=width; - if (!CLVS_socket) - { - if (cls.state) - { - char *server; - server = Info_ValueForKey(cl.serverinfo, "voiceaddress"); - if (*server) - CLVC_SetServer(server); - } - - SNDVC_Submit(0, buffer, samples, freq, width); - return; - } - else if (!cls.state) - { - readpoint = 0; - sendpoint= 0; - SNDVC_Submit(0, buffer, samples, freq, width); - return; - } - - SNDVC_Submit(0, buffer, samples, freq, width); //remembering at all times that we will not be allowed to hear it ourselves. - - //add to send buffer. - if (samples > 0x7ffe) - samples = 0x7ffe; - - if (sendpoint + samples*width+sizeof(unsigned char)+sizeof(short)+sizeof(*sampleswritten) < sizeof(outputbuffer)) - { -// Con_DPrintf("sending %i\n", (int)samples); - codec = 1; - outputbuffer[sendpoint] = codec; sendpoint += sizeof(unsigned char); - *(unsigned short*)(&outputbuffer[sendpoint]) = samples; sendpoint += sizeof(unsigned short); - sampleswritten = (short *)&outputbuffer[sendpoint]; sendpoint += sizeof(*sampleswritten); - *sampleswritten = audiocodecs[codec].encode((short *)buffer, &outputbuffer[sendpoint], samples); - sendpoint += *sampleswritten; - } - else - { - Con_Printf("Connection overflowing\n"); - } - -//try and send it - sent = send(CLVS_socket, outputbuffer, sendpoint, 0); - if (sent > 0) - { -// Con_DPrintf("sent %i\n", (int)sent); - sendpoint -= sent; - } - else - { -CLVS_socket=0; - } - - -// SNDVC_Submit(buffer, samples, freq, width); -} - -#endif -#endif diff --git a/engine/sndcodec/snd_voicecodecs.c b/engine/sndcodec/snd_voicecodecs.c deleted file mode 100644 index e9b7d9bd5..000000000 --- a/engine/sndcodec/snd_voicecodecs.c +++ /dev/null @@ -1,189 +0,0 @@ -#include "bothdefs.h" - -#ifdef VOICECHAT - -#include "quakedef.h" -#include "voicechat.h" - - - -#include "g72x.h" - -int VC_g72x_encoder (short *in, unsigned char *out, int samples, int (*g72x_encoder)(int,int,struct g72x_state *state), int bits) -{ - struct g72x_state state; - unsigned int out_buffer = 0; - int out_bits = 0; - unsigned char out_byte; - int code; - int written=0; - - g72x_init_state(&state); - - while (samples) - { - code = g72x_encoder(*in, AUDIO_ENCODING_LINEAR, &state); - - out_buffer |= (code << out_bits); - out_bits += bits; - if (out_bits >= 8) - { - out_byte = out_buffer & 0xff; - out_bits -= 8; - out_buffer >>= 8; - *out = out_byte; - out++; - written++; - } - in++; - - samples--; - } - code=0; - while (out_bits > 0) - { - out_buffer |= (code << out_bits); - out_bits += bits; - if (out_bits >= 8) - { - out_byte = out_buffer & 0xff; - out_bits -= 8; - out_buffer >>= 8; - *out = out_byte; - out++; - written++; - } - } - - return written; -} - -int VC_g723_24_encoder (short *in, unsigned char *out, int samples) -{ - return VC_g72x_encoder(in, out, samples, g723_24_encoder, 3); -} - -int VC_g721_encoder (short *in, unsigned char *out, int samples) -{ - return VC_g72x_encoder(in, out, samples, g721_encoder, 4); -} - -int VC_g723_40_encoder (short *in, unsigned char *out, int samples) -{ - return VC_g72x_encoder(in, out, samples, g723_40_encoder, 5); -} - -int VC_g72x_decoder (unsigned char *in, short *out, int samples, int (*g72x_decoder)(int,int,struct g72x_state *state), int bits) -{ - struct g72x_state state; - unsigned int in_buffer = 0; - int in_bits = 0; - unsigned char in_byte; - int code; - int read=0; - - g72x_init_state(&state); - - while (samples) - { - if (in_bits < bits) - { - in_byte = *in++; - read++; - in_buffer |= (in_byte << in_bits); - in_bits += 8; - } - code = in_buffer & ((1 << bits) - 1); - in_buffer >>= bits; - in_bits -= bits; - - *out = g72x_decoder(code, AUDIO_ENCODING_LINEAR, &state); - out++; - - samples--; - } - - return read; -} - -int VC_g723_24_decoder (unsigned char *in, short *out, int samples) -{ - return VC_g72x_decoder(in, out, samples, g723_24_decoder, 3); -} - -int VC_g721_decoder (unsigned char *in, short *out, int samples) -{ - return VC_g72x_decoder(in, out, samples, g721_decoder, 4); -} - -int VC_g723_40_decoder (unsigned char *in, short *out, int samples) -{ - return VC_g72x_decoder(in, out, samples, g723_40_decoder, 5); -} - - - - - - - - - - - - - - - -int VS_Raw_enc (short *in, unsigned char *out, int samples) -{ - memcpy(out, in, samples*2); - return samples*2; -} - -int VS_Raw_dec (unsigned char *in, short *out, int samples) -{ - memcpy(out, in, samples*2); - return samples*2; -} - - - - - - - - - - - - - - - - - - - - - - - - - -audiocodec_t audiocodecs[] = { - {"Raw 11025sps 16bit", VS_Raw_enc, VS_Raw_dec}, -#ifdef _G72X_H - {"G.723.24", VC_g723_24_encoder, VC_g723_24_decoder}, - {"G.721 32", VC_g721_encoder, VC_g721_decoder}, - {"G.723.40", VC_g723_40_encoder, VC_g723_40_decoder}, -#else - {"Non-implemented codec (G.723.24)"}, - {"Non-implemented codec (G.721 32)"}, - {"Non-implemented codec (G.723.40)"}, -#endif - {0} -}; - -const int audionumcodecs = sizeof(audiocodecs)/sizeof(audiocodec_t); -#endif diff --git a/engine/sndcodec/voicechat.h b/engine/sndcodec/voicechat.h deleted file mode 100644 index be7fe3d77..000000000 --- a/engine/sndcodec/voicechat.h +++ /dev/null @@ -1,9 +0,0 @@ -//raw data is 16 bps -typedef struct { - char *name; - int (*encode) (short *in, unsigned char *out, int numsamps); //returns number of bytes. - int (*decode) (unsigned char *in, short *out, int numsamps); //returns number of 16bps samples. -} audiocodec_t; - -extern audiocodec_t audiocodecs[]; -extern const int audionumcodecs; diff --git a/engine/sw/sw.h b/engine/sw/sw.h index 272440b4c..4fe361354 100644 --- a/engine/sw/sw.h +++ b/engine/sw/sw.h @@ -28,6 +28,7 @@ typedef struct unsigned int vpwidth; unsigned int vpheight; qintptr_t vpcstride; + struct workqueue_s *wq; } swthread_t; typedef struct @@ -39,7 +40,19 @@ typedef struct unsigned int clipflags; /*1=left,2=right,4=top,8=bottom,16=near*/ } swvert_t; -swthread_t *SWRast_CreateThread(int tno); +#define WQ_SIZE 1024*1024*8 +#define WQ_MASK (WQ_SIZE-1) +#define WQ_MAXTHREADS 64 +struct workqueue_s +{ + unsigned int numthreads; + qbyte queue[WQ_SIZE]; + volatile unsigned int pos; + + swthread_t swthreads[WQ_MAXTHREADS]; +}; +extern struct workqueue_s commandqueue; + enum wqcmd_e @@ -50,7 +63,8 @@ enum wqcmd_e WTC_NOOP, WTC_VIEWPORT, WTC_TRIFAN, - WTC_TRISOUP + WTC_TRISOUP, + WTC_SPANS }; enum @@ -102,13 +116,17 @@ typedef union qboolean cleardepth; qboolean clearcolour; } viewport; + struct + { + int foo; + } spans; } wqcom_t; -void SWRast_EndCommand(wqcom_t *com); -wqcom_t *SWRast_BeginCommand(int cmdtype, unsigned int size); -void SWRast_Sync(void); +void SWRast_EndCommand(struct workqueue_s *wq, wqcom_t *com); +wqcom_t *SWRast_BeginCommand(struct workqueue_s *wq, int cmdtype, unsigned int size); +void SWRast_Sync(struct workqueue_s *wq); @@ -128,7 +146,7 @@ texid_tf SW_LoadTexture(char *identifier, int width, int height, uploadfmt_t fmt texid_tf SW_LoadTexture8Pal24(char *identifier, int width, int height, qbyte *data, qbyte *palette24, unsigned int flags); texid_tf SW_LoadTexture8Pal32(char *identifier, int width, int height, qbyte *data, qbyte *palette32, unsigned int flags); texid_tf SW_LoadCompressed(char *name); -texid_tf SW_FindTexture(char *identifier); +texid_tf SW_FindTexture(char *identifier, unsigned int flags); texid_tf SW_AllocNewTexture(char *identifier, int w, int h); void SW_Upload(texid_t tex, char *name, uploadfmt_t fmt, void *data, void *palette, int width, int height, unsigned int flags); void SW_DestroyTexture(texid_t tex); @@ -139,7 +157,7 @@ void SWBE_DrawMesh_List(shader_t *shader, int nummeshes, struct mesh_s **mesh, s void SWBE_DrawMesh_Single(shader_t *shader, struct mesh_s *meshchain, struct vbo_s *vbo, struct texnums_s *texnums, unsigned int be_flags); void SWBE_SubmitBatch(struct batch_s *batch); struct batch_s *SWBE_GetTempBatch(void); -void SWBE_DrawWorld(qbyte *vis); +void SWBE_DrawWorld(qboolean drawworld, qbyte *vis); void SWBE_Init(void); void SWBE_GenBrushModelVBO(struct model_s *mod); void SWBE_ClearVBO(struct vbo_s *vbo); diff --git a/engine/sw/sw_backend.c b/engine/sw/sw_backend.c index a2f0ed87f..3f2c01047 100644 --- a/engine/sw/sw_backend.c +++ b/engine/sw/sw_backend.c @@ -452,18 +452,18 @@ void SWBE_DrawMesh_Single(shader_t *shader, mesh_t *mesh, struct vbo_s *vbo, str if (mesh->istrifan) { - com = SWRast_BeginCommand(WTC_TRIFAN, mesh->numvertexes*sizeof(swvert_t) + sizeof(com->trifan) - sizeof(com->trifan.verts)); + com = SWRast_BeginCommand(&commandqueue, WTC_TRIFAN, mesh->numvertexes*sizeof(swvert_t) + sizeof(com->trifan) - sizeof(com->trifan.verts)); com->trifan.texture = texnums->base.ptr; com->trifan.numverts = mesh->numvertexes; SWBE_TransformVerticies(com->trifan.verts, mesh); - SWRast_EndCommand(com); + SWRast_EndCommand(&commandqueue, com); } else { - com = SWRast_BeginCommand(WTC_TRISOUP, (mesh->numvertexes*sizeof(swvert_t)) + sizeof(com->trisoup) - sizeof(com->trisoup.verts) + (sizeof(index_t)*mesh->numindexes)); + com = SWRast_BeginCommand(&commandqueue, WTC_TRISOUP, (mesh->numvertexes*sizeof(swvert_t)) + sizeof(com->trisoup) - sizeof(com->trisoup.verts) + (sizeof(index_t)*mesh->numindexes)); com->trisoup.texture = texnums->base.ptr; com->trisoup.numverts = mesh->numvertexes; @@ -472,7 +472,7 @@ void SWBE_DrawMesh_Single(shader_t *shader, mesh_t *mesh, struct vbo_s *vbo, str SWBE_TransformVerticies(com->trisoup.verts, mesh); memcpy(com->trisoup.verts + mesh->numvertexes, mesh->indexes, sizeof(index_t)*mesh->numindexes); - SWRast_EndCommand(com); + SWRast_EndCommand(&commandqueue, com); } } void SWBE_DrawMesh_List(shader_t *shader, int nummeshes, struct mesh_s **mesh, struct vbo_s *vbo, struct texnums_s *texnums, unsigned int be_flags) @@ -593,7 +593,7 @@ void SWBE_Set2D(void) memcpy(shaderstate.m_mvp, r_refdef.m_projection, sizeof(shaderstate.m_mvp)); } -void SWBE_DrawWorld(qbyte *vis) +void SWBE_DrawWorld(qboolean drawworld, qbyte *vis) { batch_t *batches[SHADER_SORT_COUNT]; @@ -615,7 +615,7 @@ void SWBE_DrawWorld(qbyte *vis) shaderstate.curentity = NULL; SWBE_SelectEntity(&r_worldentity); - SWBE_SubmitMeshes(vis!=NULL, batches, SHADER_SORT_PORTAL, SHADER_SORT_NEAREST); + SWBE_SubmitMeshes(drawworld, batches, SHADER_SORT_PORTAL, SHADER_SORT_NEAREST); SWBE_Set2D(); } diff --git a/engine/sw/sw_image.c b/engine/sw/sw_image.c index 77f1cdbfa..934016a75 100644 --- a/engine/sw/sw_image.c +++ b/engine/sw/sw_image.c @@ -21,7 +21,7 @@ texid_tf SW_AllocNewTexture(char *identifier, int w, int h) n.ref = &img->com; return n; } -texid_tf SW_FindTexture(char *identifier) +texid_tf SW_FindTexture(char *identifier, unsigned int flags) { return r_nulltex; } @@ -70,9 +70,11 @@ void SW_Upload8(swimage_t *img, int w, int h, unsigned char *data) texid_tf SW_LoadTexture(char *identifier, int width, int height, uploadfmt_t fmt, void *data, unsigned int flags) { - texid_t img = SW_FindTexture(identifier); + texid_t img = SW_FindTexture(identifier, flags); if (!img.ptr) img = SW_AllocNewTexture(identifier, width, height); + if (!img.ptr) + return r_nulltex; switch(fmt) { case TF_SOLID8: @@ -114,7 +116,7 @@ void SW_DestroyTexture(texid_t tex) swimage_t *img = tex.ptr; /*make sure its not in use by the renderer*/ - SWRast_Sync(); + SWRast_Sync(&commandqueue); /*okay, it can be killed*/ BZ_Free(img); diff --git a/engine/sw/sw_rast.c b/engine/sw/sw_rast.c index ea462b2c8..f66c05b3d 100644 --- a/engine/sw/sw_rast.c +++ b/engine/sw/sw_rast.c @@ -30,20 +30,12 @@ we can also trivially implement interlacing with this method */ - -#define MAXWORKERTHREADS 64 -static swthread_t swthreads[MAXWORKERTHREADS]; - cvar_t sw_interlace = CVAR("sw_interlace", "0"); -cvar_t sw_threads = CVAR("sw_threads", "0"); +cvar_t sw_vthread = CVAR("sw_vthread", "0"); +cvar_t sw_fthreads = CVAR("sw_fthreads", "0"); -struct -{ - unsigned int numthreads; - qbyte queue[1024*1024*8]; - volatile unsigned int pos; -} wq; -#define WQ_MASK (sizeof(wq.queue)-1) +struct workqueue_s commandqueue; +struct workqueue_s spanqueue; static void WT_Triangle(swthread_t *th, swimage_t *img, swvert_t *v1, swvert_t *v2, swvert_t *v3) { @@ -594,14 +586,14 @@ qboolean WT_HandleCommand(swthread_t *t, wqcom_t *com) t->vpwidth = com->viewport.width; t->vpheight = com->viewport.height; t->vpcstride = com->viewport.stride; - if (!wq.numthreads) + if (!t->wq->numthreads) { t->interlacemod = com->viewport.interlace; //this many vthreads t->interlaceline = com->viewport.framenum%com->viewport.interlace; //this vthread } else { - t->interlacemod = wq.numthreads*com->viewport.interlace; //this many vthreads + t->interlacemod = t->wq->numthreads*com->viewport.interlace; //this many vthreads t->interlaceline = (t->threadnum*com->viewport.interlace) + (com->viewport.framenum%com->viewport.interlace); //this vthread } @@ -627,6 +619,8 @@ qboolean WT_HandleCommand(swthread_t *t, wqcom_t *com) WT_ClipTriangle(t, com->trisoup.texture, &com->trisoup.verts[idx[0]], &com->trisoup.verts[idx[1]], &com->trisoup.verts[idx[2]]); } break; + case WTC_SPANS: + break; default: Sys_Printf("Unknown render command!\n"); break; @@ -641,94 +635,105 @@ int WT_Main(void *ptr) swthread_t *t = ptr; for(;;) { - if (t->readpoint == wq.pos) + if (t->readpoint == t->wq->pos) { Sys_Sleep(0); continue; } - com = (wqcom_t*)&wq.queue[t->readpoint & WQ_MASK]; + com = (wqcom_t*)&t->wq->queue[t->readpoint & WQ_MASK]; if (WT_HandleCommand(t, com)) break; } return 0; } -void SWRast_EndCommand(wqcom_t *com) +void SWRast_EndCommand(struct workqueue_s *wq, wqcom_t *com) { - wq.pos += com->com.cmdsize; + wq->pos += com->com.cmdsize; - if (!wq.numthreads) + if (!wq->numthreads) { //immediate mode - WT_HandleCommand(swthreads, com); + WT_HandleCommand(wq->swthreads, com); } } -wqcom_t *SWRast_BeginCommand(int cmdtype, unsigned int size) +wqcom_t *SWRast_BeginCommand(struct workqueue_s *wq, int cmdtype, unsigned int size) { wqcom_t *com; //round the command size up, so we always have space for a noop/wrap if needed size = (size + sizeof(com->align)) & ~(sizeof(com->align)-1); //generate a noop if we don't have enough space for the command - if ((wq.pos&WQ_MASK) + size > sizeof(wq.queue)) + if ((wq->pos&WQ_MASK) + size > WQ_SIZE) { // SWRast_Sync(); - com = (wqcom_t *)&wq.queue[wq.pos&WQ_MASK]; - com->com.cmdsize = sizeof(wq.queue) - wq.pos&WQ_MASK; + com = (wqcom_t *)&wq->queue[wq->pos&WQ_MASK]; + com->com.cmdsize = WQ_SIZE - wq->pos&WQ_MASK; com->com.command = WTC_NOOP; - SWRast_EndCommand(com); + SWRast_EndCommand(wq, com); } - com = (wqcom_t *)&wq.queue[wq.pos&WQ_MASK]; + com = (wqcom_t *)&wq->queue[wq->pos&WQ_MASK]; com->com.cmdsize = size; com->com.command = cmdtype; return com; } -void SWRast_Sync(void) +void SWRast_Sync(struct workqueue_s *wq) { int i; swthread_t *t; - for (i = 0; i < wq.numthreads; i++) + for (i = 0; i < wq->numthreads; i++) { - t = &swthreads[i]; - while (t->readpoint != wq.pos) + t = &wq->swthreads[i]; + while (t->readpoint != wq->pos) ; } //all worker threads are up to speed } -void SWRast_CreateThreadPool(int numthreads) +void SWRast_CreateThreadPool(struct workqueue_s *wq, int numthreads) { int i = 0; swthread_t *t; - wq.pos = 0; - numthreads = ((numthreads > MAXWORKERTHREADS)?MAXWORKERTHREADS:numthreads); + wq->pos = 0; + numthreads = ((numthreads > WQ_MAXTHREADS)?WQ_MAXTHREADS:numthreads); #ifdef MULTITHREAD - for (; i < numthreads; i++) + for (i = 0; i < numthreads; i++) { - t = &swthreads[i]; + t = &wq->swthreads[i]; t->threadnum = i; - t->readpoint = wq.pos; t->thread = Sys_CreateThread(WT_Main, t, THREADP_NORMAL, 0); if (!t->thread) break; } +#else + numthreads = 0; #endif - wq.numthreads = i; + wq->numthreads = i; + + if (i == 0) + numthreads = 1; + else + numthreads = i; + for (i = 0; i < numthreads; i++) + { + wq->swthreads[i].readpoint = wq->pos; + wq->swthreads[i].wq = wq; + } } -void SWRast_TerminateThreadPool(void) +void SWRast_TerminateThreadPool(struct workqueue_s *wq) { int i; - wqcom_t *com = SWRast_BeginCommand(WTC_DIE, sizeof(com->com)); - SWRast_EndCommand(com); + wqcom_t *com = SWRast_BeginCommand(wq, WTC_DIE, sizeof(com->com)); + SWRast_EndCommand(wq, com); #ifdef MULTITHREAD - for (i = 0; i < wq.numthreads; i++) + for (i = 0; i < wq->numthreads; i++) { - Sys_WaitOnThread(swthreads[i].thread); + Sys_WaitOnThread(wq->swthreads[i].thread); } #endif - wq.numthreads = 0; + wq->numthreads = 0; } @@ -755,12 +760,12 @@ void SW_Draw_Shutdown(void) } void SW_R_Init(void) { - SWRast_CreateThreadPool(sw_threads.ival); - sw_threads.modified = false; + SWRast_CreateThreadPool(&commandqueue, sw_vthread.ival?1:0); + sw_vthread.modified = true; } void SW_R_DeInit(void) { - SWRast_TerminateThreadPool(); + SWRast_TerminateThreadPool(&commandqueue); } void SW_R_RenderView(void) { @@ -794,12 +799,7 @@ void SW_R_RenderView(void) RQ_BeginFrame(); - if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL)) - { - Surf_DrawWorld (); // adds static entities to the list - } - else - SWBE_DrawWorld(NULL); + Surf_DrawWorld (); // adds static entities to the list S_ExtraUpdate (); // don't let sound get messed up if going slow @@ -881,21 +881,28 @@ void SW_SCR_UpdateScreen(void) SWBE_Set2D(); - SWRast_Sync(); + SWRast_Sync(&commandqueue); + SWRast_Sync(&spanqueue); SW_VID_SwapBuffers(); - if (sw_threads.modified) + if (sw_vthread.modified) { - SWRast_TerminateThreadPool(); - SWRast_CreateThreadPool(sw_threads.ival); - sw_threads.modified = false; + SWRast_TerminateThreadPool(&commandqueue); + SWRast_CreateThreadPool(&commandqueue, sw_vthread.ival?1:0); + sw_vthread.modified = false; + } + if (sw_fthreads.modified) + { + SWRast_TerminateThreadPool(&spanqueue); + SWRast_CreateThreadPool(&spanqueue, sw_fthreads.ival); + sw_fthreads.modified = false; } - com = SWRast_BeginCommand(WTC_VIEWPORT, sizeof(com->viewport)); + com = SWRast_BeginCommand(&commandqueue, WTC_VIEWPORT, sizeof(com->viewport)); com->viewport.interlace = bound(0, sw_interlace.ival, 15)+1; com->viewport.clearcolour = r_clear.ival; com->viewport.cleardepth = true; SW_VID_UpdateViewport(com); - SWRast_EndCommand(com); + SWRast_EndCommand(&commandqueue, com); Shader_DoReload(); diff --git a/fteqtv/control.c b/fteqtv/control.c index 2dc70cac6..cb55dcf68 100644 --- a/fteqtv/control.c +++ b/fteqtv/control.c @@ -537,12 +537,8 @@ int main(int argc, char **argv) if (cluster->tcpsocket[0] == INVALID_SOCKET && cluster->tcpsocket[1] == INVALID_SOCKET && !cluster->tcplistenportnum) { cluster->tcplistenportnum = 27599; - cluster->tcpsocket[0] = Net_TCPListen(cluster->tcplistenportnum, false); - if (cluster->tcpsocket[0] != INVALID_SOCKET) - Sys_Printf(cluster, "opened tcp4 port %i\n", cluster->tcplistenportnum); - cluster->tcpsocket[1] = Net_TCPListen(cluster->tcplistenportnum, true); - if (cluster->tcpsocket[1] != INVALID_SOCKET) - Sys_Printf(cluster, "opened tcp6 port %i\n", cluster->tcplistenportnum); + Net_TCPListen(cluster, cluster->tcplistenportnum, true); + Net_TCPListen(cluster, cluster->tcplistenportnum, false); } Sys_Printf(cluster, "\n" diff --git a/fteqtv/dotnet2005/qtvprox.vcproj b/fteqtv/dotnet2005/qtvprox.vcproj index f01642364..de11e9241 100644 --- a/fteqtv/dotnet2005/qtvprox.vcproj +++ b/fteqtv/dotnet2005/qtvprox.vcproj @@ -44,8 +44,12 @@ Name="VCCLCompilerTool" Optimization="0" PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS" + ExceptionHandling="0" BasicRuntimeChecks="3" RuntimeLibrary="1" + EnableFunctionLevelLinking="true" + FloatingPointModel="2" + RuntimeTypeInfo="false" UsePrecompiledHeader="0" PrecompiledHeaderThrough="" PrecompiledHeaderFile="" diff --git a/fteqtv/msg.c b/fteqtv/msg.c index ccfc10daf..0e9dbc6d2 100644 --- a/fteqtv/msg.c +++ b/fteqtv/msg.c @@ -91,6 +91,20 @@ void ReadString(netmsg_t *b, char *string, int maxlen) while(ReadByte(b)) //finish reading the string, even if we will loose part of it ; } +float ReadCoord(netmsg_t *b, unsigned int pext) +{ + if (pext & PEXT_FLOATCOORDS) + return ReadFloat(b); + else + return ReadShort(b) / 8.0; +} +float ReadAngle(netmsg_t *b, unsigned int pext) +{ + if (pext & PEXT_FLOATCOORDS) + return (ReadShort(b) * 360.0) / 0x10000; + else + return (ReadByte(b) * 360.0) / 0x100; +} void WriteByte(netmsg_t *b, unsigned char c) { @@ -143,4 +157,17 @@ void WriteData(netmsg_t *b, const void *data, int length) *buf++ = ((unsigned char*)data)[i]; b->cursize+=length; } - +void WriteCoordf(netmsg_t *b, unsigned int pext, float fl) +{ + if (pext & PEXT_FLOATCOORDS) + WriteFloat(b, fl); + else + WriteShort(b, fl*8); +} +void WriteAnglef(netmsg_t *b, unsigned int pext, float fl) +{ + if (pext & PEXT_FLOATCOORDS) + WriteShort(b, (fl/360)*0x10000); + else + WriteByte(b, (fl/360)*0x100); +} \ No newline at end of file diff --git a/fteqtv/netchan.c b/fteqtv/netchan.c index eb01e67f3..6fcd7217b 100644 --- a/fteqtv/netchan.c +++ b/fteqtv/netchan.c @@ -21,10 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "qtv.h" #include -#ifndef IPV6_V6ONLY - #define IPV6_V6ONLY 27 -#endif - #define curtime Sys_Milliseconds() diff --git a/fteqtv/parse.c b/fteqtv/parse.c index 26cbd76b5..61ff52ed7 100644 --- a/fteqtv/parse.c +++ b/fteqtv/parse.c @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "bsd_string.h" -#define ParseError(m) (m)->cursize = (m)->cursize+1 // +#define ParseError(m) (m)->readpos = (m)->cursize+1 // void SendBufferToViewer(viewer_t *v, const char *buffer, int length, qboolean reliable) { @@ -114,17 +114,83 @@ void ConnectionData(sv_t *tv, void *buffer, int length, int to, unsigned int pla static void ParseServerData(sv_t *tv, netmsg_t *m, int to, unsigned int playermask) { - int protocol; + unsigned int protocol; + unsigned int supported; viewer_t *v; //free the old map state QTV_CleanupMap(tv); - protocol = ReadLong(m); - if (protocol != PROTOCOL_VERSION) + tv->pext = 0; + + for(;;) { - ParseError(m); - return; + protocol = ReadLong(m); + switch (protocol) + { + case PROTOCOL_VERSION: + break; + case PROTOCOL_VERSION_FTE: + protocol = ReadLong(m); + tv->pext = protocol; + + supported = PEXT_SETVIEW|PEXT_ACCURATETIMINGS; /*simple forwarding*/ + supported |= PEXT_256PACKETENTITIES|PEXT_VIEW2|PEXT_HLBSP|PEXT_Q2BSP|PEXT_Q3BSP; //features other than the protocol (stats, simple limits etc) + + //supported |= PEXT_FLOATCOORDS|PEXT_TRANS|PEXT_MODELDBL|PEXT_ENTITYDBL|PEXT_ENTITYDBL2; //things we ought to support, but do not + + if (protocol & PEXT_FLOATCOORDS) + { + Sys_Printf(tv->cluster, "ParseMessage: PROTOCOL_VERSION_FTE (PEXT_FLOATCOORDS) not supported\n"); + supported |= PEXT_FLOATCOORDS; + } + if (protocol & ~supported) + Sys_Printf(tv->cluster, "ParseMessage: PROTOCOL_VERSION_FTE (%x) not supported\n", protocol & ~supported); + continue; + case PROTOCOL_VERSION_FTE2: + protocol = ReadLong(m); + supported = 0; +// supported |= PEXT2_PRYDONCURSOR|PEXT2_VOICECHAT|PEXT2_SETANGLEDELTA|PEXT2_REPLACEMENTDELTAS|PEXT2_MAXPLAYERS; + + if (protocol & ~supported) + Sys_Printf(tv->cluster, "ParseMessage: PROTOCOL_VERSION_FTE2 (%x) not supported\n", protocol & ~supported); + continue; + case PROTOCOL_VERSION_HUFFMAN: + Sys_Printf(tv->cluster, "ParseMessage: PROTOCOL_VERSION_HUFFMAN not supported\n", protocol); + ParseError(m); + return; + case PROTOCOL_VERSION_VARLENGTH: + { + int len = ReadLong(m); + if (len < 0 || len > 8192) + { + Sys_Printf(tv->cluster, "ParseMessage: PROTOCOL_VERSION_VARLENGTH invalid\n"); + ParseError(m); + return; + } + protocol = ReadLong(m);/*ident*/ + switch(protocol) + { + default: + m->readpos += len; + + Sys_Printf(tv->cluster, "ParseMessage: PROTOCOL_VERSION_VARLENGTH (%x) not supported\n", protocol); + ParseError(m); + return; + } + } + continue; + case PROTOCOL_VERSION_FRAGMENT: + protocol = ReadLong(m); + Sys_Printf(tv->cluster, "ParseMessage: PROTOCOL_VERSION_FRAGMENT not supported\n", protocol); + ParseError(m); + return; + default: + Sys_Printf(tv->cluster, "ParseMessage: Unknown protocol version %x\n", protocol); + ParseError(m); + return; + } + break; } tv->mapstarttime = tv->parsetime; @@ -1273,15 +1339,15 @@ static void ParseTempEntity(sv_t *tv, netmsg_t *m, int to, unsigned int mask) switch(i) { case TE_SPIKE: - ReadShort (m); - ReadShort (m); - ReadShort (m); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); dest |= NQ; break; case TE_SUPERSPIKE: - ReadShort (m); - ReadShort (m); - ReadShort (m); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); dest |= NQ; break; case TE_GUNSHOT: @@ -1295,15 +1361,15 @@ static void ParseTempEntity(sv_t *tv, netmsg_t *m, int to, unsigned int mask) nqversionlength = 8; break; case TE_EXPLOSION: - ReadShort (m); - ReadShort (m); - ReadShort (m); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); dest |= NQ; break; case TE_TAREXPLOSION: - ReadShort (m); - ReadShort (m); - ReadShort (m); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); dest |= NQ; break; case TE_LIGHTNING1: @@ -1311,49 +1377,51 @@ static void ParseTempEntity(sv_t *tv, netmsg_t *m, int to, unsigned int mask) case TE_LIGHTNING3: ReadShort (m); - ReadShort (m); - ReadShort (m); - ReadShort (m); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); - ReadShort (m); - ReadShort (m); - ReadShort (m); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); dest |= NQ; break; case TE_WIZSPIKE: - ReadShort (m); - ReadShort (m); - ReadShort (m); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); dest |= NQ; break; case TE_KNIGHTSPIKE: - ReadShort (m); - ReadShort (m); - ReadShort (m); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); dest |= NQ; break; case TE_LAVASPLASH: - ReadShort (m); - ReadShort (m); - ReadShort (m); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); dest |= NQ; break; case TE_TELEPORT: - ReadShort (m); - ReadShort (m); - ReadShort (m); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); dest |= NQ; break; case TE_BLOOD: ReadByte (m); - ReadShort (m); - ReadShort (m); - ReadShort (m); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); + //FIXME: generate svc_particle for nq break; case TE_LIGHTNINGBLOOD: - ReadShort (m); - ReadShort (m); - ReadShort (m); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); + ReadCoord (m, tv->pext); + //FIXME: generate svc_particle for nq break; default: Sys_Printf(tv->cluster, "temp entity %i not recognised\n", i); diff --git a/fteqtv/protocol.h b/fteqtv/protocol.h index ccf460c88..d22c49e23 100644 --- a/fteqtv/protocol.h +++ b/fteqtv/protocol.h @@ -206,6 +206,54 @@ enum { #define PROTOCOL_VERSION_NQ 15 #define PROTOCOL_VERSION 28 +#define PROTOCOL_VERSION_FTE (('F'<<0) + ('T'<<8) + ('E'<<16) + ('X' << 24)) //fte extensions. +#define PROTOCOL_VERSION_FTE2 (('F'<<0) + ('T'<<8) + ('E'<<16) + ('2' << 24)) //fte extensions. +#define PROTOCOL_VERSION_HUFFMAN (('H'<<0) + ('U'<<8) + ('F'<<16) + ('F' << 24)) //packet compression +#define PROTOCOL_VERSION_VARLENGTH (('v'<<0) + ('l'<<8) + ('e'<<16) + ('n' << 24)) //variable length handshake +#define PROTOCOL_VERSION_FRAGMENT (('F'<<0) + ('R'<<8) + ('A'<<16) + ('G' << 24)) //supports fragmentation/packets larger than 1450 + + + +#define PEXT_SETVIEW 0x00000001 +#define PEXT_SCALE 0x00000002 +#define PEXT_LIGHTSTYLECOL 0x00000004 +#define PEXT_TRANS 0x00000008 +#define PEXT_VIEW2 0x00000010 +//#define PEXT_BULLETENS 0x00000020 //obsolete +#define PEXT_ACCURATETIMINGS 0x00000040 +#define PEXT_SOUNDDBL 0x00000080 //revised startsound protocol +#define PEXT_FATNESS 0x00000100 //GL only (or servers) +#define PEXT_HLBSP 0x00000200 +#define PEXT_TE_BULLET 0x00000400 +#define PEXT_HULLSIZE 0x00000800 +#define PEXT_MODELDBL 0x00001000 +#define PEXT_ENTITYDBL 0x00002000 //max of 1024 ents instead of 512 +#define PEXT_ENTITYDBL2 0x00004000 //max of 1024 ents instead of 512 +#define PEXT_FLOATCOORDS 0x00008000 //supports floating point origins. +//#define PEXT_VWEAP 0x00010000 //cause an extra qbyte to be sent, and an extra list of models for vweaps. +#define PEXT_Q2BSP 0x00020000 +#define PEXT_Q3BSP 0x00040000 +#define PEXT_COLOURMOD 0x00080000 //this replaces an older value which would rarly have caried any actual data. +#define PEXT_SPLITSCREEN 0x00100000 +#define PEXT_HEXEN2 0x00200000 //more stats and working particle builtin. +#define PEXT_SPAWNSTATIC2 0x00400000 //Sends an entity delta instead of a baseline. +#define PEXT_CUSTOMTEMPEFFECTS 0x00800000 //supports custom temp ents. +#define PEXT_256PACKETENTITIES 0x01000000 //Client can recieve 256 packet entities. +//#define PEXT_NEVERUSED 0x02000000 +#define PEXT_SHOWPIC 0x04000000 +#define PEXT_SETATTACHMENT 0x08000000 //md3 tags (needs networking, they need to lerp). +//#define PEXT_NEVERUSED 0x10000000 +#define PEXT_CHUNKEDDOWNLOADS 0x20000000 //alternate file download method. Hopefully it'll give quadroupled download speed, especially on higher pings. +#define PEXT_CSQC 0x40000000 //csqc additions +#define PEXT_DPFLAGS 0x80000000 //extra flags for viewmodel/externalmodel and possible other persistant style flags. + +#define PEXT2_PRYDONCURSOR 0x00000001 +#define PEXT2_VOICECHAT 0x00000002 +#define PEXT2_SETANGLEDELTA 0x00000004 +#define PEXT2_REPLACEMENTDELTAS 0x00000008 +#define PEXT2_MAXPLAYERS 0x00000010 //Client is able to cope with more players than 32. abs max becomes 255, due to colormap issues. +//#define PEXT2_PK3DOWNLOADS 0x10000000 //retrieve a list of pk3s/pk3s/paks for downloading (with optional URL and crcs) + //flags on entities #define U_ORIGIN1 (1<<9) diff --git a/fteqtv/qtv.h b/fteqtv/qtv.h index e79bd9b8e..e90eb9bc1 100644 --- a/fteqtv/qtv.h +++ b/fteqtv/qtv.h @@ -192,6 +192,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef EAGAIN #define EAGAIN EWOULDBLOCK #endif +#ifndef IPV6_V6ONLY + #define IPV6_V6ONLY 27 +#endif #ifndef pgetaddrinfo #ifndef _WIN32 @@ -602,6 +605,7 @@ struct sv_s { //details about a server connection (also known as stream) qboolean silentstream; qboolean usequakeworldprotocols; + unsigned int pext; int challenge; unsigned short qport; int isconnected; @@ -904,7 +908,7 @@ void Sys_Printf(cluster_t *cluster, char *fmt, ...) PRINTFWARNING(2); void Net_ProxySend(cluster_t *cluster, oproxy_t *prox, void *buffer, int length); oproxy_t *Net_FileProxy(sv_t *qtv, char *filename); sv_t *QTV_NewServerConnection(cluster_t *cluster, int streamid, char *server, char *password, qboolean force, enum autodisconnect_e autodisconnect, qboolean noduplicates, qboolean query); -SOCKET Net_TCPListen(int port, qboolean ipv6); +void Net_TCPListen(cluster_t *cluster, int port, qboolean ipv6); qboolean Net_StopFileProxy(sv_t *qtv); diff --git a/fteqtv/qw.c b/fteqtv/qw.c index 58b4d0da5..be68e94c9 100644 --- a/fteqtv/qw.c +++ b/fteqtv/qw.c @@ -3100,47 +3100,11 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean } else if (!strcmp(v->expectcommand, "setmvdport")) { - int newp; - SOCKET news; + int newp = atoi(message); - newp = atoi(message); - - - if (newp) - { - news = Net_TCPListen(newp, true); - - if (news != INVALID_SOCKET) - { - if (cluster->tcpsocket[1] != INVALID_SOCKET) - closesocket(cluster->tcpsocket[1]); - cluster->tcpsocket[1] = news; - cluster->tcplistenportnum = newp; - } - } - else if (cluster->tcpsocket[1] != INVALID_SOCKET) - { - closesocket(cluster->tcpsocket[1]); - cluster->tcpsocket[1] = INVALID_SOCKET; - } - - if (newp) - { - news = Net_TCPListen(newp, false); - - if (news != INVALID_SOCKET) - { - if (cluster->tcpsocket[0] != INVALID_SOCKET) - closesocket(cluster->tcpsocket[0]); - cluster->tcpsocket[0] = news; - cluster->tcplistenportnum = newp; - } - } - else if (cluster->tcpsocket[0] != INVALID_SOCKET) - { - closesocket(cluster->tcpsocket[0]); - cluster->tcpsocket[0] = INVALID_SOCKET; - } + Net_TCPListen(cluster, newp, true); + Net_TCPListen(cluster, newp, false); + cluster->tcplistenportnum = newp; } else { diff --git a/fteqtv/rcon.c b/fteqtv/rcon.c index 342d49800..3ed8285e2 100644 --- a/fteqtv/rcon.c +++ b/fteqtv/rcon.c @@ -1010,64 +1010,23 @@ void Cmd_Reconnect(cmdctxt_t *ctx) void Cmd_MVDPort(cmdctxt_t *ctx) { char *val = Cmd_Argv(ctx, 1); - int news; int newp = atoi(val); + if (!*val) + { + Cmd_Printf(ctx, "Listening for tcp connections on port %i\n", ctx->cluster->tcplistenportnum); + return; + } + if (!newp) { if (ctx->cluster->tcpsocket[0] != INVALID_SOCKET && ctx->cluster->tcpsocket[1] != INVALID_SOCKET) Cmd_Printf(ctx, "Already closed\n"); - - if (ctx->cluster->tcpsocket[0] != INVALID_SOCKET) - { - closesocket(ctx->cluster->tcpsocket[0]); - ctx->cluster->tcpsocket[0] = INVALID_SOCKET; - ctx->cluster->tcplistenportnum = 0; - - Cmd_Printf(ctx, "tcp4 port is now closed\n"); - } - - if (ctx->cluster->tcpsocket[1] != INVALID_SOCKET) - { - closesocket(ctx->cluster->tcpsocket[1]); - ctx->cluster->tcpsocket[1] = INVALID_SOCKET; - ctx->cluster->tcplistenportnum = 0; - - Cmd_Printf(ctx, "tcp6 port is now closed\n"); - } } - else - { - news = Net_TCPListen(newp, false); - - if (news != INVALID_SOCKET) - { - if (ctx->cluster->tcpsocket[0] != INVALID_SOCKET) - closesocket(ctx->cluster->tcpsocket[0]); - ctx->cluster->tcpsocket[0] = news; - ctx->cluster->tcplistenportnum = newp; - - Cmd_Printf(ctx, "Opened tcp4 port %i\n", newp); - } - else - Cmd_Printf(ctx, "Failed to open tcp4 port %i\n", newp); - - news = Net_TCPListen(newp, true); - - if (news != INVALID_SOCKET) - { - if (ctx->cluster->tcpsocket[1] != INVALID_SOCKET) - closesocket(ctx->cluster->tcpsocket[1]); - ctx->cluster->tcpsocket[1] = news; - ctx->cluster->tcplistenportnum = newp; - - Cmd_Printf(ctx, "Opened tcp6 port %i\n", newp); - } - else - Cmd_Printf(ctx, "Failed to open tcp6 port %i\n", newp); - - } + Net_TCPListen(ctx->cluster, newp, true); + Net_TCPListen(ctx->cluster, newp, false); + ctx->cluster->tcplistenportnum = newp; } void Cmd_DemoList(cmdctxt_t *ctx) diff --git a/fteqtv/source.c b/fteqtv/source.c index ada557969..74e72deff 100644 --- a/fteqtv/source.c +++ b/fteqtv/source.c @@ -237,7 +237,7 @@ qboolean Net_CompareAddress(netadr_t *s1, netadr_t *s2, int qp1, int qp2) return false; } -SOCKET Net_TCPListen(int port, qboolean ipv6) +void Net_TCPListen(cluster_t *cluster, int port, qboolean ipv6) { SOCKET sock; @@ -249,6 +249,7 @@ SOCKET Net_TCPListen(int port, qboolean ipv6) // int fromlen; unsigned long nonblocking = true; + unsigned long v6only = false; if (ipv6) { @@ -269,19 +270,43 @@ SOCKET Net_TCPListen(int port, qboolean ipv6) addrsize = sizeof(struct sockaddr_in); } + if (!ipv6 && !v6only && cluster->tcpsocket[1] != INVALID_SOCKET) + { + int sz = sizeof(v6only); + if (getsockopt(cluster->tcpsocket[1], IPPROTO_IPV6, IPV6_V6ONLY, (char *)&v6only, &sz) == 0 && !v6only) + port = 0; + } + if (cluster->tcpsocket[ipv6] != INVALID_SOCKET) + { + closesocket(cluster->tcpsocket[ipv6]); + cluster->tcpsocket[ipv6] = INVALID_SOCKET; + + if (v6only) + Sys_Printf(cluster, "closed tcp%i port\n", ipv6?6:4); + else + Sys_Printf(cluster, "closed tcp port\n"); + } + if (!port) + return; if ((sock = socket (prot, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { - return INVALID_SOCKET; + cluster->tcpsocket[ipv6] = INVALID_SOCKET; + return; } if (ioctlsocket (sock, FIONBIO, &nonblocking) == -1) { + cluster->tcpsocket[ipv6] = INVALID_SOCKET; closesocket(sock); - return INVALID_SOCKET; + return; } + if (prot == AF_INET6) + if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&v6only, sizeof(v6only)) == -1) + v6only = true; + if (bind (sock, address, addrsize) == -1) { printf("socket bind error %i (%s)\n", qerrno, strerror(qerrno)); @@ -291,7 +316,12 @@ SOCKET Net_TCPListen(int port, qboolean ipv6) listen(sock, 2); //don't listen for too many clients. - return sock; + if (v6only) + Sys_Printf(cluster, "opened tcp%i port %i\n", ipv6?6:4, port); + else + Sys_Printf(cluster, "opened tcp port %i\n", port); + + cluster->tcpsocket[ipv6] = sock; } char *strchrrev(char *str, char chr) @@ -453,6 +483,12 @@ qboolean Net_ConnectToTCPServer(sv_t *qtv, char *ip) return false; } + if (afam == AF_INET6) + { + qboolean v6only = true; + setsockopt(qtv->sourcesock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&v6only, sizeof(v6only)); + } + memset(&from, 0, sizeof(from)); ((struct sockaddr*)&from)->sa_family = afam; if (bind(qtv->sourcesock, (struct sockaddr *)&from, sizeof(from)) == -1) @@ -510,6 +546,12 @@ qboolean Net_ConnectToUDPServer(sv_t *qtv, char *ip) if (qtv->sourcesock == INVALID_SOCKET) return false; + if (afam == AF_INET6) + { + qboolean v6only = true; + setsockopt(qtv->sourcesock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&v6only, sizeof(v6only)); + } + memset(&from, 0, sizeof(from)); ((struct sockaddr*)&from)->sa_family = afam; if (bind(qtv->sourcesock, (struct sockaddr *)&from, asz) == -1) @@ -622,6 +664,7 @@ qboolean Net_ConnectToServer(sv_t *qtv) char *ip = Net_DiagnoseProtocol(qtv); qtv->usequakeworldprotocols = false; + qtv->pext = 0; if (qtv->sourcetype == SRC_DEMO) qtv->nextconnectattempt = qtv->curtime + RECONNECT_TIME_DEMO; //wait half a minuite before trying to reconnect diff --git a/specs/modmaking.txt b/specs/modmaking.txt index 18cff6d8e..74d5acb03 100644 --- a/specs/modmaking.txt +++ b/specs/modmaking.txt @@ -16,8 +16,8 @@ You can also 'compile csprogs.src' if you want to compile, eg, a csqc mod. Additionally, the 'applycompile' basically does a quick savegame, effectively applying a newly compiled mod without restarting a map. This is useful if you just want to test a single repeatable function without booting players or anything - this won't automagically change any fields! Multiplayer testing: -Unlike other engines, FTE permits multiple instances of itself. -(Note that ezquake will not start up if FTE is already running, but FTE will start up if ezquake is, so if you want to test ezquake+FTE compatibility, start ezquake first). +Unlike other QuakeWorld engines, FTE permits multiple instances of itself. +(Note that other quakeworld engines will refuse to start up if FTE is already running, but FTE will start up if they are running, so if you want to test ezquake+FTE compatibility, start ezquake first). Also... FTE supports splitscreen! This can simplify testing multiplayer when you can't be bothered switching between two clients. Mostly this should be documented elsewhere, but here's the basics. diff --git a/specs/particles.txt b/specs/particles.txt index 8e76cae7c..c1e4fa1a2 100644 --- a/specs/particles.txt +++ b/specs/particles.txt @@ -72,7 +72,7 @@ alpha alphadelta specifies how much the alpha value of the effect changes per second (subtracted) -die +die specifies the maximum age of the particle diesubrand @@ -215,10 +215,10 @@ spawnmode [arg1] [arg2] *default*: particles spawn as a regular trail. spawnparam1 - obsolete + obsolete. see spawnmode. spawnparam2 - obsolete + obsolete. see spawnmode. up the particle's origin is moved upwards by this amount