d3d11 fixes. mipmapping implemented, vertex streaming more performant. Still behind the d3d9 renderer.

Fixed d3d11 vs d3d9 conflicts when switching renderers.
Fixed hlsl-less d3d9 lava.
Added gl_specular_fallback to override the default gloss level.
Added these cvars to give more control over imported/dlight lighting r_shadow_realtime_dlight_ambient r_shadow_realtime_dlight_diffuse r_shadow_realtime_dlight_specular r_editlights_import_radius r_editlights_import_ambient r_editlights_import_diffuse r_editlights_import_specular. Effective value of r_editlights_import_specular is now 1. Was 4.
Fixed spot/cube/smap lights.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4160 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2012-12-04 19:37:57 +00:00
parent 52bacf161b
commit 95266f8215
34 changed files with 896 additions and 808 deletions

View File

@ -116,7 +116,7 @@ ifeq ($(FTE_TARGET),droid)
endif
STRIP=$(TOOLCHAIN)strip
CC=$(TOOLCHAIN)gcc -I$(NDK_PATH)/platforms/android-$(DROID_API_LEVEL)/$(DROID_PLAT_INC)/usr/include/ -DANDROID $(DROID_ABI)
CC=$(TOOLCHAIN)gcc -I$(NDK_PATH)/platforms/android-$(DROID_API_LEVEL)/$(DROID_PLAT_INC)/usr/include/ -DANDROID $(DROID_ABI) -fno-strict-aliasing
DO_LD=$(CC) -Wl,-soname,libftedroid.so -shared -Wl,--no-undefined -Wl,-z,noexecstack --sysroot=$(NDK_PATH)/platforms/android-$(DROID_API_LEVEL)/$(DROID_PLAT_INC) -L$(NDK_PATH)/platforms/android-$(DROID_API_LEVEL)/$(DROID_PLAT_INC)/usr/lib -o $@ $(LTO_LD) $(WCFLAGS) $(CFLAGS) -llog -lc -lz -lm
endif
@ -338,7 +338,7 @@ else
GNUC_FUNCS= -Dstrnicmp=strncasecmp -Dstricmp=strcasecmp
endif
BASE_CFLAGS=$(WARNINGFLAGS) $(GNUC_FUNCS) -I$(CLIENT_DIR) -I$(SERVER_DIR) -I$(COMMON_DIR) -I$(GL_DIR) -I$(D3D_DIR) -I$(PROGS_DIR) -I$(BOTLIB_DIR) -I$(LIBS_DIR) -I$(LIBS_DIR)/dxsdk9/include -I$(LIBS_DIR)/sdl/include -I/usr/include/SDL -I$(LIBS_DIR)/sdl/include/SDL -I./libs/freetype2/include -I./libs/freetype2/include/freetype -I./libs/speex -DBOTLIB $(SVNREVISION)
BASE_CFLAGS=$(WARNINGFLAGS) $(GNUC_FUNCS) -I$(CLIENT_DIR) -I$(SERVER_DIR) -I$(COMMON_DIR) -I$(GL_DIR) -I$(D3D_DIR) -I$(PROGS_DIR) -I$(BOTLIB_DIR) -I$(LIBS_DIR) -I$(LIBS_DIR)/dxsdk9/include -I$(LIBS_DIR)/dxsdk7/include -I$(LIBS_DIR)/sdl/include -I/usr/include/SDL -I$(LIBS_DIR)/sdl/include/SDL -I./libs/freetype2/include -I./libs/freetype2/include/freetype -I./libs/speex -DBOTLIB $(SVNREVISION)
CLIENT_ONLY_CFLAGS=-DCLIENTONLY
SERVER_ONLY_CFLAGS=-DSERVERONLY
JOINT_CFLAGS=
@ -356,7 +356,7 @@ PROFILE_CFLAGS=-pg
DX7SDK=-I./libs/dxsdk7/include/
GLCFLAGS=-DGLQUAKE
D3DCFLAGS=-DD3D9QUAKE
D3DCFLAGS=-DD3D9QUAKE -DD3D11QUAKE
NPFTECFLAGS=-DNPFTE
SPEEXCFLAGS=-DSPEEX_STATIC -I$(BASE_DIR)/libs/speex/include -DFIXED_POINT -DUSE_KISS_FFT -DEXPORT=""
@ -755,32 +755,68 @@ endif
#FTE_TARGET=vc (Visual C)
ifeq ($(FTE_TARGET),vc)
CC=cl
ifeq ($(BITS),64)
WINDRES=x86_64-w64-mingw32-windres
MSVCPATH=C:/Program Files (x86)/Microsoft Visual Studio 8/VC/BIN/amd64/
MSVCINC=-I"C:\Program Files (x86)\Microsoft Visual Studio 8\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 8\VC\PlatformSDK\include" -I"C:\Program Files (x86)\Microsoft Visual Studio 8\SDK\v2.0\include"
MSVCLIB=/LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio 8\VC\ATLMFC\LIB\amd64" /LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio 8\VC\LIB\amd64" /LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio 8\VC\PlatformSDK\lib\amd64" /LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio 8\SDK\v2.0\LIB\AMD64"
JPEGLIB=libs/libjpeg$(BITS).lib
else
MSVCPATH=C:/Program Files (x86)/Microsoft Visual Studio 8/VC/BIN/
MSVCINC=-I"C:\Program Files (x86)\Microsoft Visual Studio 8\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 8\VC\PlatformSDK\include" -I"C:\Program Files (x86)\Microsoft Visual Studio 8\SDK\v2.0\include"
MSVCLIB=/LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio 8\VC\ATLMFC\LIB" /LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio 8\VC\LIB" /LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio 8\VC\PlatformSDK\lib" /LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio 8\SDK\v2.0\LIB"
JPEGLIB=libs/jpeg.lib
endif
STRIP=@echo strip
CC="$(MSVCPATH)cl" $(MSVCINC) -D_CRT_SECURE_NO_WARNINGS
DEBUG_CFLAGS ?= -Od $(CPUOPTIMIZATIONS) /fp:fast
PROFILE_CFLAGS = -O2 -Ot -Ox -GL $(CPUOPTIMISATIONS) /fp:fast
PROFILE_LDFLAGS = /LTCG:PGINSTRUMENT
RELEASE_CFLAGS = -O2 -Ot -Ox -GL $(CPUOPTIMIZATIONS) /fp:fast
RELEASE_LDFLAGS = /LTCG:PGOPTIMIZE
DO_CC=@$(CC) /nologo $(ALL_CFLAGS) -Fo$@ -c $<
DO_LD=link /nologo /out:$@ wsock32.lib user32.lib advapi32.lib winmm.lib libs/zlib.lib shell32.lib /nodefaultlib:libc.lib /nodefaultlib:MSVCRT /manifest:no /OPT:REF
DO_LD=@"$(MSVCPATH)link" /nologo /out:"$@" /nodefaultlib:libc.lib /nodefaultlib:MSVCRT $(MSVCLIB) /manifest:no /OPT:REF wsock32.lib user32.lib advapi32.lib winmm.lib libs/zlib$(BITS).lib shell32.lib
PRECOMPHEADERS =
NODEPS = 1
LIBS_DIR=./libs/
SV_CFLAGS=$(SERVER_ONLY_CFLAGS) $(W32_CFLAGS)
SV_EXE_NAME=../fteqwsv.exe
SV_DIR=sv_vc
SPEEXCFLAGS+= -Dinline=_inline -D_USE_MATH_DEFINES
SV_CFLAGS=$(SERVER_ONLY_CFLAGS) $(W32_CFLAGS) -DMULTITHREAD -DMSVCLIBSPATH="libs/"
SV_EXE_NAME=../fteqwsv$(BITS).exe
SV_DIR=sv_vc$(BITS)
SV_OBJS=$(COMMON_OBJS) $(SERVER_OBJS) $(PROGS_OBJS) $(WINDOWSSERVERONLY_OBJS) fs_win32.o resources.o
SV_LDFLAGS=/subsystem:console
GL_EXE_NAME=../fteglqw$(BITS).exe
GLCL_EXE_NAME=../minfteqw.gl$(BITS)
GLB_DIR=gl_vc$(BITS)
GLCL_DIR=glcl_vc$(BITS)
GL_LDFLAGS=$(GLLDFLAGS) $(JPEGLIB) libs/libpng$(BITS).lib uuid.lib gdi32.lib ole32.lib /subsystem:windows
GL_CFLAGS=$(GLCFLAGS) $(W32_CFLAGS) -DMULTITHREAD $(SPEEXCFLAGS) -DMSVCLIBSPATH="libs/"
GLCL_OBJS=$(D3DGL_OBJS) $(GLQUAKE_OBJS) $(SPEEX_OBJS) gl_vidnt.o snd_win.o snd_directx.o cd_win.o fs_win32.o in_win.o sys_win.o sys_win_threads.o resources.o
GL_OBJS=
D3DCL_OBJS=$(D3DQUAKE_OBJS) $(SPEEX_OBJS) snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o sys_win_threads.o $(D3DGL_OBJS) fs_win32.o $(LTO_END) resources.o $(LTO_START)
D3D_EXE_NAME=../fted3dqw$(BITS).exe
D3DCL_EXE_NAME=../fted3dclqw$(BITS).exe
D3D_LDFLAGS=$(JPEGLIB) libs/libpng$(BITS).lib uuid.lib gdi32.lib ole32.lib
D3D_CFLAGS=$(D3DCFLAGS) $(W32_CFLAGS) $(DX7SDK) -DMULTITHREAD $(SPEEXCFLAGS) -DMSVCLIBSPATH="libs/"
D3DB_DIR=d3d_vc$(BITS)
D3DCL_DIR=d3dcl_vc$(BITS)
M_EXE_NAME=../fteqw.exe
MCL_OBJS=$(GL_OBJS) $(D3DGL_OBJS) $(GLQUAKE_OBJS) fs_win32.o gl_vidnt.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o sys_win_threads.o resources.o
M_CFLAGS=$(GLCFLAGS) $(W32_CFLAGS) $(D3DCFLAGS)
MB_DIR=m_vc
M_LDFLAGS=$(GLLDFLAGS) libs/jpeg.lib libs/libpng.lib libs/zlib.lib uuid.lib gdi32.lib ole32.lib /subsystem:windows
M_EXE_NAME=../fteqw$(BITS).exe
MCL_OBJS=$(GL_OBJS) $(D3DGL_OBJS) $(D3DQUAKE_OBJS) $(GLQUAKE_OBJS) $(SPEEX_OBJS) fs_win32.o gl_vidnt.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o sys_win_threads.o resources.o
M_CFLAGS=$(D3DCFLAGS) $(GLCFLAGS) $(W32_CFLAGS) $(D3DCFLAGS) -DMULTITHREAD $(SPEEXCFLAGS) -DMSVCLIBSPATH="libs/"
MB_DIR=m_vc$(BITS)
M_LDFLAGS=$(GLLDFLAGS) $(JPEGLIB) libs/libpng$(BITS).lib uuid.lib gdi32.lib ole32.lib /subsystem:windows
endif
#FTE_TARGET=win32 | FTE_TARGET=win64 (MinGW32 | MinGW64)

View File

@ -127,9 +127,9 @@ static void CL_ClearDlight(dlight_t *dl, int key)
dl->color[2] = 1;
dl->corona = r_flashblend.value * 0.25;
dl->coronascale = r_flashblendscale.value;
dl->lightcolourscales[0] = 0;
dl->lightcolourscales[1] = 1;
dl->lightcolourscales[2] = 4;
dl->lightcolourscales[0] = r_shadow_realtime_dlight_ambient.value;
dl->lightcolourscales[1] = r_shadow_realtime_dlight_diffuse.value;
dl->lightcolourscales[2] = r_shadow_realtime_dlight_specular.value;
// if (r_shadow_realtime_dlight_shadowmap.value)
// dl->flags |= LFLAG_SHADOWMAP;
}

View File

@ -3039,7 +3039,9 @@ void CL_FTP_f(void)
void CL_Fog_f(void)
{
if (Cmd_Argc() <= 1)
if (cl.fog_locked && !Cmd_FromGamecode())
Con_Printf("Current fog %f (r:%f g:%f b:%f)\n", cl.fog_density, cl.fog_colour[0], cl.fog_colour[1], cl.fog_colour[2]);
else if (Cmd_Argc() <= 1)
{
Con_Printf("Current fog %f (r:%f g:%f b:%f)\n", cl.fog_density, cl.fog_colour[0], cl.fog_colour[1], cl.fog_colour[2]);
}
@ -3052,6 +3054,9 @@ void CL_Fog_f(void)
cl.fog_colour[1] = atof(Cmd_Argv(3));
cl.fog_colour[2] = atof(Cmd_Argv(4));
}
if (Cmd_FromGamecode())
cl.fog_locked = !!cl.fog_density;
}
}

View File

