diff --git a/engine/Makefile b/engine/Makefile index 8af871950..a8e4bc8bd 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -1108,8 +1108,9 @@ ifeq ($(FTE_TARGET),droid) endif ifeq ($(FTE_TARGET),web) - RELEASE_CFLAGS=-O1 -DOMIT_QCC -DGL_STATIC - CC=emcc -DFTE_TARGET_WEB -s TOTAL_MEMORY=268435456 -s FULL_ES2=1 + RELEASE_CFLAGS=-O1 -DOMIT_QCC -DGL_STATIC -DFTE_TARGET_WEB --pre-js web/prejs.js + DEBUG_CFLAGS=-O0 -g --jcache -DOMIT_QCC -DGL_STATIC -DFTE_TARGET_WEB --pre-js web/prejs.js + CC=emcc -s TOTAL_MEMORY=268435456 #-s ASM_JS=1 #BASELDFLAGS= @@ -1132,6 +1133,9 @@ ifeq ($(FTE_TARGET),web) GLB_DIR=gl_web GL_EXE_NAME=../ftewebgl.html + GL_LDFLAGS=$(GLLDFLAGS) $(IMAGELDFLAGS) $(OGGVORBISLDFLAGS) + GL_CFLAGS=$(GLCFLAGS) + IMAGELDFLAGS= OGGVORBISLDFLAGS= diff --git a/engine/client/in_sdl.c b/engine/client/in_sdl.c index 95ca6685d..079099516 100644 --- a/engine/client/in_sdl.c +++ b/engine/client/in_sdl.c @@ -397,6 +397,12 @@ void Sys_SendKeyEvents(void) case QR_OPENGL: vid.pixelwidth = event.resize.w; vid.pixelheight = event.resize.h; + { + extern cvar_t vid_conautoscale, vid_conwidth; //make sure the screen is updated properly. + Cvar_ForceCallback(&vid_conautoscale); + Cvar_ForceCallback(&vid_conwidth); + } + break; #endif } diff --git a/engine/client/renderer.c b/engine/client/renderer.c index ee55a889d..8faba8293 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -350,7 +350,11 @@ 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); +#ifdef FTE_TARGET_WEB +cvar_t r_shadow_realtime_dlight = SCVARF ("r_shadow_realtime_dlight", "0", CVAR_ARCHIVE); +#else cvar_t r_shadow_realtime_dlight = SCVARF ("r_shadow_realtime_dlight", "1", CVAR_ARCHIVE); +#endif cvar_t r_shadow_realtime_dlight_shadows = SCVARF ("r_shadow_realtime_dlight_shadows", "1", CVAR_ARCHIVE); 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"); diff --git a/engine/client/sys_sdl.c b/engine/client/sys_sdl.c index a75ae21ea..41a7c8aaa 100644 --- a/engine/client/sys_sdl.c +++ b/engine/client/sys_sdl.c @@ -74,7 +74,7 @@ unsigned int Sys_Milliseconds(void) if (newtime < oldtime) Con_Printf("Sys_Milliseconds stepped backwards!\n"); else - curtime += oldtime - newtime; + curtime += newtime - oldtime; oldtime = newtime; return curtime; } @@ -82,6 +82,8 @@ unsigned int Sys_Milliseconds(void) //return the current time, in the form of a double double Sys_DoubleTime (void) { + return Sys_Milliseconds() / 1000.0; +/* static int first = true; static double oldtime = 0.0, curtime = 0.0; double newtime; @@ -106,6 +108,7 @@ double Sys_DoubleTime (void) oldtime = newtime; return curtime; +*/ } //create a directory @@ -500,12 +503,15 @@ int QDECL main(int argc, char **argv) memset(&parms, 0, sizeof(parms)); - parms.argv = argv; +#ifdef FTE_TARGET_WEB + parms.basedir = ""; +#else parms.basedir = "."; +#endif parms.argc = argc; - parms.argv = argv; + parms.argv = (const char**)argv; #ifndef WIN32 fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY); diff --git a/engine/common/mathlib.h b/engine/common/mathlib.h index 3ba638050..76307c9db 100644 --- a/engine/common/mathlib.h +++ b/engine/common/mathlib.h @@ -42,7 +42,16 @@ typedef vec4_t avec4_t; typedef qbyte byte_vec4_t[4]; #endif -#define vecV_t avec4_t +//VECV_STRIDE is used only as an argument for opengl. +#ifdef FTE_TARGET_WEB + //emscripten is alergic to explicit strides without packed attributes, at least in emulated code. + //so we need to keep everything packed. screw sse-friendly packing. + #define vecV_t vec3_t + #define VECV_STRIDE 0 +#else + #define vecV_t avec4_t + #define VECV_STRIDE sizeof(vecV_t) +#endif typedef int fixed4_t; typedef int fixed8_t; diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index 25cd3435f..d91cb3913 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -1797,6 +1797,9 @@ static void FTENET_NATPMP_Refresh(pmpcon_t *pmp, short oldport, ftenet_connectio else pmp->pmpaddr = pmp->reqpmpaddr; + if (*(int*)pmp->pmpaddr.address.ip == INADDR_ANY) + continue; + //get the public ip. pmpreqmsg.op = 0; NET_SendPacket(NS_SERVER, 2, &pmpreqmsg, pmp->pmpaddr); @@ -1804,6 +1807,8 @@ static void FTENET_NATPMP_Refresh(pmpcon_t *pmp, short oldport, ftenet_connectio //open the firewall/nat. pmpreqmsg.op = 1; NET_SendPacket(NS_SERVER, sizeof(pmpreqmsg), &pmpreqmsg, pmp->pmpaddr); + + break; } } } @@ -1824,6 +1829,7 @@ qboolean FTENET_NATPMP_GetPacket(struct ftenet_generic_connection_s *con) unsigned int now = Sys_Milliseconds(); if (now - pmp->refreshtime > PMP_POLL_TIME) //weird logic to cope with wrapping { +Con_Printf("nat-pmp refresh (%u - %u > %u)\n", now, pmp->refreshtime, PMP_POLL_TIME); pmp->refreshtime = now; FTENET_NATPMP_Refresh(pmp, pmp->natadr.port, pmp->col); } @@ -1833,11 +1839,10 @@ qboolean FTENET_NATPMP_SendPacket(struct ftenet_generic_connection_s *con, int l { return false; } -qboolean FTENET_NATPMP_Close(struct ftenet_generic_connection_s *con) +void FTENET_NATPMP_Close(struct ftenet_generic_connection_s *con) { //FIXME: we should send a packet to close the port Z_Free(con); - return true; } ftenet_generic_connection_t *FTENET_NATPMP_EstablishConnection(qboolean isserver, const char *address) { @@ -2479,6 +2484,7 @@ typedef struct ftenet_tcpconnect_stream_s { enum { TCPC_UNKNOWN, + TCPC_UNFRAMED, //something else is doing the framing (ie: we're running in emscripten and over some hidden websocket connection) TCPC_QIZMO, TCPC_WEBSOCKET } clienttype; @@ -2869,6 +2875,17 @@ handshakeerror: net_message.currentbit = 0; net_from = st->remoteaddr; + return true; + case TCPC_UNFRAMED: + if (!st->inlen) + continue; + net_message.cursize = st->inlen; + memcpy(net_message_buffer, st->inbuffer, net_message.cursize); + st->inlen = 0; + + net_message.packing = SZ_RAWBYTES; + net_message.currentbit = 0; + net_from = st->remoteaddr; return true; case TCPC_WEBSOCKET: while (st->inlen >= 2) @@ -3094,6 +3111,14 @@ qboolean FTENET_TCPConnect_SendPacket(ftenet_generic_connection_t *gcon, int len } } break; + case TCPC_UNFRAMED: + if (length > sizeof(st->outbuffer)) + { + Con_DPrintf("FTENET_TCPConnect_SendPacket: outgoing overflow\n"); + } + memcpy(st->outbuffer, data, length); + st->outlen = length; + break; case TCPC_WEBSOCKET: { /*as a server, we don't need the mask stuff*/ @@ -3185,6 +3210,7 @@ void FTENET_TCPConnect_Close(ftenet_generic_connection_t *gcon) FTENET_Generic_Close(gcon); } +#ifdef HAVE_PACKET int FTENET_TCPConnect_SetReceiveFDSet(ftenet_generic_connection_t *gcon, fd_set *fdset) { int maxfd = 0; @@ -3207,6 +3233,7 @@ int FTENET_TCPConnect_SetReceiveFDSet(ftenet_generic_connection_t *gcon, fd_set } return maxfd; } +#endif ftenet_generic_connection_t *FTENET_TCPConnect_EstablishConnection(int affamily, qboolean isserver, const char *address) { @@ -3221,9 +3248,17 @@ ftenet_generic_connection_t *FTENET_TCPConnect_EstablishConnection(int affamily, int family; if (!strncmp(address, "tcp://", 6)) address += 6; + if (!strncmp(address, "ws://", 5)) + address += 5; + if (!strncmp(address, "wss://", 6)) + address += 6; if (isserver) { +#ifndef HAVE_PACKET + //unable to listen on tcp if we have no packet interface + return NULL; +#else if (!NET_PortToAdr(affamily, address, &adr)) return NULL; //couldn't resolve the name if (adr.type == NA_IP) @@ -3250,10 +3285,11 @@ ftenet_generic_connection_t *FTENET_TCPConnect_EstablishConnection(int affamily, if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) Sys_Error ("UDP_OpenSocket: ioctl FIONBIO: %s", strerror(qerrno)); +#endif } else { - if (!NET_PortToAdr(affamily, address, &adr)) + if (!NET_StringToAdr(address, 0, &adr)) return NULL; //couldn't resolve the name if (adr.type == NA_IP) @@ -3274,7 +3310,9 @@ ftenet_generic_connection_t *FTENET_TCPConnect_EstablishConnection(int affamily, newcon->generic.GetPacket = FTENET_TCPConnect_GetPacket; newcon->generic.SendPacket = FTENET_TCPConnect_SendPacket; newcon->generic.Close = FTENET_TCPConnect_Close; +#ifdef HAVE_PACKET newcon->generic.SetReceiveFDSet = FTENET_TCPConnect_SetReceiveFDSet; +#endif newcon->generic.islisten = isserver; newcon->generic.addrtype[0] = adr.type; @@ -3288,15 +3326,19 @@ ftenet_generic_connection_t *FTENET_TCPConnect_EstablishConnection(int affamily, newcon->active++; newcon->tcpstreams = Z_Malloc(sizeof(*newcon->tcpstreams)); - newcon->tcpstreams->clienttype = TCPC_UNKNOWN; newcon->tcpstreams->next = NULL; newcon->tcpstreams->socketnum = newsocket; newcon->tcpstreams->inlen = 0; newcon->tcpstreams->remoteaddr = adr; +#ifdef FTE_TARGET_WEB + newcon->tcpstreams->clienttype = TCPC_UNFRAMED; +#else //send the qizmo greeting. + newcon->tcpstreams->clienttype = TCPC_UNKNOWN; send(newsocket, "qizmo\n", 6, 0); +#endif newcon->tcpstreams->timeouttime = Sys_DoubleTime() + 30; } @@ -5054,7 +5096,7 @@ void NET_InitServer(void) #ifdef USEIPX Cvar_ForceCallback(&sv_port_ipx); #endif -#ifdef TCPCONNECT +#if defined(TCPCONNECT) && defined(HAVE_TCP) Cvar_ForceCallback(&sv_port_tcp); #ifdef IPPROTO_IPV6 Cvar_ForceCallback(&sv_port_tcp6); diff --git a/engine/common/netinc.h b/engine/common/netinc.h index 4dde4d384..02dae0cca 100644 --- a/engine/common/netinc.h +++ b/engine/common/netinc.h @@ -5,6 +5,10 @@ #define HAVE_PACKET //if we have the socket api at all... #endif +#ifdef FTE_TARGET_WEB +#undef HAVE_PACKET //no udp packet interface. +#endif + #ifdef NACL struct sockaddr diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index a52778ea8..ade09eda9 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -386,10 +386,13 @@ void GL_MTBind(int tmu, int target, texid_t texnum) if (target) qglBindTexture (target, texnum.num); + if ( #ifndef FORCESTATE - if (shaderstate.curtexturetype[tmu] != target && !gl_config.nofixedfunc) + shaderstate.curtexturetype[tmu] != target && #endif + !gl_config.nofixedfunc) { + if (shaderstate.curtexturetype[tmu]) qglDisable(shaderstate.curtexturetype[tmu]); shaderstate.curtexturetype[tmu] = target; @@ -520,7 +523,7 @@ static void BE_ApplyAttributes(unsigned int bitstochange, unsigned int bitstoend shaderstate.curvertexpointer = shaderstate.pendingvertexpointer; shaderstate.curvertexvbo = shaderstate.pendingvertexvbo; GL_SelectVBO(shaderstate.curvertexvbo); - qglVertexPointer(3, GL_FLOAT, sizeof(vecV_t), shaderstate.curvertexpointer); + qglVertexPointer(3, GL_FLOAT, VECV_STRIDE, shaderstate.curvertexpointer); } if ((bitstoendisable) & (1u<coord2.gl.vbo && !shaderstate.sourcevbo->coord2.gl.addr) { GL_SelectVBO(shaderstate.pendingvertexvbo); - qglVertexAttribPointer(i, 3, GL_FLOAT, GL_FALSE, sizeof(vecV_t), shaderstate.pendingvertexpointer); + qglVertexAttribPointer(i, 3, GL_FLOAT, GL_FALSE, VECV_STRIDE, shaderstate.pendingvertexpointer); } else { GL_SelectVBO(shaderstate.sourcevbo->coord2.gl.vbo); - qglVertexAttribPointer(VATTR_VERTEX2, 3, GL_FLOAT, GL_FALSE, sizeof(vecV_t), shaderstate.sourcevbo->coord2.gl.addr); + qglVertexAttribPointer(VATTR_VERTEX2, 3, GL_FLOAT, GL_FALSE, VECV_STRIDE, shaderstate.sourcevbo->coord2.gl.addr); } break; case VATTR_COLOUR: @@ -571,31 +574,31 @@ static void BE_ApplyAttributes(unsigned int bitstochange, unsigned int bitstoend break; case VATTR_TEXCOORD: GL_SelectVBO(shaderstate.sourcevbo->texcoord.gl.vbo); - qglVertexAttribPointer(VATTR_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->texcoord.gl.addr); + qglVertexAttribPointer(VATTR_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, shaderstate.sourcevbo->texcoord.gl.addr); break; case VATTR_LMCOORD: if (!shaderstate.sourcevbo->lmcoord[0].gl.vbo && !shaderstate.sourcevbo->lmcoord[0].gl.addr) { GL_SelectVBO(shaderstate.sourcevbo->texcoord.gl.vbo); - qglVertexAttribPointer(VATTR_LMCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->texcoord.gl.addr); + qglVertexAttribPointer(VATTR_LMCOORD, 2, GL_FLOAT, GL_FALSE, 0, shaderstate.sourcevbo->texcoord.gl.addr); } else { GL_SelectVBO(shaderstate.sourcevbo->lmcoord[0].gl.vbo); - qglVertexAttribPointer(VATTR_LMCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->lmcoord[0].gl.addr); + qglVertexAttribPointer(VATTR_LMCOORD, 2, GL_FLOAT, GL_FALSE, 0, shaderstate.sourcevbo->lmcoord[0].gl.addr); } break; case VATTR_LMCOORD2: GL_SelectVBO(shaderstate.sourcevbo->lmcoord[1].gl.vbo); - qglVertexAttribPointer(VATTR_LMCOORD2, 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->lmcoord[1].gl.addr); + qglVertexAttribPointer(VATTR_LMCOORD2, 2, GL_FLOAT, GL_FALSE, 0, shaderstate.sourcevbo->lmcoord[1].gl.addr); break; case VATTR_LMCOORD3: GL_SelectVBO(shaderstate.sourcevbo->lmcoord[2].gl.vbo); - qglVertexAttribPointer(VATTR_LMCOORD3, 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->lmcoord[2].gl.addr); + qglVertexAttribPointer(VATTR_LMCOORD3, 2, GL_FLOAT, GL_FALSE, 0, shaderstate.sourcevbo->lmcoord[2].gl.addr); break; case VATTR_LMCOORD4: GL_SelectVBO(shaderstate.sourcevbo->lmcoord[3].gl.vbo); - qglVertexAttribPointer(VATTR_LMCOORD4, 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->lmcoord[3].gl.addr); + qglVertexAttribPointer(VATTR_LMCOORD4, 2, GL_FLOAT, GL_FALSE, 0, shaderstate.sourcevbo->lmcoord[3].gl.addr); break; case VATTR_NORMALS: if (!shaderstate.sourcevbo->normals.gl.addr) @@ -605,7 +608,7 @@ static void BE_ApplyAttributes(unsigned int bitstochange, unsigned int bitstoend continue; } GL_SelectVBO(shaderstate.sourcevbo->normals.gl.vbo); - qglVertexAttribPointer(VATTR_NORMALS, 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->normals.gl.addr); + qglVertexAttribPointer(VATTR_NORMALS, 3, GL_FLOAT, GL_FALSE, 0, shaderstate.sourcevbo->normals.gl.addr); break; case VATTR_SNORMALS: if (!shaderstate.sourcevbo->svector.gl.addr) @@ -615,7 +618,7 @@ static void BE_ApplyAttributes(unsigned int bitstochange, unsigned int bitstoend continue; } GL_SelectVBO(shaderstate.sourcevbo->svector.gl.vbo); - qglVertexAttribPointer(VATTR_SNORMALS, 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->svector.gl.addr); + qglVertexAttribPointer(VATTR_SNORMALS, 3, GL_FLOAT, GL_FALSE, 0, shaderstate.sourcevbo->svector.gl.addr); break; case VATTR_TNORMALS: if (!shaderstate.sourcevbo->tvector.gl.addr) @@ -625,15 +628,15 @@ static void BE_ApplyAttributes(unsigned int bitstochange, unsigned int bitstoend continue; } GL_SelectVBO(shaderstate.sourcevbo->tvector.gl.vbo); - qglVertexAttribPointer(VATTR_TNORMALS, 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->tvector.gl.addr); + qglVertexAttribPointer(VATTR_TNORMALS, 3, GL_FLOAT, GL_FALSE, 0, shaderstate.sourcevbo->tvector.gl.addr); break; case VATTR_BONENUMS: GL_SelectVBO(shaderstate.sourcevbo->bonenums.gl.vbo); - qglVertexAttribPointer(VATTR_BONENUMS, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(byte_vec4_t), shaderstate.sourcevbo->bonenums.gl.addr); + qglVertexAttribPointer(VATTR_BONENUMS, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, shaderstate.sourcevbo->bonenums.gl.addr); break; case VATTR_BONEWEIGHTS: GL_SelectVBO(shaderstate.sourcevbo->boneweights.gl.vbo); - qglVertexAttribPointer(VATTR_BONEWEIGHTS, 4, GL_FLOAT, GL_FALSE, sizeof(vec4_t), shaderstate.sourcevbo->boneweights.gl.addr); + qglVertexAttribPointer(VATTR_BONEWEIGHTS, 4, GL_FLOAT, GL_FALSE, 0, shaderstate.sourcevbo->boneweights.gl.addr); break; } if ((bitstoendisable) & (1u<coord.gl.vbo; } +#ifdef FTE_TARGET_WEB + if (!shaderstate.pendingvertexvbo) + return; + if (!shaderstate.sourcevbo->indicies.gl.vbo) + return; +#endif + BE_PolyOffset(shaderstate.flags & BEF_PUSHDEPTH); switch(shaderstate.mode) { diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 195df3128..b1a60addf 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -57,6 +57,37 @@ void (APIENTRY *qglStencilOpSeparateATI) (GLenum face, GLenum fail, GLenum zfail //quick hack that made quake work on both 1+ext and 1.1 gl implementations. BINDTEXFUNCPTR qglBindTexture; + + +/*glslang - arb_shader_objects +gl core uses different names/distinctions from the extension +*/ +FTEPFNGLCREATEPROGRAMOBJECTARBPROC qglCreateProgramObjectARB; +FTEPFNGLDELETEOBJECTARBPROC qglDeleteProgramObject_; +FTEPFNGLDELETEOBJECTARBPROC qglDeleteShaderObject_; +FTEPFNGLUSEPROGRAMOBJECTARBPROC qglUseProgramObjectARB; +FTEPFNGLCREATESHADEROBJECTARBPROC qglCreateShaderObjectARB; +FTEPFNGLSHADERSOURCEARBPROC qglShaderSourceARB; +FTEPFNGLCOMPILESHADERARBPROC qglCompileShaderARB; +FTEPFNGLGETOBJECTPARAMETERIVARBPROC qglGetShaderParameteriv_; +FTEPFNGLGETOBJECTPARAMETERIVARBPROC qglGetProgramParameteriv_; +FTEPFNGLATTACHOBJECTARBPROC qglAttachObjectARB; +FTEPFNGLGETINFOLOGARBPROC qglGetShaderInfoLog_; +FTEPFNGLGETINFOLOGARBPROC qglGetProgramInfoLog_; +FTEPFNGLLINKPROGRAMARBPROC qglLinkProgramARB; +FTEPFNGLBINDATTRIBLOCATIONARBPROC qglBindAttribLocationARB; +FTEPFNGLGETATTRIBLOCATIONARBPROC qglGetAttribLocationARB; +FTEPFNGLGETUNIFORMLOCATIONARBPROC qglGetUniformLocationARB; +FTEPFNGLUNIFORMMATRIXPROC qglUniformMatrix4fvARB; +FTEPFNGLUNIFORMMATRIXPROC qglUniformMatrix3x4fv; +FTEPFNGLUNIFORMMATRIXPROC qglUniformMatrix4x3fv; +FTEPFNGLUNIFORM4FARBPROC qglUniform4fARB; +FTEPFNGLUNIFORM4FVARBPROC qglUniform4fvARB; +FTEPFNGLUNIFORM3FARBPROC qglUniform3fARB; +FTEPFNGLUNIFORM3FVARBPROC qglUniform3fvARB; +FTEPFNGLUNIFORM4FVARBPROC qglUniform2fvARB; +FTEPFNGLUNIFORM1IARBPROC qglUniform1iARB; +FTEPFNGLUNIFORM1FARBPROC qglUniform1fARB; #endif //standard 1.1 opengl calls void (APIENTRY *qglAlphaFunc) (GLenum func, GLclampf ref); @@ -152,35 +183,6 @@ PFNGLGENPROGRAMSARBPROC qglGenProgramsARB; FTEPFNGLLOCKARRAYSEXTPROC qglLockArraysEXT; FTEPFNGLUNLOCKARRAYSEXTPROC qglUnlockArraysEXT; -/*glslang - arb_shader_objects -gl core uses different names/distinctions from the extension -*/ -FTEPFNGLCREATEPROGRAMOBJECTARBPROC qglCreateProgramObjectARB; -FTEPFNGLDELETEOBJECTARBPROC qglDeleteProgramObject_; -FTEPFNGLDELETEOBJECTARBPROC qglDeleteShaderObject_; -FTEPFNGLUSEPROGRAMOBJECTARBPROC qglUseProgramObjectARB; -FTEPFNGLCREATESHADEROBJECTARBPROC qglCreateShaderObjectARB; -FTEPFNGLSHADERSOURCEARBPROC qglShaderSourceARB; -FTEPFNGLCOMPILESHADERARBPROC qglCompileShaderARB; -FTEPFNGLGETOBJECTPARAMETERIVARBPROC qglGetShaderParameteriv_; -FTEPFNGLGETOBJECTPARAMETERIVARBPROC qglGetProgramParameteriv_; -FTEPFNGLATTACHOBJECTARBPROC qglAttachObjectARB; -FTEPFNGLGETINFOLOGARBPROC qglGetShaderInfoLog_; -FTEPFNGLGETINFOLOGARBPROC qglGetProgramInfoLog_; -FTEPFNGLLINKPROGRAMARBPROC qglLinkProgramARB; -FTEPFNGLBINDATTRIBLOCATIONARBPROC qglBindAttribLocationARB; -FTEPFNGLGETATTRIBLOCATIONARBPROC qglGetAttribLocationARB; -FTEPFNGLGETUNIFORMLOCATIONARBPROC qglGetUniformLocationARB; -FTEPFNGLUNIFORMMATRIXPROC qglUniformMatrix4fvARB; -FTEPFNGLUNIFORMMATRIXPROC qglUniformMatrix3x4fv; -FTEPFNGLUNIFORMMATRIXPROC qglUniformMatrix4x3fv; -FTEPFNGLUNIFORM4FARBPROC qglUniform4fARB; -FTEPFNGLUNIFORM4FVARBPROC qglUniform4fvARB; -FTEPFNGLUNIFORM3FARBPROC qglUniform3fARB; -FTEPFNGLUNIFORM3FVARBPROC qglUniform3fvARB; -FTEPFNGLUNIFORM4FVARBPROC qglUniform2fvARB; -FTEPFNGLUNIFORM1IARBPROC qglUniform1iARB; -FTEPFNGLUNIFORM1FARBPROC qglUniform1fARB; //extensions //arb multitexture @@ -395,11 +397,6 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) else gl_config.gles = false; - if (webgl) - { - gl_major_version = 2; - gl_minor_version = 0; - } if (!gl_config.gles) { if (qglGetError()) @@ -420,6 +417,8 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) s++; gl_minor_version = atoi(s); } + if (webgl) + gl_major_version+=1; //yes, I know, this can't cope with minor versions of 10+... I don't care yet. gl_config.glversion += gl_major_version + (gl_minor_version/10.f); @@ -720,7 +719,9 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) qglUnmapBufferARB = (void *)getglext("glUnmapBufferARB"); } -#ifndef GL_STATIC +#ifdef GL_STATIC + gl_config.arb_shader_objects = true; +#else if (Cvar_Get("gl_blacklist_debug_glsl", "0", CVAR_RENDERERLATCH, "gl blacklists")->ival && !gl_config.nofixedfunc) { Con_Printf(CON_NOTICE "GLSL disabled\n"); @@ -788,10 +789,6 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) qglLinkProgramARB = (void *)getglext("glLinkProgram"); qglBindAttribLocationARB = (void *)getglext("glBindAttribLocation"); qglGetAttribLocationARB = (void *)getglext("glGetAttribLocation"); - qglVertexAttribPointer = (void *)getglext("glVertexAttribPointer"); - qglGetVertexAttribiv = (void *)getglext("glGetVertexAttribiv"); - qglEnableVertexAttribArray = (void *)getglext("glEnableVertexAttribArray"); - qglDisableVertexAttribArray = (void *)getglext("glDisableVertexAttribArray"); qglGetUniformLocationARB = (void *)getglext("glGetUniformLocation"); qglUniformMatrix4fvARB = (void *)getglext("glUniformMatrix4fv"); qglUniformMatrix3x4fv = (void *)getglext("glUniformMatrix3x4fv"); @@ -803,6 +800,10 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) qglUniform2fvARB = (void *)getglext("glUniform2fv"); qglUniform1iARB = (void *)getglext("glUniform1i"); qglUniform1fARB = (void *)getglext("glUniform1f"); + qglVertexAttribPointer = (void *)getglext("glVertexAttribPointer"); + qglGetVertexAttribiv = (void *)getglext("glGetVertexAttribiv"); + qglEnableVertexAttribArray = (void *)getglext("glEnableVertexAttribArray"); + qglDisableVertexAttribArray = (void *)getglext("glDisableVertexAttribArray"); Con_DPrintf("GLSL available\n"); } else if (GL_CheckExtension("GL_ARB_fragment_shader") @@ -1181,10 +1182,15 @@ GLhandleARB GLSlang_CreateShader (char *name, int ver, char **precompilerconstan /*required version not supported, don't even try*/ if (ver > gl_config.maxglslversion) return 0; - - prstrings[strings] = va("#version %u\n", ver); - length[strings] = strlen(prstrings[strings]); - strings++; +#ifdef FTE_TARGET_WEB + //emscripten prefixes our shader with a precision specifier, and then the browser bitches as the (otherwise valid) #version, so don't say anything at all if its ver 100, and the browser won't complain + if (ver != 100) +#endif + { + prstrings[strings] = va("#version %u\n", ver); + length[strings] = strlen(prstrings[strings]); + strings++; + } } while(*precompilerconstants) @@ -1484,6 +1490,7 @@ void GL_Init(void *(*getglfunction) (char *name)) qglScissor = (void *)getglcore("glScissor"); qglPolygonOffset = (void *)getglext("glPolygonOffset"); #endif +#ifndef FTE_TARGET_WEB qglAlphaFunc = (void *)getglcore("glAlphaFunc"); qglBegin = (void *)getglcore("glBegin"); qglClearDepth = (void *)getglcore("glClearDepth"); @@ -1527,7 +1534,7 @@ void GL_Init(void *(*getglfunction) (char *name)) qglVertex2f = (void *)getglcore("glVertex2f"); qglVertex3f = (void *)getglcore("glVertex3f"); qglVertex3fv = (void *)getglcore("glVertex3fv"); - +#endif //various vertex array stuff. qglArrayElement = (void *)getglcore("glArrayElement"); diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 712254f49..22adf68c6 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -114,6 +114,10 @@ extern r_config_t r_config; #else #include + #ifdef GL_STATIC + #define GL_GLEXT_PROTOTYPES + #include + #endif #endif //#include #include "glsupp.h" @@ -585,6 +589,32 @@ void R_NetGraph (void); #define qglFramebufferTexture2DEXT qglFramebufferTexture2D #define qglDeleteRenderbuffersEXT qglDeleteRenderbuffers //#define qglCompressedTexImage2DARB qglCompressedTexImage2D + +#define qglCreateProgramObjectARB glCreateProgram +#define qglDeleteProgramObject_ glDeleteProgram +#define qglDeleteShaderObject_ glDeleteShader +#define qglUseProgramObjectARB glUseProgram +#define qglCreateShaderObjectARB glCreateShader +#define qglShaderSourceARB glShaderSource +#define qglCompileShaderARB glCompileShader +#define qglGetProgramParameteriv_ glGetProgramiv +#define qglGetShaderParameteriv_ glGetShaderiv +#define qglAttachObjectARB glAttachShader +#define qglGetProgramInfoLog_ glGetProgramInfoLog +#define qglGetShaderInfoLog_ glGetShaderInfoLog +#define qglLinkProgramARB glLinkProgram +#define qglBindAttribLocationARB glBindAttribLocation +#define qglGetAttribLocationARB glGetAttribLocation +#define qglGetUniformLocationARB glGetUniformLocation +#define qglUniformMatrix4fvARB glUniformMatrix4fv +#define qglUniform4fARB glUniform4f +#define qglUniform4fvARB glUniform4fv +#define qglUniform3fARB glUniform3f +#define qglUniform3fvARB glUniform3fv +#define qglUniform2fvARB glUniform2fv +#define qglUniform1iARB glUniform1i +#define qglUniform1fARB glUniform1f + #else extern void (APIENTRY *qglBindTexture) (GLenum target, GLuint texture); extern void (APIENTRY *qglBlendFunc) (GLenum sfactor, GLenum dfactor); @@ -645,6 +675,32 @@ extern void (APIENTRY *qglFramebufferTexture2DEXT)(GLenum target, GLenum attachm extern void (APIENTRY *qglFramebufferRenderbufferEXT)(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint textureId); extern GLenum (APIENTRY *qglCheckFramebufferStatusEXT)(GLenum target); + +//glslang - arb_shader_objects +extern FTEPFNGLCREATEPROGRAMOBJECTARBPROC qglCreateProgramObjectARB; +extern FTEPFNGLDELETEOBJECTARBPROC qglDeleteProgramObject_; +extern FTEPFNGLDELETEOBJECTARBPROC qglDeleteShaderObject_; +extern FTEPFNGLUSEPROGRAMOBJECTARBPROC qglUseProgramObjectARB; +extern FTEPFNGLCREATESHADEROBJECTARBPROC qglCreateShaderObjectARB; +extern FTEPFNGLSHADERSOURCEARBPROC qglShaderSourceARB; +extern FTEPFNGLCOMPILESHADERARBPROC qglCompileShaderARB; +extern FTEPFNGLGETOBJECTPARAMETERIVARBPROC qglGetProgramParameteriv_; +extern FTEPFNGLGETOBJECTPARAMETERIVARBPROC qglGetShaderParameteriv_; +extern FTEPFNGLATTACHOBJECTARBPROC qglAttachObjectARB; +extern FTEPFNGLGETINFOLOGARBPROC qglGetProgramInfoLog_; +extern FTEPFNGLGETINFOLOGARBPROC qglGetShaderInfoLog_; +extern FTEPFNGLLINKPROGRAMARBPROC qglLinkProgramARB; +extern FTEPFNGLBINDATTRIBLOCATIONARBPROC qglBindAttribLocationARB; +extern FTEPFNGLGETATTRIBLOCATIONARBPROC qglGetAttribLocationARB; +extern FTEPFNGLGETUNIFORMLOCATIONARBPROC qglGetUniformLocationARB; +extern FTEPFNGLUNIFORMMATRIXPROC qglUniformMatrix4fvARB; +extern FTEPFNGLUNIFORM4FARBPROC qglUniform4fARB; +extern FTEPFNGLUNIFORM4FVARBPROC qglUniform4fvARB; +extern FTEPFNGLUNIFORM3FARBPROC qglUniform3fARB; +extern FTEPFNGLUNIFORM3FVARBPROC qglUniform3fvARB; +extern FTEPFNGLUNIFORM2FVARBPROC qglUniform2fvARB; +extern FTEPFNGLUNIFORM1IARBPROC qglUniform1iARB; +extern FTEPFNGLUNIFORM1FARBPROC qglUniform1fARB; extern FTEPFNGLVERTEXATTRIBPOINTER qglVertexAttribPointer; extern FTEPFNGLGETVERTEXATTRIBIV qglGetVertexAttribiv; extern FTEPFNGLENABLEVERTEXATTRIBARRAY qglEnableVertexAttribArray; @@ -917,6 +973,9 @@ extern void (APIENTRY *qglTexSubImage1D) (GLenum target, GLint level, GLint xoff extern void (APIENTRY *qglTranslated) (GLdouble x, GLdouble y, GLdouble z); extern void (APIENTRY *qglTranslatef) (GLfloat x, GLfloat y, GLfloat z); +extern FTEPFNGLUNIFORMMATRIXPROC qglUniformMatrix4x3fv; +extern FTEPFNGLUNIFORMMATRIXPROC qglUniformMatrix3x4fv; + #ifdef _WIN32 extern BOOL (WINAPI *qwglCopyContext)(HGLRC, HGLRC, UINT); extern HGLRC (WINAPI *qwglCreateContext)(HDC); @@ -939,34 +998,6 @@ extern PFNGLBINDPROGRAMARBPROC qglBindProgramARB; extern PFNGLGENPROGRAMSARBPROC qglGenProgramsARB; */ -//glslang - arb_shader_objects -extern FTEPFNGLCREATEPROGRAMOBJECTARBPROC qglCreateProgramObjectARB; -extern FTEPFNGLDELETEOBJECTARBPROC qglDeleteProgramObject_; -extern FTEPFNGLDELETEOBJECTARBPROC qglDeleteShaderObject_; -extern FTEPFNGLUSEPROGRAMOBJECTARBPROC qglUseProgramObjectARB; -extern FTEPFNGLCREATESHADEROBJECTARBPROC qglCreateShaderObjectARB; -extern FTEPFNGLSHADERSOURCEARBPROC qglShaderSourceARB; -extern FTEPFNGLCOMPILESHADERARBPROC qglCompileShaderARB; -extern FTEPFNGLGETOBJECTPARAMETERIVARBPROC qglGetProgramParameteriv_; -extern FTEPFNGLGETOBJECTPARAMETERIVARBPROC qglGetShaderParameteriv_; -extern FTEPFNGLATTACHOBJECTARBPROC qglAttachObjectARB; -extern FTEPFNGLGETINFOLOGARBPROC qglGetProgramInfoLog_; -extern FTEPFNGLGETINFOLOGARBPROC qglGetShaderInfoLog_; -extern FTEPFNGLLINKPROGRAMARBPROC qglLinkProgramARB; -extern FTEPFNGLBINDATTRIBLOCATIONARBPROC qglBindAttribLocationARB; -extern FTEPFNGLGETATTRIBLOCATIONARBPROC qglGetAttribLocationARB; -extern FTEPFNGLGETUNIFORMLOCATIONARBPROC qglGetUniformLocationARB; -extern FTEPFNGLUNIFORMMATRIXPROC qglUniformMatrix4fvARB; -extern FTEPFNGLUNIFORMMATRIXPROC qglUniformMatrix4x3fv; -extern FTEPFNGLUNIFORMMATRIXPROC qglUniformMatrix3x4fv; -extern FTEPFNGLUNIFORM4FARBPROC qglUniform4fARB; -extern FTEPFNGLUNIFORM4FVARBPROC qglUniform4fvARB; -extern FTEPFNGLUNIFORM3FARBPROC qglUniform3fARB; -extern FTEPFNGLUNIFORM3FVARBPROC qglUniform3fvARB; -extern FTEPFNGLUNIFORM2FVARBPROC qglUniform2fvARB; -extern FTEPFNGLUNIFORM1IARBPROC qglUniform1iARB; -extern FTEPFNGLUNIFORM1FARBPROC qglUniform1fARB; - extern FTEPFNGLLOCKARRAYSEXTPROC qglLockArraysEXT; extern FTEPFNGLUNLOCKARRAYSEXTPROC qglUnlockArraysEXT; diff --git a/engine/http/httpclient.c b/engine/http/httpclient.c index fda100e00..908efdb27 100644 --- a/engine/http/httpclient.c +++ b/engine/http/httpclient.c @@ -5,7 +5,149 @@ #include "netinc.h" #if defined(WEBCLIENT) -#if defined(NACL) + +#if defined(FTE_TARGET_WEB) +#include + +typedef struct +{ + vfsfile_t funcs; + unsigned long offset; + unsigned long length; + char data[]; +} mfile_t; +static int VFSMEM_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) +{ + mfile_t *f = (mfile_t*)file; + if (f->offset >= f->length) + return -1; //eof! + if (bytestoread > f->length - f->offset) + bytestoread = f->length - f->offset; //eof! + memcpy(buffer, &f->data[f->offset], bytestoread); + f->offset += bytestoread; + return bytestoread; +} +static int VFSMEM_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestoread) +{ + return 0; +} +static qboolean VFSMEM_Seek (struct vfsfile_s *file, unsigned long pos) +{ + mfile_t *f = (mfile_t*)file; + f->offset = pos; + return true; +} +static unsigned long VFSMEM_Tell (struct vfsfile_s *file) +{ + mfile_t *f = (mfile_t*)file; + return f->offset; +} +static unsigned long VFSMEM_GetSize (struct vfsfile_s *file) +{ + mfile_t *f = (mfile_t*)file; + return f->length; +} +static void VFSMEM_Close(vfsfile_t *file) +{ + free(file); +} +static void VFSMEM_Flush(struct vfsfile_s *file) +{ +} +static vfsfile_t *VFSMEM_File(void *data, unsigned int datasize) +{ + /*create a file which is already unlinked*/ + mfile_t *f; + f = malloc(sizeof(*f) + datasize); + if (!f) + return NULL; + f->funcs.ReadBytes = VFSMEM_ReadBytes; + f->funcs.WriteBytes = VFSMEM_WriteBytes; + f->funcs.Seek = VFSMEM_Seek; + f->funcs.Tell = VFSMEM_Tell; + f->funcs.GetLen = VFSMEM_GetSize; + f->funcs.Close = VFSMEM_Close; + f->funcs.Flush = VFSMEM_Flush; + f->offset = 0; + f->length = datasize; + memcpy(f->data, data, datasize); + + return &f->funcs; +} + +static void DL_Abort(struct dl_download *dl) +{ + dl->ctx = NULL; +} +static void DL_OnLoad(void *c, void *data, int datasize) +{ + struct dl_download *dl = c; + Con_Printf("download %p: success\n", dl); + + //make sure the file is 'open'. + if (!dl->file) + { + if (*dl->localname) + { + Con_Printf("create file\n"); + FS_CreatePath(dl->localname, FS_GAME); + dl->file = FS_OpenVFS(dl->localname, "w+b", FS_GAME); + } + else + { + //emscripten does not close the file. plus we seem to end up with infinite loops. + Con_Printf("temp file\n"); + dl->file = VFSMEM_File(data, datasize); + } + } + + if (dl->file) + { + Con_Printf("writing to file\n"); + VFS_WRITE(dl->file, data, datasize); + } + + dl->replycode = 200; + dl->completed += datasize; + dl->status = DL_FINISHED; +} +static void DL_OnError(void *c) +{ + struct dl_download *dl = c; + Con_Printf("download %p: error\n", dl); + + dl->replycode = 404; //we don't actually know. should we not do this? + dl->status = DL_FAILED; +} + +//this becomes a poll function. the main thread will call this once a frame or so. +qboolean HTTPDL_Decide(struct dl_download *dl) +{ + const char *url = dl->redir; + if (!*url) + url = dl->url; + + if (dl->ctx) + { + if (dl->status == DL_FAILED || dl->status == DL_FINISHED) + { + DL_Abort(dl); + return false; //safe to destroy it now + } + } + else + { + dl->status = DL_ACTIVE; + dl->abort = DL_Abort; + dl->ctx = dl; + + Con_Printf("Sending %p request for %s\n", dl, url); + emscripten_async_wget_data(url, dl, DL_OnLoad, DL_OnError); + } + + return true; +} +#elif defined(NACL) #include #include #include diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 0fa9976d3..ba8da869a 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -1684,9 +1684,6 @@ void Q_InitProgs(void) // svprogfuncs->ToggleBreak(svprogfuncs, "", 0, 2); // svprogfuncs->SetWatchPoint(svprogfuncs, ""); - sv.world.max_edicts = pr_maxedicts.value; - if (sv.world.max_edicts > MAX_EDICTS) - sv.world.max_edicts = MAX_EDICTS; sv.world.edict_size = PR_InitEnts(svprogfuncs, sv.world.max_edicts); if (progstype == PROG_QW) diff --git a/engine/server/server.h b/engine/server/server.h index 5a276b846..c0d32e708 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -269,7 +269,7 @@ typedef struct svcustomtents_t customtents[255]; - int csqcentversion[MAX_EDICTS];//prevents ent versions from going backwards + int *csqcentversion;//prevents ent versions from going backwards } server_t; typedef enum diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index b776b234b..61d2d6dcc 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -537,6 +537,11 @@ void SV_UnspawnServer (void) //terminate the running server. sv.world.worldmodel = NULL; sv.state = ss_dead; *sv.name = '\0'; + if (sv.csqcentversion) + { + BZ_Free(sv.csqcentversion); + sv.csqcentversion = NULL; + } } for (i = 0; i < MAX_CLIENTS; i++) { @@ -565,6 +570,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us { func_t f; char *file; + extern cvar_t pr_maxedicts; gametype_e newgametype; @@ -678,6 +684,9 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us PR_Deinit(); + if (sv.csqcentversion) + BZ_Free(sv.csqcentversion); + // wipe the entire per-level structure memset (&sv, 0, sizeof(sv)); @@ -888,6 +897,15 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us sv.state = ss_loading; + sv.world.max_edicts = pr_maxedicts.value; + if (sv.world.max_edicts > MAX_EDICTS) + sv.world.max_edicts = MAX_EDICTS; +#ifdef PEXT_CSQC + sv.csqcentversion = BZ_Malloc(sizeof(*sv.csqcentversion) * sv.world.max_edicts); + for (i=0 ; i