@ -6403,6 +6403,7 @@ void CLNQ_ParseServerMessage (void)
cl.fog_colour[1] = MSG_ReadByte()/255.0f;
cl.fog_colour[2] = MSG_ReadByte()/255.0f;
/*time =*/ MSG_ReadShort();
cl.fog_locked = !!cl.fog_density;
break;
case svcfitz_spawnbaseline2:
i = MSG_ReadShort ();

View File

@ -1661,8 +1661,11 @@ void CL_SpawnCustomTEnd(custtentinst_t *info)
vec3_t org;
int i, j;
//FIXME: pvs cull
if (t->particleeffecttype != -1)
if (t->particleeffecttype == -1)
failed = true;
else
{
failed = false;
for (i=0 ; i<info->count ; i++)
{
for (j=0 ; j<3 ; j++)
@ -1670,7 +1673,7 @@ void CL_SpawnCustomTEnd(custtentinst_t *info)
org[j] = info->pos[j] + (info->pos2[j] - info->pos[j])*frandom();
}
P_RunParticleEffectType(org, info->dir, 1, t->particleeffecttype);
failed |= P_RunParticleEffectType(org, info->dir, 1, t->particleeffecttype);
}
}
}

View File

@ -647,6 +647,7 @@ typedef struct
float skyrotate;
vec3_t skyaxis;
qboolean fog_locked;
float fog_density;
vec3_t fog_colour;

View File

@ -129,6 +129,8 @@ void R2D_Init(void)
{
unsigned int nogloss[4*4];
int i;
unsigned int glossval;
extern cvar_t gl_specular_fallback;
conback = NULL;
Shader_Init();
@ -149,8 +151,12 @@ void R2D_Init(void)
#pragma warningmsg("Fixme: move conwidth handling into here")
#endif
glossval = min(gl_specular_fallback.value*255, 255);
glossval *= 0x10101;
glossval |= 0xff000000;
glossval = LittleLong(glossval);
for (i = 0; i < 4*4; i++)
nogloss[i] = LittleLong(0xff101010);
nogloss[i] = glossval;
missing_texture = R_LoadTexture8("no_texture", 16, 16, (unsigned char*)r_notexture_mip + r_notexture_mip->offsets[0], IF_NOALPHA|IF_NOGAMMA, 0);
missing_texture_gloss = R_LoadTexture("no_texture_gloss", 4, 4, TF_RGBA32, (unsigned char*)nogloss, IF_NOGAMMA);
translate_texture = r_nulltex;

View File

@ -423,7 +423,14 @@ extern cvar_t r_fullbright;
extern cvar_t r_lightmap;
extern cvar_t r_glsl_offsetmapping;
extern cvar_t r_shadow_realtime_dlight, r_shadow_realtime_dlight_shadows;
extern cvar_t r_shadow_realtime_dlight_ambient;
extern cvar_t r_shadow_realtime_dlight_diffuse;
extern cvar_t r_shadow_realtime_dlight_specular;
extern cvar_t r_shadow_realtime_world, r_shadow_realtime_world_shadows;
extern cvar_t r_editlights_import_radius;
extern cvar_t r_editlights_import_ambient;
extern cvar_t r_editlights_import_diffuse;
extern cvar_t r_editlights_import_specular;
extern cvar_t r_mirroralpha;
extern cvar_t r_wateralpha;
extern cvar_t r_waterstyle;

View File

@ -302,6 +302,7 @@ cvar_t gl_maxdist = SCVAR("gl_maxdist", "8192");
#ifdef SPECULAR
cvar_t gl_specular = CVARF ("gl_specular", "1", CVAR_ARCHIVE);
cvar_t gl_specular_fallback = CVARF ("gl_specular_fallback", "0.05", CVAR_ARCHIVE|CVAR_RENDERERLATCH);
#endif
// The callbacks are not in D3D yet (also ugly way of seperating this)
@ -342,9 +343,16 @@ cvar_t r_glsl_turbscale = CVARF ("r_glsl_turbscale", "1", CVAR_ARCHIVE);
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);
cvar_t r_shadow_realtime_world_lightmaps = SCVARF ("r_shadow_realtime_world_lightmaps", "0", 0);
cvar_t r_shadow_realtime_dlight = SCVARF ("r_shadow_realtime_dlight", "1", CVAR_ARCHIVE);
cvar_t r_shadow_realtime_dlight_shadows = SCVARF ("r_shadow_realtime_dlight_shadows", "1", CVAR_ARCHIVE);
cvar_t r_shadow_realtime_world_lightmaps = SCVARF ("r_shadow_realtime_world_lightmaps", "0", 0);
cvar_t r_shadow_realtime_dlight_ambient = SCVAR ("r_shadow_realtime_dlight_ambient", "0");
cvar_t r_shadow_realtime_dlight_diffuse = SCVAR ("r_shadow_realtime_dlight_diffuse", "1");
cvar_t r_shadow_realtime_dlight_specular = SCVAR ("r_shadow_realtime_dlight_specular", "4"); //excessive, but noticable. its called stylized, okay? shiesh, some people
cvar_t r_editlights_import_radius = SCVAR ("r_editlights_import_radius", "1");
cvar_t r_editlights_import_ambient = SCVAR ("r_editlights_import_ambient", "0");
cvar_t r_editlights_import_diffuse = SCVAR ("r_editlights_import_diffuse", "1");
cvar_t r_editlights_import_specular = SCVAR ("r_editlights_import_specular", "1"); //excessive, but noticable. its called stylized, okay? shiesh, some people
cvar_t r_shadow_shadowmapping = SCVARF ("debug_r_shadow_shadowmapping", "0", 0);
cvar_t r_sun_dir = SCVAR ("r_sun_dir", "0.2 0.5 0.8");
cvar_t r_sun_colour = SCVARF ("r_sun_colour", "0 0 0", CVAR_ARCHIVE);
@ -415,7 +423,6 @@ void GLRenderer_Init(void)
Cvar_Register (&gl_motionblur, GLRENDEREROPTIONS);
Cvar_Register (&gl_motionblurscale, GLRENDEREROPTIONS);
Cvar_Register (&vid_multisample, GLRENDEREROPTIONS);
Cvar_Register (&gl_smoothcrosshair, GRAPHICALNICETIES);
@ -430,6 +437,7 @@ void GLRenderer_Init(void)
Cvar_Register (&r_xflip, GLRENDEREROPTIONS);
#endif
Cvar_Register (&gl_specular, GRAPHICALNICETIES);
Cvar_Register (&gl_specular_fallback, GRAPHICALNICETIES);
// Cvar_Register (&gl_lightmapmode, GLRENDEREROPTIONS);
@ -528,6 +536,11 @@ void Renderer_Init(void)
#ifdef RTLIGHTS
Cmd_AddCommand ("r_editlights_reload", R_ReloadRTLights_f);
Cmd_AddCommand ("r_editlights_save", R_SaveRTLights_f);
Cvar_Register (&r_editlights_import_radius, "Realtime Light editing/importing");
Cvar_Register (&r_editlights_import_ambient, "Realtime Light editing/importing");
Cvar_Register (&r_editlights_import_diffuse, "Realtime Light editing/importing");
Cvar_Register (&r_editlights_import_specular, "Realtime Light editing/importing");
#endif
Cmd_AddCommand("r_dumpshaders", Shader_WriteOutGenerics_f);
@ -574,6 +587,7 @@ void Renderer_Init(void)
Cvar_Register (&vid_width, VIDCOMMANDGROUP);
Cvar_Register (&vid_height, VIDCOMMANDGROUP);
Cvar_Register (&vid_refreshrate, VIDCOMMANDGROUP);
Cvar_Register (&vid_multisample, GLRENDEREROPTIONS);
Cvar_Register (&vid_desktopsettings, VIDCOMMANDGROUP);
@ -599,6 +613,9 @@ void Renderer_Init(void)
Cvar_Register (&r_shadow_realtime_world, GRAPHICALNICETIES);
Cvar_Register (&r_shadow_realtime_world_shadows, GRAPHICALNICETIES);
Cvar_Register (&r_shadow_realtime_dlight, GRAPHICALNICETIES);
Cvar_Register (&r_shadow_realtime_dlight_ambient, GRAPHICALNICETIES);
Cvar_Register (&r_shadow_realtime_dlight_diffuse, GRAPHICALNICETIES);
Cvar_Register (&r_shadow_realtime_dlight_specular, GRAPHICALNICETIES);
Cvar_Register (&r_shadow_realtime_dlight_shadows, GRAPHICALNICETIES);
Cvar_Register (&r_shadow_realtime_world_lightmaps, GRAPHICALNICETIES);
Cvar_Register (&r_shadow_shadowmapping, GRAPHICALNICETIES);
@ -2250,7 +2267,13 @@ void R_SetFrustum (float projmat[16], float viewmat[16])
#if FRUSTUMPLANES > 4
//do far plane
//fog will not logically not actually reach 0, though precision issues will force it. we cut off at an exponant of -500
if (r_refdef.gfog_rgbd[3])
if (r_refdef.gfog_rgbd[3]
#ifdef TERRAIN
&& cl.worldmodel && cl.worldmodel->terrain
#else
&& 0
#endif
)
{
float culldist;
float fog;

View File

@ -42,7 +42,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef _DEBUG
#if _MSC_VER >= 1300
#define CATCHCRASH
//#define CATCHCRASH
#endif
#endif
@ -1420,13 +1420,13 @@ void Sys_SendKeyEvents (void)
return;
}
while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
// we always update if there are any event, even if we're paused
scr_skipupdate = 0;
if (!GetMessage (&msg, NULL, 0, 0))
break;
//if (!GetMessage (&msg, NULL, 0, 0))
// break;
// Sys_Quit ();
// if (TranslateMessage (&msg))
// continue;

View File

@ -638,12 +638,15 @@ void Mod_ParseInfoFromEntityLump(model_t *wmodel, char *data, char *mapname) //a
}
else if (!strcmp("fog", key))
{
int oel = Cmd_ExecLevel;
void CL_Fog_f(void);
key[0] = 'f';
key[1] = ' ';
Q_strncpyz(key+2, com_token, sizeof(key)-2);
Cmd_TokenizeString(key, false, false);
Cmd_ExecLevel=RESTRICT_LOCAL;
CL_Fog_f();
Cmd_ExecLevel=oel;
}
else if (!strcmp("sky", key)) // for Quake2 maps
{

View File

@ -176,7 +176,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif
#else
#define USE_SQLITE
// #define USE_MYSQL
#ifdef SERVERONLY
#define USE_MYSQL //allow mysql in dedicated servers.
#endif
#define SIDEVIEWS 4 //enable secondary/reverse views.
@ -230,8 +232,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// #define OFFSCREENGECKO
#endif
//#define SQL
#define CSQC_DAT //support for csqc
#define MENU_DAT //support for menu.dat
@ -411,8 +411,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define MSVCDISABLEWARNINGS
#if _MSC_VER >= 1300
#define FTE_DEPRECATED __declspec(deprecated)
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_NONSTDC_NO_WARNINGS
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#ifndef _CRT_NONSTDC_NO_WARNINGS
#define _CRT_NONSTDC_NO_WARNINGS
#endif
#endif
#define NORETURN __declspec(noreturn)
#endif

View File

@ -178,13 +178,30 @@ typedef struct
mesh_t **meshlist;
unsigned int nummeshes;
ID3D11Buffer *cbuffers[2];
#define NUMECBUFFERS 8
ID3D11Buffer *vcbuffer;
ID3D11Buffer *ecbuffers[NUMECBUFFERS];
int ecbufferidx;
unsigned int wbatch;
unsigned int maxwbatches;
batch_t *wbatches;
qboolean textureschanged;
ID3D11ShaderResourceView *pendingtextures[MAX_TMUS];
float depthrange;
qboolean purgevertexstream;
ID3D11Buffer *vertexstream;
int vertexstreamoffset;
qboolean purgeindexstream;
ID3D11Buffer *indexstream;
int indexstreamoffset;
} d3d11backend_t;
#define VERTEXSTREAMSIZE (1024*1024*2) //2mb = 1 PAE jumbo page
#define DYNVBUFFSIZE 65536
#define DYNIBUFFSIZE 65536
@ -232,7 +249,8 @@ static void BE_DestroySamplerStates(void)
int flags;
for (flags = 0; flags <= (SHADER_PASS_CLAMP|SHADER_PASS_NEAREST); flags++)
{
ID3D11SamplerState_Release(shaderstate.sampstate[flags]);
if (shaderstate.sampstate[flags])
ID3D11SamplerState_Release(shaderstate.sampstate[flags]);
shaderstate.sampstate[flags] = NULL;
}
}
@ -534,21 +552,42 @@ void D3D11BE_Init(void)
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;
for (i = 0; i < NUMECBUFFERS; i++)
{
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.ecbuffers[i])))
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])))
if (FAILED(ID3D11Device_CreateBuffer(pD3DDev11, &bd, NULL, &shaderstate.vcbuffer)))
return;
//generate the streaming buffers for stuff that doesn't provide info in nice static vbos
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
bd.ByteWidth = VERTEXSTREAMSIZE;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.MiscFlags = 0;
bd.StructureByteStride = 0;
bd.Usage = D3D11_USAGE_DYNAMIC;
if (FAILED(ID3D11Device_CreateBuffer(pD3DDev11, &bd, NULL, &shaderstate.indexstream)))
return;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.ByteWidth = VERTEXSTREAMSIZE;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.MiscFlags = 0;
bd.StructureByteStride = 0;
bd.Usage = D3D11_USAGE_DYNAMIC;
if (FAILED(ID3D11Device_CreateBuffer(pD3DDev11, &bd, NULL, &shaderstate.vertexstream)))
return;
shaderstate.shader_rtlight = R_RegisterShader("rtlight", LIGHTPASS_SHADER);
@ -601,53 +640,56 @@ static unsigned int allocindexbuffer(void **dest, unsigned int entries)
}
#endif
static void BindTexture(unsigned int tu, void *id)
ID3D11ShaderResourceView *D3D11_Image_View(const texid_t *id);
static void BindTexture(unsigned int tu, const texid_t *id)
{
if (shaderstate.curtex[tu].ptr != id)
ID3D11ShaderResourceView *view = D3D11_Image_View(id);
if (shaderstate.pendingtextures[tu] != view)
{
shaderstate.curtex[tu].ptr = id;
ID3D11DeviceContext_PSSetShaderResources(d3ddevctx, tu, 1, (ID3D11ShaderResourceView**)&id);
shaderstate.textureschanged = true;
shaderstate.pendingtextures[tu] = view;
}
}
static void SelectPassTexture(unsigned int tu, shaderpass_t *pass)
{
texid_t foo;
switch(pass->texgen)
{
default:
case T_GEN_DIFFUSE:
BindTexture(tu, shaderstate.curtexnums->base.ptr);
BindTexture(tu, &shaderstate.curtexnums->base);
break;
case T_GEN_NORMALMAP:
BindTexture( tu, shaderstate.curtexnums->bump.ptr);
BindTexture(tu, &shaderstate.curtexnums->bump);
break;
case T_GEN_SPECULAR:
BindTexture(tu, shaderstate.curtexnums->specular.ptr);
BindTexture(tu, &shaderstate.curtexnums->specular);
break;
case T_GEN_UPPEROVERLAY:
BindTexture(tu, shaderstate.curtexnums->upperoverlay.ptr);
BindTexture(tu, &shaderstate.curtexnums->upperoverlay);
break;
case T_GEN_LOWEROVERLAY:
BindTexture(tu, shaderstate.curtexnums->loweroverlay.ptr);
BindTexture(tu, &shaderstate.curtexnums->loweroverlay);
break;
case T_GEN_FULLBRIGHT:
BindTexture(tu, shaderstate.curtexnums->fullbright.ptr);
BindTexture(tu, &shaderstate.curtexnums->fullbright);
break;
case T_GEN_ANIMMAP:
BindTexture(tu, pass->anim_frames[(int)(pass->anim_fps * shaderstate.curtime) % pass->anim_numframes].ptr);
BindTexture(tu, &pass->anim_frames[(int)(pass->anim_fps * shaderstate.curtime) % pass->anim_numframes]);
break;
case T_GEN_SINGLEMAP:
BindTexture(tu, pass->anim_frames[0].ptr);
BindTexture(tu, &pass->anim_frames[0]);
break;
case T_GEN_DELUXMAP:
{
int lmi = shaderstate.curbatch->lightmap[0];
if (lmi < 0 || !lightmap[lmi]->hasdeluxe)
BindTexture(tu, NULL);
BindTexture(tu, &r_nulltex);
else
{
lmi+=1;
BindTexture(tu, lightmap[lmi]->lightmap_texture.ptr);
BindTexture(tu, &lightmap[lmi]->lightmap_texture);
}
}
break;
@ -655,9 +697,9 @@ static void SelectPassTexture(unsigned int tu, shaderpass_t *pass)
{
int lmi = shaderstate.curbatch->lightmap[0];
if (lmi < 0)
BindTexture(tu, NULL);
BindTexture(tu, &r_nulltex);
else
BindTexture(tu, lightmap[lmi]->lightmap_texture.ptr);
BindTexture(tu, &lightmap[lmi]->lightmap_texture);
}
break;
@ -665,7 +707,10 @@ static void SelectPassTexture(unsigned int tu, shaderpass_t *pass)
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);
{
foo = Media_UpdateForShader(pass->cin);
BindTexture(tu, &foo);
}
break;
}
@ -1541,14 +1586,19 @@ static void BE_SubmitMeshChain(int idxfirst)
static void BE_ApplyUniforms(program_t *prog, int permu)
{
ID3D11Buffer *cbuf[2] =
{
shaderstate.ecbuffers[shaderstate.ecbufferidx],
shaderstate.vcbuffer
};
//FIXME: how many of these calls can we avoid?
ID3D11DeviceContext_IASetInputLayout(d3ddevctx, prog->permu[permu].handle.hlsl.layout);
ID3D11DeviceContext_VSSetShader(d3ddevctx, prog->permu[permu].handle.hlsl.vert, NULL, 0);
ID3D11DeviceContext_PSSetShader(d3ddevctx, prog->permu[permu].handle.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);
ID3D11DeviceContext_VSSetConstantBuffers(d3ddevctx, 0, 2, cbuf);
ID3D11DeviceContext_PSSetConstantBuffers(d3ddevctx, 0, 2, cbuf);
}
static void BE_RenderMeshProgram(shader_t *s, unsigned int vertcount, unsigned int idxfirst, unsigned int idxcount)
@ -1582,9 +1632,12 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertcount, unsigned i
/*deactivate any extras*/
for (; passno < shaderstate.lastpasscount; passno++)
{
BindTexture(passno, NULL);
shaderstate.pendingtextures[passno] = NULL;
shaderstate.textureschanged = true;
}
shaderstate.lastpasscount = passno;
if (shaderstate.textureschanged)
ID3D11DeviceContext_PSSetShaderResources(d3ddevctx, 0, passno, shaderstate.pendingtextures);
shaderstate.lastpasscount = s->numpasses;
BE_SubmitMeshChain(idxfirst);
}
@ -1791,107 +1844,181 @@ void D3D11BE_SelectEntity(entity_t *ent)
BE_RotateForEntity(ent, ent->model);
}
static void BE_GenTempMeshVBO(vbo_t **vbo, mesh_t *mesh)
static qboolean 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;
D3D11_MAPPED_SUBRESOURCE msr;
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);
D3D11_MAP type;
int sz;
//common stuff
for (i = 0; i < mesh->numvertexes; i++)
//vbo first
{
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++)
vbovdata_t *out;
sz = sizeof(*out) * mesh->numvertexes;
if (shaderstate.purgevertexstream || shaderstate.vertexstreamoffset + sz > VERTEXSTREAMSIZE)
{
VectorCopy(mesh->normals_array[i], vbodata[i].ndir);
VectorCopy(mesh->snormals_array[i], vbodata[i].sdir);
VectorCopy(mesh->tnormals_array[i], vbodata[i].tdir);
shaderstate.purgevertexstream = false;
shaderstate.vertexstreamoffset = 0;
type = D3D11_MAP_WRITE_DISCARD;
}
}
//some sort of colours
if (mesh->colors4b_array)
{
for (i = 0; i < mesh->numvertexes; i++)
else
{
Vector4Copy(mesh->colors4b_array[i], vbodata[i].colorsb);
type = D3D11_MAP_WRITE_NO_OVERWRITE; //yes sir, sorry sir, we promise to not break anything
}
}
else if (mesh->colors4f_array)
{
for (i = 0; i < mesh->numvertexes; i++)
if (FAILED(ID3D11DeviceContext_Map(d3ddevctx, (ID3D11Resource*)shaderstate.vertexstream, 0, type, 0, &msr)))
{
Vector4Scale(mesh->colors4f_array[i], 255, vbodata[i].colorsb);
Con_Printf("BE_RotateForEntity: failed to map vertex stream buffer start\n");
return false;
}
}
else
{
for (i = 0; i < mesh->numvertexes; i++)
//figure out where our pointer is and mark it as consumed
out = (vbovdata_t*)((qbyte*)msr.pData + shaderstate.vertexstreamoffset);
//FIXME: do we actually need to bother setting all this junk?
tmpvbo.coord.d3d.buff = shaderstate.vertexstream;
tmpvbo.coord.d3d.offs = (quintptr_t)&out[0].coord - (quintptr_t)&out[0] + shaderstate.vertexstreamoffset;
tmpvbo.texcoord.d3d.buff = shaderstate.vertexstream;
tmpvbo.texcoord.d3d.offs = (quintptr_t)&out[0].tex - (quintptr_t)&out[0] + shaderstate.vertexstreamoffset;
tmpvbo.lmcoord[0].d3d.buff = shaderstate.vertexstream;
tmpvbo.lmcoord[0].d3d.offs = (quintptr_t)&out[0].lm - (quintptr_t)&out[0] + shaderstate.vertexstreamoffset;
tmpvbo.normals.d3d.buff = shaderstate.vertexstream;
tmpvbo.normals.d3d.offs = (quintptr_t)&out[0].ndir - (quintptr_t)&out[0] + shaderstate.vertexstreamoffset;
tmpvbo.svector.d3d.buff = shaderstate.vertexstream;
tmpvbo.svector.d3d.offs = (quintptr_t)&out[0].sdir - (quintptr_t)&out[0] + shaderstate.vertexstreamoffset;
tmpvbo.tvector.d3d.buff = shaderstate.vertexstream;
tmpvbo.tvector.d3d.offs = (quintptr_t)&out[0].tdir - (quintptr_t)&out[0] + shaderstate.vertexstreamoffset;
tmpvbo.colours.d3d.buff = shaderstate.vertexstream;
tmpvbo.colours.d3d.offs = (quintptr_t)&out[0].colorsb - (quintptr_t)&out[0] + shaderstate.vertexstreamoffset;
//consumed
shaderstate.vertexstreamoffset += sz;
//now vomit into the buffer
if (!mesh->normals_array && mesh->colors4f_array)
{
Vector4Set(vbodata[i].colorsb, 255, 255, 255, 255);
//2d drawing
for (i = 0; i < mesh->numvertexes; i++)
{
VectorCopy(mesh->xyz_array[i], out[i].coord);
Vector2Copy(mesh->st_array[i], out[i].tex);
VectorClear(out[i].ndir);
VectorClear(out[i].sdir);
VectorClear(out[i].tdir);
Vector4Scale(mesh->colors4f_array[i], 255, out[i].colorsb);
}
}
else if (!mesh->normals_array && mesh->colors4b_array)
{
//2d drawing, ish
for (i = 0; i < mesh->numvertexes; i++)
{
VectorCopy(mesh->xyz_array[i], out[i].coord);
Vector2Copy(mesh->st_array[i], out[i].tex);
VectorClear(out[i].ndir);
VectorClear(out[i].sdir);
VectorClear(out[i].tdir);
*(unsigned int*)out[i].colorsb = *(unsigned int*)mesh->colors4b_array[i];
}
}
else if (mesh->normals_array && !mesh->colors4f_array && !mesh->colors4b_array)
{
//hlsl-lit models
for (i = 0; i < mesh->numvertexes; i++)
{
VectorCopy(mesh->xyz_array[i], out[i].coord);
Vector2Copy(mesh->st_array[i], out[i].tex);
VectorCopy(mesh->normals_array[i], out[i].ndir);
VectorCopy(mesh->snormals_array[i], out[i].sdir);
VectorCopy(mesh->tnormals_array[i], out[i].tdir);
*(unsigned int*)out[i].colorsb = 0xffffffff; //write colours to ensure nothing is read back within the cpu cache block.
}
}
else
{
//common stuff
for (i = 0; i < mesh->numvertexes; i++)
{
VectorCopy(mesh->xyz_array[i], out[i].coord);
Vector2Copy(mesh->st_array[i], out[i].tex);
}
//not so common stuff
if (mesh->normals_array)
{
for (i = 0; i < mesh->numvertexes; i++)
{
VectorCopy(mesh->normals_array[i], out[i].ndir);
VectorCopy(mesh->snormals_array[i], out[i].sdir);
VectorCopy(mesh->tnormals_array[i], out[i].tdir);
}
}
//some sort of colours
if (mesh->colors4b_array)
{
for (i = 0; i < mesh->numvertexes; i++)
{
Vector4Copy(mesh->colors4b_array[i], out[i].colorsb);
}
}
else if (mesh->colors4f_array)
{
for (i = 0; i < mesh->numvertexes; i++)
{
Vector4Scale(mesh->colors4f_array[i], 255, out[i].colorsb);
}
}
else
{
for (i = 0; i < mesh->numvertexes; i++)
{
Vector4Set(out[i].colorsb, 255, 255, 255, 255);
}
}
}
//and we're done
ID3D11DeviceContext_Unmap(d3ddevctx, (ID3D11Resource*)shaderstate.vertexstream, 0);
}
//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);
//now ebo
{
index_t *out;
sz = sizeof(*out) * mesh->numindexes;
if (shaderstate.purgeindexstream || shaderstate.indexstreamoffset + sz > VERTEXSTREAMSIZE)
{
shaderstate.purgeindexstream = false;
shaderstate.indexstreamoffset = 0;
type = D3D11_MAP_WRITE_DISCARD;
}
else
{
type = D3D11_MAP_WRITE_NO_OVERWRITE;
}
if (FAILED(ID3D11DeviceContext_Map(d3ddevctx, (ID3D11Resource*)shaderstate.indexstream, 0, type, 0, &msr)))
{
Con_Printf("BE_RotateForEntity: failed to map vertex stream buffer start\n");
return false;
}
//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);
out = (index_t*)((qbyte*)msr.pData + shaderstate.indexstreamoffset);
tmpvbo.indicies.d3d.buff = shaderstate.indexstream;
tmpvbo.indicies.d3d.offs = shaderstate.indexstreamoffset;
//consumed
shaderstate.indexstreamoffset += sz;
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;
memcpy(out, mesh->indexes, sz);
//and we're done
ID3D11DeviceContext_Unmap(d3ddevctx, (ID3D11Resource*)shaderstate.indexstream, 0);
}
tmpvbo.indexcount = mesh->numindexes;
tmpvbo.vertcount = mesh->numvertexes;
tmpvbo.next = NULL;
*vbo = &tmpvbo;
return true;
}
void D3D11BE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch)
@ -2133,7 +2260,7 @@ 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)))
if (FAILED(ID3D11DeviceContext_Map(d3ddevctx, (ID3D11Resource*)shaderstate.vcbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &msr)))
{
Con_Printf("BE_RotateForEntity: failed to map constant buffer\n");
return;
@ -2145,17 +2272,19 @@ void D3D11BE_SetupViewCBuffer(void)
VectorCopy(r_origin, cbv->v_eyepos);
cbv->v_time = r_refdef.time;
ID3D11DeviceContext_Unmap(d3ddevctx, (ID3D11Resource*)shaderstate.cbuffers[1], 0);
ID3D11DeviceContext_Unmap(d3ddevctx, (ID3D11Resource*)shaderstate.vcbuffer, 0);
}
//also updates the entity constant buffer
static void BE_RotateForEntity (const entity_t *e, const model_t *mod)
{
float ndr;
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)))
shaderstate.ecbufferidx = (shaderstate.ecbufferidx + 1) & (NUMECBUFFERS-1);
if (FAILED(ID3D11DeviceContext_Map(d3ddevctx, (ID3D11Resource*)shaderstate.ecbuffers[shaderstate.ecbufferidx], 0, D3D11_MAP_WRITE_DISCARD, 0, &msr)))
{
Con_Printf("BE_RotateForEntity: failed to map constant buffer\n");
return;
@ -2261,13 +2390,22 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod)
VectorCopy(e->light_dir, cbe->e_light_dir);
VectorCopy(e->light_range, cbe->e_light_mul);
ID3D11DeviceContext_Unmap(d3ddevctx, (ID3D11Resource*)shaderstate.cbuffers[0], 0);
ID3D11DeviceContext_Unmap(d3ddevctx, (ID3D11Resource*)shaderstate.ecbuffers[shaderstate.ecbufferidx], 0);
ndr = (e->flags & Q2RF_DEPTHHACK)?0.333:1;
if (ndr != shaderstate.depthrange)
{
// D3DVIEWPORT9 vport;
// IDirect3DDevice9_GetViewport(pD3DDev9, &vport);
// vport.MaxZ = (e->flags & Q2RF_DEPTHHACK)?0.333:1;
// IDirect3DDevice9_SetViewport(pD3DDev9, &vport);
D3D11_VIEWPORT vport;
shaderstate.depthrange = ndr;
vport.TopLeftX = (r_refdef.vrect.x * vid.pixelwidth) / vid.width;
vport.TopLeftY = (r_refdef.vrect.y * vid.pixelheight) / vid.height;
vport.Width = (r_refdef.vrect.width * vid.pixelwidth) / vid.width;
vport.Height = (r_refdef.vrect.height * vid.pixelheight) / vid.height;
vport.MinDepth = 0;
vport.MaxDepth = shaderstate.depthrange;
d3ddevctx->lpVtbl->RSSetViewports(d3ddevctx, 1, &vport);
}
}
@ -2290,7 +2428,8 @@ void D3D11BE_SubmitBatch(batch_t *batch)
if (!shaderstate.batchvbo)
{
BE_GenTempMeshVBO(&shaderstate.batchvbo, batch->mesh[0]);
if (!BE_GenTempMeshVBO(&shaderstate.batchvbo, batch->mesh[0]))
return;
BE_DrawMeshChain_Internal();
}
else
@ -2309,7 +2448,8 @@ void D3D11BE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, v
if (!shaderstate.batchvbo)
{
BE_GenTempMeshVBO(&shaderstate.batchvbo, meshlist[0]);
if (!BE_GenTempMeshVBO(&shaderstate.batchvbo, meshlist[0]))
return;
shaderstate.nummeshes = 1;
BE_DrawMeshChain_Internal();
}
@ -2330,7 +2470,8 @@ void D3D11BE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, te
if (!shaderstate.batchvbo)
{
BE_GenTempMeshVBO(&shaderstate.batchvbo, meshchain);
if (!BE_GenTempMeshVBO(&shaderstate.batchvbo, meshchain))
return;
BE_DrawMeshChain_Internal();
}
else
@ -2715,6 +2856,8 @@ void D3D11BE_DrawWorld (qboolean drawworld, qbyte *vis)
shaderstate.curentity = NULL;
shaderstate.depthrange = 0;
if (!r_refdef.recurse)
{
if (shaderstate.wbatch > shaderstate.maxwbatches)

View File

@ -17,6 +17,16 @@ typedef struct d3dtexture_s
} d3d11texture_t;
static d3d11texture_t *d3d11textures;
ID3D11ShaderResourceView *D3D11_Image_View(const texid_t *id)
{
d3d11texture_t *info = (d3d11texture_t*)id->ref;
if (!info)
return NULL;
if (!info->view)
ID3D11Device_CreateShaderResourceView(pD3DDev11, (ID3D11Resource *)info->tex2d, NULL, &info->view);
return info->view;
}
void D3D11_Image_Shutdown(void)
{
//destroy all named textures
@ -39,6 +49,10 @@ void D3D11_DestroyTexture (texid_t tex)
d3d11texture_t *t = (d3d11texture_t*)tex.ref;
ID3D11Texture2D *tx = tex.ptr;
if (!t)
return;
if (t->view)
ID3D11ShaderResourceView_Release(t->view);
if (t->tex2d)
@ -90,49 +104,111 @@ static texid_t ToTexID(d3d11texture_t *tex)
tid.ref = &tex->com;
if (!tex->view)
ID3D11Device_CreateShaderResourceView(pD3DDev11, (ID3D11Resource *)tex->tex2d, NULL, &tex->view);
tid.ptr = tex->view;
tid.ptr = NULL;//(void*)0xdeadbeef;
return tid;
}
static void D3D_MipMap (qbyte *out, int outwidth, int outheight, const qbyte *in, int inwidth, int inheight)
{
int i, j;
const qbyte *inrow;
//with npot
int rowwidth = inwidth*4; //rowwidth is the byte width of the input
inrow = in;
for (i=0 ; i<outheight ; i++, inrow+=rowwidth*2)
{
for (in = inrow, j=0 ; j<outwidth ; j++, out+=4, in+=8)
{
out[0] = (in[0] + in[4] + in[rowwidth+0] + in[rowwidth+4])>>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;
}
}
}
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;
D3D11_SUBRESOURCE_DATA subresdesc[64] = {0};
int i;
int owidth, oheight;
tdesc.Width = width;
tdesc.Height = height;
tdesc.MipLevels = 1;
tdesc.MipLevels = (!datargba || (flags & IF_NOMIPMAP))?1:0; //0 generates mipmaps automagically
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.Usage = datargba?D3D11_USAGE_IMMUTABLE:D3D11_USAGE_DYNAMIC;
tdesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
tdesc.CPUAccessFlags = 0;
tdesc.CPUAccessFlags = (datargba)?0:D3D11_CPU_ACCESS_WRITE;
tdesc.MiscFlags = 0;
hr = ID3D11Device_CreateTexture2D(pD3DDev11, &tdesc, (datargba?&subresdesc:NULL), &tx);
//first mip level
subresdesc[0].SysMemPitch = width*4;
subresdesc[0].SysMemSlicePitch = width*height*4;
if (!datargba)
{
subresdesc[0].pSysMem = NULL;
//one mip, but no data
i = 1;
}
else
{
subresdesc[0].pSysMem = datargba;
for (i = 1; i < 64 && width > 1 && height > 1; i++)
{
owidth = width;
oheight = height;
width /= 2;
height /= 2;
subresdesc[i].pSysMem = malloc(width*height*4);
subresdesc[i].SysMemPitch = width*4;
subresdesc[i].SysMemSlicePitch = width*height*4;
D3D_MipMap((void*)subresdesc[i].pSysMem, width, height, subresdesc[i-1].pSysMem, owidth, oheight);
}
}
tdesc.MipLevels = i; //0 generates mipmaps automagically
hr = ID3D11Device_CreateTexture2D(pD3DDev11, &tdesc, (subresdesc[0].pSysMem?subresdesc:NULL), &tx);
if (FAILED(hr))
{
Con_Printf("Failed to create texture\n");
tx = NULL;
}
for (i = 1; i < tdesc.MipLevels; i++)
{
free((void*)subresdesc[i].pSysMem);
}
return tx;
}
texid_t D3D11_AllocNewTexture(char *ident, int width, int height, unsigned int flags)
{
d3d11texture_t *t;
void *img = D3D11_AllocNewTextureData(NULL, width, height, flags);
if (!img)
d3d11texture_t *t = d3d_lookup_texture("");
texid_t id;
if (t->tex2d)
return ToTexID(t);
t->tex2d = D3D11_AllocNewTextureData(NULL, width, height, flags);
id = ToTexID(t);
if (!t->tex2d)
{
D3D11_DestroyTexture(id);
return r_nulltex;
t = d3d_lookup_texture("");
t->tex2d = img;
}
return ToTexID(t);
return id;
}
static void D3D11_RoundDimensions(int *scaled_width, int *scaled_height, qboolean mipmap)
@ -178,42 +254,22 @@ static void D3D11_RoundDimensions(int *scaled_width, int *scaled_height, qboolea
*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<outheight ; i++, inrow+=rowwidth*2)
{
for (in = inrow, j=0 ; j<outwidth ; j++, out+=4, in+=8)
{
out[0] = (in[0] + in[4] + in[rowwidth+0] + in[rowwidth+4])>>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;
int x, y;
unsigned int *dest;
// unsigned char swapbuf[4];
// unsigned char swapbuf2[4];
// D3D11_MAPPED_SUBRESOURCE lock;
D3D11_MAPPED_SUBRESOURCE lock;
D3D11_TEXTURE2D_DESC desc;
if (!tex)
return;
desc.Width = 0;
desc.Height = 0;
ID3D11Texture2D_GetDesc(tex, &desc);
#if 0
if (width == desc.Width && height == desc.Height)
{
ID3D11DeviceContext_UpdateSubresource(d3ddevctx, (ID3D11Resource*)tex, 0, NULL, data, width*4, width*height*4);
@ -222,7 +278,7 @@ static void Upload_Texture_32(ID3D11Texture2D *tex, unsigned int *data, int widt
Con_Printf("Wrong size!\n");
return;
#if 0
#else
if (FAILED(ID3D11DeviceContext_Map(d3ddevctx, (ID3D11Resource*)tex, 0, D3D11_MAP_WRITE_DISCARD, 0, &lock)))
{
Con_Printf("Dynamic texture update failed\n");
@ -236,10 +292,10 @@ static void Upload_Texture_32(ID3D11Texture2D *tex, unsigned int *data, int widt
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;
// *(unsigned int*)swapbuf2 = *(unsigned int*)swapbuf = data[x];
// swapbuf[0] = swapbuf2[2];
// swapbuf[2] = swapbuf2[0];
dest[x] = data[x];//*(unsigned int*)swapbuf;
}
data += width;
}
@ -257,10 +313,10 @@ static void Upload_Texture_32(ID3D11Texture2D *tex, unsigned int *data, int widt
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;
//*(unsigned int*)swapbuf2 = *(unsigned int*)swapbuf = inrow[(x * width)/desc.Width];
//swapbuf[0] = swapbuf2[2];
//swapbuf[2] = swapbuf2[0];
row[x] = inrow[(x * width)/desc.Width];//*(unsigned int*)swapbuf;
}
}
}
@ -291,8 +347,8 @@ static void D3D11_LoadTexture_32(d3d11texture_t *tex, unsigned int *data, int wi
tex->tex2d = D3D11_AllocNewTextureData(data, width, height, flags);
return;
}
Upload_Texture_32(tex->tex2d, data, width, height, flags);
else
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)
@ -401,15 +457,22 @@ static void D3D11_LoadTexture_8(d3d11texture_t *tex, unsigned char *data, unsign
D3D11_LoadTexture_32(tex, trans, width, height, 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_Upload (texid_t id, char *name, enum uploadfmt fmt, void *data, void *palette, int width, int height, unsigned int flags)
{
d3d11texture_t *tex = (d3d11texture_t *)id.ref;
switch (fmt)
{
case TF_RGBX32:
flags |= IF_NOALPHA;
//fall through
case TF_RGBA32:
Upload_Texture_32(tex.ptr, data, width, height, flags);
Upload_Texture_32(tex->tex2d, data, width, height, flags);
if (tex->view)
{
tex->view->lpVtbl->Release(tex->view);
tex->view = NULL;
}
ToTexID(tex);
break;
case TF_TRANS8:
OutputDebugString(va("D3D11_LoadTextureFmt doesn't support fmt TF_TRANS8 (%s)\n", fmt, name));
@ -486,6 +549,8 @@ texid_t D3D11_LoadTexture (char *identifier, int width, int height, enum uploadf
}
tex = d3d_lookup_texture(identifier);
if (tex->tex2d) //already loaded
return ToTexID(tex);
switch (fmt)
{

View File

@ -54,7 +54,7 @@ HRESULT (WINAPI *pD3DCompile) (
ID3DBlob **ppCode,
ID3DBlob **ppErrorMsgs
);
dllhandle_t *shaderlib;
static dllhandle_t *shaderlib;

View File

@ -1284,21 +1284,21 @@ static void GenerateTCMods(const shaderpass_t *pass, float *dest)
for (mno = 0; mno < shaderstate.nummeshes; mno++)
{
mesh = shaderstate.meshlist[mno];
src = tcgen(pass, mesh->numvertexes, dest, mesh);
src = tcgen(pass, mesh->numvertexes, dest + mesh->vbofirstvert*2, mesh);
//tcgen might return unmodified info
if (pass->numtcmods)
{
tcmod(&pass->tcmods[0], mesh->numvertexes, src, dest, mesh);
tcmod(&pass->tcmods[0], mesh->numvertexes, src, dest + mesh->vbofirstvert*2, mesh);
for (i = 1; i < pass->numtcmods; i++)
{
tcmod(&pass->tcmods[i], mesh->numvertexes, dest, dest, mesh);
tcmod(&pass->tcmods[i], mesh->numvertexes, dest + mesh->vbofirstvert*2, dest + mesh->vbofirstvert*2, mesh);
}
}
else if (src != dest)
{
memcpy(dest, src, sizeof(vec2_t)*mesh->numvertexes);
memcpy(dest + mesh->vbofirstvert*2, src, sizeof(vec2_t)*mesh->numvertexes);
}
dest += mesh->numvertexes*2;
// dest += mesh->numvertexes*2;
}
}
@ -2183,6 +2183,9 @@ static void D3D9BE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *
}
}
vbo->indexcount = idx;
vbo->vertcount = vert;
IDirect3DIndexBuffer9_Unlock(ebuff);
IDirect3DVertexBuffer9_Unlock(vbuff);

View File

@ -134,7 +134,7 @@ HRESULT (WINAPI *pD3DXCompileShader) (
LPD3DXBUFFER *ppErrorMsgs,
LPD3DXCONSTANTTABLE *constants
);
dllhandle_t *shaderlib;
static dllhandle_t *shaderlib;

View File

@ -1091,6 +1091,9 @@ static void (D3D9_SCR_UpdateScreen) (void)
Media_RecordFrame();
#endif
if (Key_MouseShouldBeFree())
SCR_DrawCursor(0);
RSpeedEnd(RSPEED_TOTALREFRESH);
RSpeedShow();

View File

@ -165,6 +165,8 @@ static void D3DVID_UpdateWindowStatus (HWND hWnd)
int window_width, window_height;
GetClientRect(hWnd, &nr);
Sys_Printf("Update: %i %i %i %i\n", nr.left, nr.top, nr.right, nr.bottom);
//if its bad then we're probably minimised
if (nr.right <= nr.left)
return;
@ -188,6 +190,9 @@ static void D3DVID_UpdateWindowStatus (HWND hWnd)
window_center_x = (window_rect.left + window_rect.right) / 2;
window_center_y = (window_rect.top + window_rect.bottom) / 2;
Sys_Printf("Window: %i %i %i %i\n", window_x, window_y, window_width, window_height);
INS_UpdateClipCursor ();
}
@ -243,15 +248,17 @@ static qboolean D3D11AppActivate(BOOL fActive, BOOL minimize)
static LRESULT WINAPI D3D11_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LONG lRet = 1;
LONG lRet = 0;
int fActive, fMinimized, temp;
extern unsigned int uiWheelMessage;
extern qboolean keydown[K_MAX];
if ( uMsg == uiWheelMessage )
uMsg = WM_MOUSEWHEEL;
switch (uMsg)
{
#if 1
/* case WM_KILLFOCUS:
if (modestate == MS_FULLDIB)
ShowWindow(mainwindow, SW_SHOWMINNOACTIVE);
@ -267,7 +274,43 @@ static LRESULT WINAPI D3D11_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
if (!vid_initializing)
if (keydown[K_ALT] && wParam == '\r')
{
if (modestate == MS_FULLSCREEN)
modestate = MS_WINDOWED;
else
{
RECT rect;
extern cvar_t vid_width, vid_height;
int width = vid_width.ival;
int height = vid_height.ival;
rect.left = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
rect.top = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
rect.right = rect.left+width;
rect.bottom = rect.top+height;
AdjustWindowRectEx(&rect, WS_OVERLAPPED, FALSE, 0);
SetWindowPos(hWnd, NULL, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, SWP_SHOWWINDOW|SWP_FRAMECHANGED);
modestate = MS_FULLSCREEN;
}
IDXGISwapChain_SetFullscreenState(d3dswapchain, modestate == MS_FULLSCREEN, NULL);
if (modestate == MS_WINDOWED)
{
RECT rect;
int width = 640;
int height = 480;
rect.left = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
rect.top = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
rect.right = rect.left+width;
rect.bottom = rect.top+height;
AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, FALSE, 0);
SetWindowLong(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW); //make sure dxgi didn't break us.
SetWindowPos(hWnd, HWND_TOP, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, SWP_SHOWWINDOW|SWP_FRAMECHANGED);
SetForegroundWindow(hWnd);
SetFocus(hWnd);
}
}
else if (!vid_initializing)
INS_TranslateKeyEvent (wParam, lParam, true, 0);
break;
@ -381,7 +424,7 @@ static LRESULT WINAPI D3D11_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
resetd3dbackbuffer(vid.pixelwidth, vid.pixelheight);
resetD3D11();
D3D11BE_Reset(false);
lRet = 0;
lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
break;
case WM_CLOSE:
@ -402,10 +445,13 @@ static LRESULT WINAPI D3D11_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
ShowWindow(mainwindow, SW_SHOWNORMAL);
if (ActiveApp && modestate == MS_FULLSCREEN)
IDXGISwapChain_SetFullscreenState(d3dswapchain, modestate == MS_FULLSCREEN, NULL);
// fix the leftover Alt from any Alt-Tab or the like that switched us away
// ClearAllStates ();
lRet = 0;
lRet = 1;
break;
case WM_DESTROY:
@ -418,7 +464,9 @@ static LRESULT WINAPI D3D11_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
case MM_MCINOTIFY:
lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam);
break;
#endif
case WM_ERASEBKGND:
return 1;
default:
/* pass all unhandled messages to DefWindowProc */
lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
@ -524,7 +572,7 @@ static qboolean resetd3dbackbuffer(int width, int height)
return true;
}
static qboolean initD3D11Device(HWND hWnd, rendererstate_t *info, PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN func)
static qboolean initD3D11Device(HWND hWnd, rendererstate_t *info, PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN func, IDXGIAdapter *adapt)
{
int flags = D3D11_CREATE_DEVICE_SINGLETHREADED;
DXGI_SWAP_CHAIN_DESC scd;
@ -555,7 +603,14 @@ static qboolean initD3D11Device(HWND hWnd, rendererstate_t *info, PFN_D3D11_CREA
// flags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
if (FAILED(func(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags,
if (adapt)
{
DXGI_ADAPTER_DESC adesc;
adapt->lpVtbl->GetDesc(adapt, &adesc);
Con_Printf("D3D11 Adaptor: %S\n", adesc.Description);
}
if (FAILED(func(adapt, adapt?D3D_DRIVER_TYPE_UNKNOWN:D3D_DRIVER_TYPE_HARDWARE, NULL, flags,
flevels, sizeof(flevels)/sizeof(flevels[0]),
D3D11_SDK_VERSION,
&scd,
@ -585,20 +640,50 @@ static qboolean initD3D11Device(HWND hWnd, rendererstate_t *info, PFN_D3D11_CREA
static void initD3D11(HWND hWnd, rendererstate_t *info)
{
static dllhandle_t *d3d11dll;
static dllhandle_t *dxgi;
static PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN fnc;
dllfunction_t funcs[] =
static HRESULT (*pCreateDXGIFactory1)(REFIID riid, void **ppFactory);
IID factiid = {0x770aae78, 0xf26f, 0x4dba, 0xa8, 0x29, 0x25, 0x3c, 0x83, 0xd1, 0xb3, 0x87};
IDXGIFactory1 *fact = NULL;
IDXGIAdapter *adapt = NULL;
dllfunction_t d3d11funcs[] =
{
{(void**)&fnc, "D3D11CreateDeviceAndSwapChain"},
{NULL}
};
dllfunction_t dxgifuncs[] =
{
{(void**)&pCreateDXGIFactory1, "CreateDXGIFactory1"},
{NULL}
};
if (!d3d11mod)
d3d11mod = Sys_LoadLibrary("d3d11", funcs);
d3d11mod = Sys_LoadLibrary("d3d11", d3d11funcs);
if (!dxgi)
dxgi = Sys_LoadLibrary("dxgi", dxgifuncs);
if (!d3d11mod)
return;
if (pCreateDXGIFactory1)
{
pCreateDXGIFactory1(&factiid, &fact);
if (fact)
{
fact->lpVtbl->EnumAdapters(fact, 0, &adapt);
}
}
initD3D11Device(hWnd, info, fnc);
initD3D11Device(hWnd, info, fnc, adapt);
if (fact)
{
//DXGI SUCKS and fucks up alt+tab every single time. its pointless to go from fullscreen to fullscreen-with-taskbar-obscuring-half-the-window.
//I'm just going to handle that stuff myself.
fact->lpVtbl->MakeWindowAssociation(fact, hWnd, DXGI_MWA_NO_WINDOW_CHANGES|DXGI_MWA_NO_ALT_ENTER|DXGI_MWA_NO_PRINT_SCREEN);
fact->lpVtbl->Release(fact);
}
}
static qboolean D3D11_VID_Init(rendererstate_t *info, unsigned char *palette)
@ -640,15 +725,14 @@ static qboolean D3D11_VID_Init(rendererstate_t *info, unsigned char *palette)
RegisterClass(&wc);
if (info->fullscreen)
wstyle = 0;
else
wstyle = WS_OVERLAPPEDWINDOW;
modestate = info->fullscreen?MS_FULLSCREEN:MS_WINDOWED;
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;
wstyle = WS_OVERLAPPEDWINDOW;
rect.left = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
rect.top = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
rect.right = rect.left+width;
rect.bottom = rect.top+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);
@ -1074,6 +1158,9 @@ static void (D3D11_SCR_UpdateScreen) (void)
SCR_DrawTwoDimensional(uimenu, nohud);
V_UpdatePalette (false);
if (Key_MouseShouldBeFree())
SCR_DrawCursor(0);
#if defined(_WIN32) && defined(GLQUAKE)
Media_RecordFrame();
#endif

View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="droid"
ProjectGUID="{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}"
RootNamespace="droid"
Keyword="MakeFileProj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="0"
>
<Tool
Name="VCNMakeTool"
BuildCommandLine="cd $(InputDir)\.. &amp;&amp; make droid-dbg PATH=C:\Cygwin\bin\ DROID_SDK_PATH=/cygdrive/c/Games/tools/android-sdk DROID_NDK_PATH=/cygdrive/c/Games/tools/android-ndk-r7 ANT=/cygdrive/c/Games/tools/apache-ant-1.8.2/bin/ant JAVATOOL=&quot;/cygdrive/c/Program\ Files/Java/jdk1.7.0_02/bin/&quot; -j8 DROID_ARCH=&quot;armeabi x86&quot;"
ReBuildCommandLine=""
CleanCommandLine="cd $(InputDir)\..\.. &amp;&amp; make clean -j8"
Output=""
PreprocessorDefinitions="ANDROID"
IncludeSearchPath=""
ForcedIncludes=""
AssemblySearchPath=""
ForcedUsingAssemblies=""
CompileAsManaged=""
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="0"
>
<Tool
Name="VCNMakeTool"
BuildCommandLine="cd $(InputDir)\.. &amp;&amp; make droid-rel PATH=C:\Cygwin\bin\ DROID_SDK_PATH=/cygdrive/c/Games/tools/android-sdk DROID_NDK_PATH=/cygdrive/c/Games/tools/android-ndk-r7 ANT=/cygdrive/c/Games/tools/apache-ant-1.8.2/bin/ant JAVATOOL=&quot;/cygdrive/c/Program\ Files/Java/jdk1.7.0_02/bin/&quot; -j8 DROID_ARCH=&quot;armeabi x86&quot;"
ReBuildCommandLine=""
CleanCommandLine=""
Output="$(TargetDir)\FTEDroid.apk"
PreprocessorDefinitions="ANDROID;NDEBUG"
IncludeSearchPath=""
ForcedIncludes=""
AssemblySearchPath=""
ForcedUsingAssemblies=""
CompileAsManaged=""
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\droid\src\com\fteqw\FTEDroidActivity.java"
>
</File>
<File
RelativePath="..\droid\src\com\fteqw\FTEDroidEngine.java"
>
</File>
<File
RelativePath="..\client\snd_droid.c"
>
</File>
<File
RelativePath="..\client\sys_droid.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -2,7 +2,6 @@ Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftequake", "ftequake.vcproj", "{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}"
ProjectSection(ProjectDependencies) = postProject
{32B12987-DF8C-4E40-B07C-B18586A4CA65} = {32B12987-DF8C-4E40-B07C-B18586A4CA65}
{0018E098-B12A-4E4D-9B22-6772DA287080} = {0018E098-B12A-4E4D-9B22-6772DA287080}
EndProjectSection
EndProject
@ -21,8 +20,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fteqcc", "..\qclib\dotnet20
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qtvprox", "..\..\fteqtv\dotnet2005\qtvprox.vcproj", "{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "droid", "droid\droid.vcproj", "{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nacl", "..\nacl\nacl.vcproj", "{4735677B-6D5A-4BE6-A945-CB32A7282F56}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xsv", "..\..\plugins\xsv\xsv.vcproj", "{873CCE24-3549-49D4-A4B4-653F91B1532A}"
@ -31,6 +28,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "berkplug", "..\..\plugins\b
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avplug", "..\..\plugins\avplug\avplug.vcproj", "{32B12987-DF8C-4E40-B07C-B18586A4CA65}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "droid", "droid.vcproj", "{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
D3DDebug|Win32 = D3DDebug|Win32
@ -295,30 +294,6 @@ Global
{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.Release|Win32.ActiveCfg = Release|Win32
{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.Release|Win32.Build.0 = Release|Win32
{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.Release|x64.ActiveCfg = Release|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.D3DDebug|Win32.ActiveCfg = Release|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.D3DDebug|x64.ActiveCfg = Debug|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.D3DRelease|Win32.ActiveCfg = Release|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.D3DRelease|x64.ActiveCfg = Release|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.Debug Dedicated Server|Win32.ActiveCfg = Debug|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.Debug Dedicated Server|x64.ActiveCfg = Debug|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.Debug|Win32.ActiveCfg = Debug|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.Debug|x64.ActiveCfg = Debug|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.GLDebug|Win32.ActiveCfg = Debug|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.GLDebug|x64.ActiveCfg = Debug|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.GLRelease|Win32.ActiveCfg = Release|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.GLRelease|x64.ActiveCfg = Release|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.MDebug|Win32.ActiveCfg = Debug|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.MDebug|x64.ActiveCfg = Debug|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.MinGLDebug|Win32.ActiveCfg = Debug|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.MinGLDebug|x64.ActiveCfg = Debug|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.MinGLRelease|Win32.ActiveCfg = Release|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.MinGLRelease|x64.ActiveCfg = Release|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.MRelease|Win32.ActiveCfg = Release|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.MRelease|x64.ActiveCfg = Release|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.Release Dedicated Server|Win32.ActiveCfg = Release|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.Release Dedicated Server|x64.ActiveCfg = Release|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.Release|Win32.ActiveCfg = Release|Win32
{AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.Release|x64.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32A7282F56}.D3DDebug|Win32.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32A7282F56}.D3DDebug|x64.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32A7282F56}.D3DRelease|Win32.ActiveCfg = Release|Win32
@ -443,6 +418,42 @@ Global
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.Release|Win32.ActiveCfg = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.Release|Win32.Build.0 = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.Release|x64.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.D3DDebug|Win32.Build.0 = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.D3DDebug|x64.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.D3DRelease|Win32.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.D3DRelease|Win32.Build.0 = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.D3DRelease|x64.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.Debug Dedicated Server|Win32.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.Debug Dedicated Server|Win32.Build.0 = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.Debug Dedicated Server|x64.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.Debug|Win32.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.Debug|Win32.Build.0 = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.Debug|x64.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.GLDebug|Win32.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.GLDebug|Win32.Build.0 = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.GLDebug|x64.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.GLRelease|Win32.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.GLRelease|Win32.Build.0 = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.GLRelease|x64.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.MDebug|Win32.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.MDebug|Win32.Build.0 = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.MDebug|x64.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.MinGLDebug|Win32.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.MinGLDebug|Win32.Build.0 = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.MinGLDebug|x64.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.MinGLRelease|Win32.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.MinGLRelease|Win32.Build.0 = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.MinGLRelease|x64.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.MRelease|Win32.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.MRelease|Win32.Build.0 = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.MRelease|x64.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.Release Dedicated Server|Win32.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.Release Dedicated Server|Win32.Build.0 = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.Release Dedicated Server|x64.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.Release|Win32.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.Release|Win32.Build.0 = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.Release|x64.ActiveCfg = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -1828,6 +1828,7 @@
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="../libs/dxsdk7/lib"
GenerateManifest="false"
IgnoreDefaultLibraryNames="libc.lib;msvcrt.lib"
GenerateMapFile="true"
MapFileName=".\ftequake___Win32_GLRelease/fteglqw.map"
@ -2008,7 +2009,7 @@
OmitFramePointers="true"
WholeProgramOptimization="true"
AdditionalIncludeDirectories="../libs/speex,..\client,../libs/freetype2/include,../common,../server,../gl,../sw,../qclib,../libs,../libs/dxsdk7/include,../d3d,../d3d9,../libs/dxsdk9/include"
PreprocessorDefinitions="_DEBUG;D3DQUAKE;WIN32;_WINDOWS"
PreprocessorDefinitions="_DEBUG;D3D9QUAKE;D3D11QUAKE;WIN32;_WINDOWS"
RuntimeLibrary="1"
EnableFunctionLevelLinking="true"
FloatingPointModel="2"
@ -4947,146 +4948,6 @@
<File
RelativePath="..\server\sv_sql.c"
>
<FileConfiguration
Name="MinGLDebug|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MinGLDebug|x64"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="D3DDebug|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="D3DDebug|x64"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MinGLRelease|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MinGLRelease|x64"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="GLDebug|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="GLDebug|x64"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release Dedicated Server|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release Dedicated Server|x64"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MRelease|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MRelease|x64"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Dedicated Server|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Dedicated Server|x64"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MDebug|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MDebug|x64"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="GLRelease|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="GLRelease|x64"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="D3DRelease|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="D3DRelease|x64"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\server\sv_user.c"

View File

@ -576,7 +576,7 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
skins += e->skinnum;
else
{
Con_DPrintf("Skin number out of range\n");
Con_DPrintf("Skin number out of range (%u > %u - %s)\n", e->skinnum, inf->numskins, model->name);
if (!inf->numskins)
return NULL;
}

View File

@ -29,49 +29,9 @@ extern cvar_t gl_overbright;
extern cvar_t gl_ati_truform;
extern cvar_t r_wireframe;
//simple dlight
static const char LIGHTPASS_SHADER[] = "\
{\n\
program rtlight%s\n\
{\n\
map $diffuse\n\
blendfunc add\n\
}\n\
{\n\
map $normalmap\n\
}\n\
{\n\
map $specular\n\
}\n\
}";
//dlight with cubemap projection
static const char RTLIGHTCUBEPROJ_SHADER[] = "\
{\n\
program rtlight%s\n\
{\n\
map $diffuse\n\
blendfunc add\n\
}\n\
{\n\
map $normalmap\n\
}\n\
{\n\
map $specular\n\
}\n\
{\n\
map $lightcubemap\n\
}\n\
}";
static const char PCFPASS_SHADER[] = "\
{\n\
program rtlight#PCF%s\n"/*\
program\n\
{\n\
#define LIGHTPASS\n\
//#define CUBE\n\
#define PCF\n\
%s%s\n\
}\n*/"\
\
{\n\
map $diffuse\n\
@ -115,17 +75,9 @@ struct {
// int vbo_texcoords[SHADER_PASS_MAX];
// int vbo_deforms; //holds verticies... in case you didn't realise.
const shader_t *shader_light[LSHADER_MODES];
qboolean inited_shader_light[LSHADER_MODES];
/* qboolean inited_shader_rtlight;
const shader_t *shader_rtlight;
qboolean inited_shader_cubeproj;
const shader_t *shader_cubeproj;
qboolean inited_shader_smap;
const shader_t *shader_smap;
qboolean inited_shader_spot;
const shader_t *shader_spot;
*/
const shader_t *shader_light[1u<<LSHADER_MODES];
qboolean inited_shader_light[1u<<LSHADER_MODES];
const shader_t *crepskyshader;
const shader_t *crepopaqueshader;
@ -1194,30 +1146,12 @@ static float *FTableForFunc ( unsigned int func )
return NULL;
}
void Shader_LightPass_Std(char *shortname, shader_t *s, const void *args)
void Shader_LightPass(char *shortname, shader_t *s, const void *args)
{
char shadertext[8192*2];
sprintf(shadertext, LIGHTPASS_SHADER, "");
Shader_DefaultScript(shortname, s, shadertext);
}
void Shader_LightPass_CubeProj(char *shortname, shader_t *s, const void *args)
{
char shadertext[8192*2];
sprintf(shadertext, RTLIGHTCUBEPROJ_SHADER, "#CUBEPROJ");
Shader_DefaultScript(shortname, s, shadertext);
}
void Shader_LightPass_PCF(char *shortname, shader_t *s, const void *args)
{
char shadertext[8192*2];
sprintf(shadertext, PCFPASS_SHADER, "");
Shader_DefaultScript(shortname, s, shadertext);
}
void Shader_LightPass_Spot(char *shortname, shader_t *s, const void *args)
{
char shadertext[8192*2];
sprintf(shadertext, PCFPASS_SHADER, "#SPOT");
Shader_DefaultScript(shortname, s, shadertext);
}
void GenerateFogTexture(texid_t *tex, float density, float zscale)
{
@ -3239,11 +3173,38 @@ static void BE_SelectFog(vec3_t colour, float alpha, float density)
qglColor4f(colour[0], colour[1], colour[2], alpha);
}
#ifdef RTLIGHTS
static qboolean GLBE_RegisterLightShader(int mode)
{
if (!shaderstate.inited_shader_light[mode])
{
char *name = va("rtlight%s%s%s",
(mode & (1u<<LSHADER_SMAP))?"#PCF":"",
(mode & (1u<<LSHADER_SPOT))?"#SPOT":"",
(mode & (1u<<LSHADER_CUBE))?"#CUBE":"");
shaderstate.inited_shader_light[mode] = true;
shaderstate.shader_light[mode] = R_RegisterCustom(name, Shader_LightPass, NULL);
//make sure it has a program and forget it if it doesn't, to save a compare.
if (!shaderstate.shader_light[mode] || !shaderstate.shader_light[mode]->prog)
{
shaderstate.shader_light[mode] = NULL;
}
}
if (shaderstate.shader_light[mode]);
return true;
return false;
}
#endif
void GLBE_SelectDLight(dlight_t *dl, vec3_t colour)
{
float view[16], proj[16];
int lmode;
extern cvar_t gl_specular;
extern cvar_t r_shadow_shadowmapping;
/*generate light projection information*/
float nearplane = 4;
@ -3272,12 +3233,16 @@ void GLBE_SelectDLight(dlight_t *dl, vec3_t colour)
shaderstate.lastuniform = 0;
lmode = 0;
if (dl->fov && shaderstate.shader_light[lmode|LSHADER_SPOT] && shaderstate.shader_light[lmode|LSHADER_SPOT]->prog)
lmode |= LSHADER_SPOT;
if ((dl->flags & LFLAG_SHADOWMAP) && shaderstate.shader_light[lmode|LSHADER_SMAP] && shaderstate.shader_light[lmode|LSHADER_SMAP]->prog)
lmode |= LSHADER_SMAP;
if (TEXVALID(shaderstate.lightcubemap) && shaderstate.shader_light[lmode|LSHADER_CUBE] && shaderstate.shader_light[lmode|LSHADER_CUBE]->prog)
lmode |= LSHADER_CUBE;
#ifdef RTLIGHTS
if (((dl->flags & LFLAG_SHADOWMAP) || r_shadow_shadowmapping.ival) && GLBE_RegisterLightShader(lmode | (1u<<LSHADER_SMAP)))
lmode |= 1u<<LSHADER_SMAP;
else
GLBE_RegisterLightShader(lmode); //make sure either shadowmapping or non-shadowmapping is loaded...
if (TEXVALID(shaderstate.lightcubemap) && GLBE_RegisterLightShader(lmode | (1u<<LSHADER_CUBE)))
lmode |= 1u<<LSHADER_CUBE;
else if (dl->fov && GLBE_RegisterLightShader(lmode | (1u<<LSHADER_SPOT)))
lmode |= 1u<<LSHADER_SPOT;
#endif
shaderstate.lightmode = lmode;
}
@ -3502,40 +3467,9 @@ static void DrawMeshes(void)
// break;
case BEM_LIGHT:
if (!shaderstate.shader_light[shaderstate.lightmode])
{
if (!shaderstate.inited_shader_light[shaderstate.lightmode])
{
shaderstate.inited_shader_light[shaderstate.lightmode] = true;
switch(shaderstate.lightmode)
{
case LSHADER_SMAP:
shaderstate.shader_light[shaderstate.lightmode] = R_RegisterCustom("rtlight_shadowmap", Shader_LightPass_PCF, NULL);
break;
case LSHADER_SPOT:
shaderstate.shader_light[shaderstate.lightmode] = R_RegisterCustom("rtlight_spot", Shader_LightPass_Spot, NULL);
break;
case LSHADER_STANDARD:
shaderstate.shader_light[shaderstate.lightmode] = R_RegisterCustom("rtlight", Shader_LightPass_Std, NULL);
break;
case LSHADER_CUBE:
shaderstate.shader_light[shaderstate.lightmode] = R_RegisterCustom("rtlight_cube", Shader_LightPass_CubeProj, NULL);
break;
}
if (!shaderstate.shader_light[shaderstate.lightmode] || !shaderstate.shader_light[shaderstate.lightmode]->prog)
{
shaderstate.shader_light[shaderstate.lightmode] = NULL;
break;
}
}
else
{
BE_LegacyLighting();
break;
}
}
BE_RenderMeshProgram(shaderstate.shader_light[shaderstate.lightmode], shaderstate.shader_light[shaderstate.lightmode]->passes);
BE_LegacyLighting();
else
BE_RenderMeshProgram(shaderstate.shader_light[shaderstate.lightmode], shaderstate.shader_light[shaderstate.lightmode]->passes);
break;
case BEM_DEPTHNORM:
BE_RenderMeshProgram(shaderstate.depthnormshader, shaderstate.depthnormshader->passes);

View File

@ -1353,6 +1353,11 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
int col;
int v;
struct font_s *font = curfont;
#ifdef D3D11QUAKE
float dxbias = (qrenderer == QR_DIRECT3D11)?0.5:0;
#else
#define dxbias 0
#endif
if (charcode & CON_HIDDEN)
return px;
@ -1415,29 +1420,29 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
switch(c->texplane)
{
case DEFAULTPLANE:
sx = ((px+c->left)*(int)vid.width) / (float)vid.rotpixelwidth;
sy = ((py+c->top)*(int)vid.height) / (float)vid.rotpixelheight;
sx = ((px+c->left + dxbias)*(int)vid.width) / (float)vid.rotpixelwidth;
sy = ((py+c->top + dxbias)*(int)vid.height) / (float)vid.rotpixelheight;
sw = ((font->charheight)*vid.width) / (float)vid.rotpixelwidth;
sh = ((font->charheight)*vid.height) / (float)vid.rotpixelheight;
v = Font_BeginChar(fontplanes.defaultfont);
break;
case BITMAPPLANE:
sx = ((px+c->left)*(int)vid.width) / (float)vid.rotpixelwidth;
sy = ((py+c->top)*(int)vid.height) / (float)vid.rotpixelheight;
sx = ((px+c->left + dxbias)*(int)vid.width) / (float)vid.rotpixelwidth;
sy = ((py+c->top + dxbias)*(int)vid.height) / (float)vid.rotpixelheight;
sw = ((font->charheight)*vid.width) / (float)vid.rotpixelwidth;
sh = ((font->charheight)*vid.height) / (float)vid.rotpixelheight;
v = Font_BeginChar(font->singletexture);
break;
case SINGLEPLANE:
sx = ((px+c->left)*(int)vid.width) / (float)vid.rotpixelwidth;
sy = ((py+c->top)*(int)vid.height) / (float)vid.rotpixelheight;
sx = ((px+c->left + dxbias)*(int)vid.width) / (float)vid.rotpixelwidth;
sy = ((py+c->top + dxbias)*(int)vid.height) / (float)vid.rotpixelheight;
sw = ((c->bmw)*vid.width) / (float)vid.rotpixelwidth;
sh = ((c->bmh)*vid.height) / (float)vid.rotpixelheight;
v = Font_BeginChar(font->singletexture);
break;
default:
sx = ((px+c->left)*(int)vid.width) / (float)vid.rotpixelwidth;
sy = ((py+c->top)*(int)vid.height) / (float)vid.rotpixelheight;
sx = ((px+c->left + dxbias)*(int)vid.width) / (float)vid.rotpixelwidth;
sy = ((py+c->top + dxbias)*(int)vid.height) / (float)vid.rotpixelheight;
sw = ((c->bmw)*vid.width) / (float)vid.rotpixelwidth;
sh = ((c->bmh)*vid.height) / (float)vid.rotpixelheight;
v = Font_BeginChar(fontplanes.texnum[c->texplane]);

View File

@ -1632,18 +1632,9 @@ void Terr_DrawInBounds(struct tdibctx *ctx, int x, int y, int w, int h)
void Terr_DrawTerrainModel (batch_t **batches, entity_t *e)
{
//a 512*512 heightmap
//will draw 2 tris per square, drawn twice for detail
//so a million triangles per frame if the whole thing is visible.
//with 130 to 180fps, display lists rule!
int x, y, i;
vec3_t mins, maxs;
model_t *m = e->model;
heightmap_t *hm = m->terrain;
mesh_t *mesh;
batch_t *b;
hmsection_t *s;
int bounds[4];
struct tdibctx tdibctx;

View File

@ -661,7 +661,7 @@ void R_ImportRTLights(char *entlump)
color[1] *= overridecolor[1];
color[2] *= overridecolor[2];
}
radius = light[3] * 1/*r_editlights_quakelightsizescale*/ * lightscale / fadescale;
radius = light[3] * r_editlights_import_radius.value * lightscale / fadescale;
color[0] = color[0] * light[0];
color[1] = color[1] * light[1];
color[2] = color[2] * light[2];
@ -700,6 +700,9 @@ void R_ImportRTLights(char *entlump)
dl->flags |= (pflags & PFLAGS_CORONA)?LFLAG_FLASHBLEND:0;
dl->flags |= (pflags & PFLAGS_NOSHADOW)?LFLAG_NOSHADOWS:0;
dl->style = style+1;
dl->lightcolourscales[0] = r_editlights_import_ambient.value;
dl->lightcolourscales[1] = r_editlights_import_diffuse.value;
dl->lightcolourscales[2] = r_editlights_import_specular.value;
//FIXME: cubemaps if skin >= 16
}

View File

@ -937,6 +937,8 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
};
nummodifiers = 0;
if (gl_specular.value)
permutationdefines[nummodifiers++] = strdup("#define SPECULAR\n");
for (end = strchr(name, '#'); end && *end; )
{
char *start = end+1;
@ -983,8 +985,6 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
permutationdefines[pn++] = "#define RELIEFMAPPING\n";
}
}
if (gl_specular.value)
permutationdefines[pn++] = "#define SPECULAR\n";
permutationdefines[pn++] = NULL;
if (0)
@ -1759,6 +1759,7 @@ static void Shader_SLProgramName (shader_t *shader, shaderpass_t *pass, char **p
*/
char *programbody;
char *start, *end;
char *hash;
end = *ptr;
while (*end == ' ' || *end == '\t' || *end == '\r')
@ -1807,7 +1808,16 @@ static void Shader_SLProgramName (shader_t *shader, shaderpass_t *pass, char **p
return;
}
shader->prog = Shader_FindGeneric(Shader_ParseString(ptr), qrtype);
hash = strchr(shader->name, '#');
if (hash)
{
//pass the # postfixes from the shader name onto the generic glsl to use
char newname[512];
Q_snprintfz(newname, sizeof(newname), "%s%s", Shader_ParseString(ptr), hash);
shader->prog = Shader_FindGeneric(newname, qrtype);
}
else
shader->prog = Shader_FindGeneric(Shader_ParseString(ptr), qrtype);
}
static void Shader_GLSLProgramName (shader_t *shader, shaderpass_t *pass, char **ptr)

View File

@ -2115,7 +2115,7 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON1));
/* Register the frame class */
wc.style = 0;
wc.style = CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)GLMainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;

View File

@ -1765,6 +1765,13 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_
optres_constantarithmatic++;
return QCC_MakeIntConst(G_INT(var_a->ofs) - G_INT(var_b->ofs));
case OP_ADD_IF:
optres_constantarithmatic++;
return QCC_MakeFloatConst(G_INT(var_a->ofs) + G_FLOAT(var_b->ofs));
case OP_ADD_FI:
optres_constantarithmatic++;
return QCC_MakeFloatConst(G_FLOAT(var_a->ofs) + G_INT(var_b->ofs));
case OP_AND_F:
optres_constantarithmatic++;
return QCC_MakeIntConst(G_INT(var_a->ofs) && G_INT(var_b->ofs));

View File

@ -499,6 +499,9 @@ then clears sv.multicast.
MULTICAST_ALL same as broadcast
MULTICAST_PVS send to clients potentially visible from org
MULTICAST_PHS send to clients potentially hearable from org
MULTICAST_ONE sent to a single client.
MULTICAST_INIT sent to clients when they first connect. for completeness.
=================
*/
void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int with, int without)

View File

@ -63,6 +63,7 @@ dllhandle_t *mysqlhandle;
#endif
#ifdef USE_SQLITE
#include "sqlite3.h"
SQLITE_API int (QDECL *qsqlite3_open)(const char *zFilename, sqlite3 **ppDb);
SQLITE_API const char *(QDECL *qsqlite3_libversion)(void);
SQLITE_API int (QDECL *qsqlite3_set_authorizer)(sqlite3*, int (QDECL *xAuth)(void*,int,const char*,const char*,const char*,const char*), void *pUserData);
@ -97,7 +98,7 @@ static dllfunction_t sqlitefuncs[] =
dllhandle_t *sqlitehandle;
#endif
cvar_t sql_driver = SCVARF("sv_sql_driver", "mysql", CVAR_NOUNSAFEEXPAND);
cvar_t sql_driver = SCVARF("sv_sql_driver", "", CVAR_NOUNSAFEEXPAND);
cvar_t sql_host = SCVARF("sv_sql_host", "127.0.0.1", CVAR_NOUNSAFEEXPAND);
cvar_t sql_username = SCVARF("sv_sql_username", "", CVAR_NOUNSAFEEXPAND);
cvar_t sql_password = SCVARF("sv_sql_password", "", CVAR_NOUNSAFEEXPAND);
@ -334,6 +335,7 @@ int sql_serverworker(void *sref)
char **mat;
int matsize;
int rowspace;
int totalrows = 0;
qboolean keeplooping = true;
Sys_Printf("processing %s\n", statementstring);
@ -359,6 +361,7 @@ int sql_serverworker(void *sref)
qres->rows = 0;
qres->columns = columns;
qres->request = qreq;
qres->firstrow = totalrows;
qres->eof = false;
qreq->next = NULL;
@ -381,6 +384,7 @@ int sql_serverworker(void *sref)
for (i = 0; i < columns; i++)
mat[i] = strdup(qsqlite3_column_text(pStmt, i));
qres->rows++;
totalrows++;
rowspace--;
mat += columns;
}
@ -413,14 +417,15 @@ int sql_serverworker(void *sref)
}
else
{
char *queryerror = va("Bad SQL statement %s", statementstring);
qres = (queryresult_t *)ZF_Malloc(sizeof(queryresult_t) + strlen(queryerror));
qres = (queryresult_t *)ZF_Malloc(sizeof(queryresult_t) + 18 + strlen(statementstring));
if (qres)
{
strcpy(qres->error, queryerror);
strcpy(qres->error, "Bad SQL statement ");
strcpy(qres->error+18, statementstring);
qres->result = NULL;
qres->rows = 0;
qres->columns = -1;
qres->firstrow = totalrows;
qres->request = qreq;
qres->eof = true;
qreq->next = NULL;
@ -727,10 +732,15 @@ int SQL_NewServer(char *driver, char **paramstr)
char nativepath[MAX_OSPATH];
int i, tsize;
//name matches
if (Q_strcasecmp(driver, "mysql") == 0)
drvchoice = SQLDRV_MYSQL;
else if (Q_strcasecmp(driver, "sqlite") == 0)
drvchoice = SQLDRV_SQLITE;
else if (!*driver && (sqlavailable & (1u<<SQLDRV_SQLITE)))
drvchoice = SQLDRV_SQLITE;
else if (!*driver && (sqlavailable & (1u<<SQLDRV_MYSQL)))
drvchoice = SQLDRV_MYSQL;
else // invalid driver choice so we bomb out
return -1;
@ -739,11 +749,12 @@ int SQL_NewServer(char *driver, char **paramstr)
if (drvchoice == SQLDRV_SQLITE)
{
//sqlite can be sandboxed.
//explicitly allow 'temp' and 'memory' databases
if (*paramstr[3] && strcmp(paramstr[3], ":memory:"))
{
//anything else is sandboxed into a subdir/database.
char *qname = va("qdb/%s.db", paramstr[3]);
char *qname = va("sqlite/%s.db", paramstr[3]);
if (!FS_NativePath(qname, FS_GAMEONLY, nativepath, sizeof(nativepath)))
return -1;
paramstr[3] = nativepath;
@ -1070,6 +1081,7 @@ void SQL_ServerCycle (progfuncs_t *prinst, struct globalvars_s *pr_globals)
G_FLOAT(OFS_PARM2) = qres->rows;
G_FLOAT(OFS_PARM3) = qres->columns;
G_FLOAT(OFS_PARM4) = qres->eof;
G_FLOAT(OFS_PARM5) = qres->firstrow;
// recall self and other references
ent = PROG_TO_EDICT(prinst, qres->request->selfent);
@ -1085,21 +1097,17 @@ void SQL_ServerCycle (progfuncs_t *prinst, struct globalvars_s *pr_globals)
PR_ExecuteProgram(prinst, qres->request->callback);
if (qres->eof)
if (server->currentresult)
{
if (server->currentresult)
if (server->currentresult->request && server->currentresult->request->persistant)
{
if (server->currentresult->request && server->currentresult->request->persistant)
{
// move into persistant list
server->currentresult->next = server->persistresults;
server->persistresults = server->currentresult;
}
else // just close the query
SQL_CloseResult(server, server->currentresult);
// move into persistant list
server->currentresult->next = server->persistresults;
server->persistresults = server->currentresult;
}
else // just close the query
SQL_CloseResult(server, server->currentresult);
}
// TODO: else we move a request back into the queue?
}
}
else // error or server-only result
@ -1114,46 +1122,47 @@ void SQL_ServerCycle (progfuncs_t *prinst, struct globalvars_s *pr_globals)
}
#ifdef USE_MYSQL
void SQL_MYSQLInit(void)
qboolean SQL_MYSQLInit(void)
{
if (!(mysqlhandle = Sys_LoadLibrary("libmysql", mysqlfuncs)))
if ((mysqlhandle = Sys_LoadLibrary("libmysql", mysqlfuncs)))
{
Con_Printf("mysql client didn't load\n");
return;
}
if (qmysql_thread_safe())
{
if (!qmysql_library_init(0, NULL, NULL))
if (qmysql_thread_safe())
{
Con_Printf("MYSQL backend loaded\n");
sqlavailable |= 1u<<SQLDRV_MYSQL;
return;
if (!qmysql_library_init(0, NULL, NULL))
{
Con_Printf("MYSQL backend loaded\n");
return true;
}
else
Con_Printf("MYSQL library init failed!\n");
}
else
Con_Printf("MYSQL library init failed!\n");
Con_Printf("MYSQL client is not thread safe!\n");
Sys_CloseLibrary(mysqlhandle);
}
else
Con_Printf("MYSQL client is not thread safe!\n");
Sys_CloseLibrary(mysqlhandle);
sqlavailable &= ~(1u<<SQLDRV_MYSQL);
{
Con_Printf("mysql client didn't load\n");
}
return false;
}
#endif
void SQL_Init(void)
{
sqlavailable = 0;
#ifdef USE_MYSQL
//mysql pokes network etc. there's no sandbox. people can use quake clients to pry upon private databases.
if (COM_CheckParm("-mysql"))
SQL_MYSQLInit();
if (SQL_MYSQLInit())
sqlavailable |= 1u<<SQLDRV_MYSQL;
#endif
#ifdef USE_SQLITE
//our sqlite implementation is sandboxed. we block database attachments, and restrict the master database name.
if (Sys_LoadLibrary("sqlite3", sqlitefuncs))
sqlitehandle = Sys_LoadLibrary("sqlite3", sqlitefuncs);
if (sqlitehandle)
{
if (!sqlavailable)
sql_driver.string = "sqlite"; //use this by default if its the only one available.
sqlavailable |= 1u<<SQLDRV_SQLITE;
}
#endif

View File

@ -8,10 +8,6 @@
#include <mysql/mysql.h>
#endif
#ifdef USE_SQLITE
#include "sqlite3.h"
#endif
#define SQL_CONNECT_STRUCTPARAMS 2
#define SQL_CONNECT_PARAMS 4
@ -40,6 +36,7 @@ typedef struct queryresult_s
struct queryrequest_s *request; /* corresponding request */
struct queryresult_s *next; /* next result in queue */
int rows; /* rows contained in single result set */
int firstrow; /* 0 on first result block */
int columns; /* fields */
qboolean eof; /* end of query reached */
void *result; /* result set from mysql */
@ -57,7 +54,7 @@ typedef struct sqlserver_s
MYSQL *mysql; /* mysql server */
#endif
#ifdef USE_SQLITE
sqlite3 *sqlite;
struct sqlite3 *sqlite;
#endif
volatile qboolean active; /* set to false to kill thread */
volatile qboolean terminated; /* set by the worker to say that it won't block (for long) and can be joined */

View File

@ -1420,238 +1420,6 @@ void CreateSampleService(qboolean create)
}
#endif
#ifdef MULTITHREAD
/* Thread creation calls */
typedef struct threadwrap_s
{
void (*func)(void *);
void *args;
} threadwrap_t;
// the thread call is wrapped so we don't need WINAPI everywhere
DWORD WINAPI threadwrapper(void *args)
{
threadwrap_t tw;
tw.func = ((threadwrap_t *)args)->func;
tw.args = ((threadwrap_t *)args)->args;
free(args);
tw.func(tw.args);
#ifndef WIN32CRTDLL
_endthreadex(0);
#endif
return 0;
}
void *Sys_CreateThread(char *name, int (*func)(void *), void *args, int priority, int stacksize)
{
threadwrap_t *tw = (threadwrap_t *)malloc(sizeof(threadwrap_t));
HANDLE handle;
if (!tw)
return NULL;
stacksize += 128; // wrapper overhead, also prevent default stack size
tw->func = func;
tw->args = args;
#ifdef WIN32CRTDLL
handle = (HANDLE)CreateThread(NULL, stacksize, &threadwrapper, (void *)tw, 0, NULL);
#else
handle = (HANDLE)_beginthreadex(NULL, stacksize, &threadwrapper, (void *)tw, 0, NULL);
#endif
if (!handle)
{
free(tw);
return NULL;
}
return (void *)handle;
}
void Sys_WaitOnThread(void *thread)
{
WaitForSingleObject((HANDLE)thread, INFINITE);
CloseHandle((HANDLE)thread);
}
/* Mutex calls */
void *Sys_CreateMutex(void)
{
return (void *)CreateMutex(NULL, 0, NULL);
}
qboolean Sys_TryLockMutex(void *mutex)
{
return WaitForSingleObject(mutex, 0) == WAIT_OBJECT_0;
}
qboolean Sys_LockMutex(void *mutex)
{
return WaitForSingleObject(mutex, INFINITE) == WAIT_OBJECT_0;
}
qboolean Sys_UnlockMutex(void *mutex)
{
return !!ReleaseMutex(mutex);
}
void Sys_DestroyMutex(void *mutex)
{
CloseHandle(mutex);
}
/* Conditional wait calls */
/*
TODO: Windows Vista has condition variables as documented here:
http://msdn.microsoft.com/en-us/library/ms682052(VS.85).aspx
Note this uses Slim Reader/Writer locks (Vista+ exclusive)
or critical sections.
The condition variable implementation is based on the libSDL implementation.
This code could probably be made more efficient with the use of events or
different mechanisms but for now the main concern is a correct and
complete solution.
*/
typedef struct condvar_s
{
int waiting;
int signals;
CRITICAL_SECTION countlock;
CRITICAL_SECTION mainlock;
HANDLE wait_sem;
HANDLE wait_done;
} condvar_t;
void *Sys_CreateConditional(void)
{
condvar_t *cv;
cv = (condvar_t *)malloc(sizeof(condvar_t));
if (!cv)
return NULL;
cv->waiting = 0;
cv->signals = 0;
InitializeCriticalSection (&cv->mainlock);
InitializeCriticalSection (&cv->countlock);
cv->wait_sem = CreateSemaphore (NULL, 0, 0x7fffffff, NULL);
cv->wait_done = CreateSemaphore (NULL, 0, 0x7fffffff, NULL);
if (cv->wait_sem && cv->wait_done)
return (void *)cv;
// something failed so deallocate everything
if (cv->wait_done)
CloseHandle(cv->wait_done);
if (cv->wait_sem)
CloseHandle(cv->wait_sem);
DeleteCriticalSection(&cv->countlock);
DeleteCriticalSection(&cv->mainlock);
free(cv);
return NULL;
}
qboolean Sys_LockConditional(void *condv)
{
EnterCriticalSection(&((condvar_t *)condv)->mainlock);
return true;
}
qboolean Sys_UnlockConditional(void *condv)
{
LeaveCriticalSection(&((condvar_t *)condv)->mainlock);
return true;
}
qboolean Sys_ConditionWait(void *condv)
{
condvar_t *cv = (condvar_t *)condv;
qboolean success;
// increase count for non-signaled waiting threads
EnterCriticalSection(&cv->countlock);
cv->waiting++;
LeaveCriticalSection(&cv->countlock);
LeaveCriticalSection(&cv->mainlock); // unlock as per condition variable definition
// wait on a signal
success = (WaitForSingleObject(cv->wait_sem, INFINITE) != WAIT_FAILED);
// update waiting count and alert signaling thread that we're done to avoid the deadlock condition
EnterCriticalSection(&cv->countlock);
if (cv->signals > 0)
{
ReleaseSemaphore(cv->wait_done, cv->signals, NULL);
cv->signals = 0;
}
cv->waiting--;
LeaveCriticalSection(&cv->countlock);
EnterCriticalSection(&cv->mainlock); // lock as per condition variable definition
return success;
}
qboolean Sys_ConditionSignal(void *condv)
{
condvar_t *cv = (condvar_t *)condv;
// if there are non-signaled waiting threads, we signal one and wait on the response
EnterCriticalSection(&cv->countlock);
if (cv->waiting > cv->signals)
{
cv->signals++;
ReleaseSemaphore(cv->wait_sem, 1, NULL);
LeaveCriticalSection(&cv->countlock);
WaitForSingleObject(cv->wait_done, INFINITE);
}
else
LeaveCriticalSection(&cv->countlock);
return true;
}
qboolean Sys_ConditionBroadcast(void *condv)
{
condvar_t *cv = (condvar_t *)condv;
// if there are non-signaled waiting threads, we signal all of them and wait on all the responses back
EnterCriticalSection(&cv->countlock);
if (cv->waiting > cv->signals)
{
int i, num_waiting;
num_waiting = (cv->waiting - cv->signals);
cv->signals = cv->waiting;
ReleaseSemaphore(cv->wait_sem, num_waiting, NULL);
LeaveCriticalSection(&cv->countlock);
// there's no call to wait for the same object multiple times so we need to loop through
// and burn up the semaphore count
for (i = 0; i < num_waiting; i++)
WaitForSingleObject(cv->wait_done, INFINITE);
}
else
LeaveCriticalSection(&cv->countlock);
return true;
}
void Sys_DestroyConditional(void *condv)
{
condvar_t *cv = (condvar_t *)condv;
CloseHandle(cv->wait_done);
CloseHandle(cv->wait_sem);
DeleteCriticalSection(&cv->countlock);
DeleteCriticalSection(&cv->mainlock);
free(cv);
}
#endif
void Sys_Sleep (double seconds)
{
Sleep(seconds * 1000);