From 5f7243c6dc85222e687551bfc8e111bd7ec6ecd8 Mon Sep 17 00:00:00 2001 From: Spoike Date: Tue, 11 Aug 2015 09:14:33 +0000 Subject: [PATCH] capture[demo] now works in d3d renderers. capturedemo now supports rendering to an fbo. this provides support for crazy video resolutions. 16k*16k videos are going to be quite large... only works in gl. hurrah... console selection/copy indicators are back! fix issue with q2 server browser. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4961 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_input.c | 5 +- engine/client/cl_main.c | 6 +- engine/client/cl_screen.c | 1 - engine/client/console.c | 1 + engine/client/m_master.c | 2 + engine/client/m_mp3.c | 163 +++++++++++++++++++++++++++---------- engine/client/merged.h | 3 +- engine/client/net_master.c | 2 + engine/client/pr_csqc.c | 1 - engine/client/r_2d.c | 17 +++- engine/client/r_surf.c | 1 - engine/client/vid.h | 1 + engine/client/view.c | 3 +- engine/common/fs.c | 2 + engine/d3d/d3d_shader.c | 47 ++++++----- engine/d3d/vid_d3d.c | 30 +++++-- engine/d3d/vid_d3d11.c | 30 +++++-- engine/gl/gl_draw.c | 9 +- engine/gl/gl_rmain.c | 37 ++++++--- engine/gl/gl_screen.c | 11 +-- engine/server/sv_send.c | 2 +- 21 files changed, 259 insertions(+), 115 deletions(-) diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index c2bed3897..fd9a75f22 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -1758,9 +1758,12 @@ void CL_SendCmd (double frametime, qboolean mainloop) wantfps = cl_netfps.value; fullsend = true; +#ifndef CLIENTONLY if (sv.state && cls.state != ca_active) fullsend = -1; - else if (!runningindepphys) + else +#endif + if (!runningindepphys) { // while we're not playing send a slow keepalive fullsend to stop mvdsv from screwing up if (cls.state < ca_active && !cls.download) diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 4fbc432c5..f65b6f976 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -21,7 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "winquake.h" -#include "gl_draw.h" #include #include "netinc.h" #include "cl_master.h" @@ -4804,9 +4803,12 @@ double Host_Frame (double time) */ Mod_Think(); //think even on idle (which means small walls and a fast cpu can get more surfaces done. +#ifndef CLIENTONLY if (sv.state && cls.state != ca_active) maxfps = 0; - else if ((cl_netfps.value>0 || cls.demoplayback || cl_threadedphysics.ival)) + else +#endif + if ((cl_netfps.value>0 || cls.demoplayback || cl_threadedphysics.ival)) { //limit the fps freely, and expect the netfps to cope. maxfpsignoreserver = true; maxfps = cl_maxfps.ival; diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index bfd6763d3..8c8f99226 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -21,7 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // cl_screen.c -- master for refresh, status bar, console, chat, notify, etc #include "quakedef.h" -#include "gl_draw.h" #ifdef GLQUAKE #include "glquake.h"//would prefer not to have this #endif diff --git a/engine/client/console.c b/engine/client/console.c index 76b8793df..a897fcfea 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -1966,6 +1966,7 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in R2D_FillBlock((send*vid.width)/(float)vid.rotpixelwidth, (y*vid.height)/(float)vid.rotpixelheight, ((sstart - send)*vid.width)/(float)vid.rotpixelwidth, (Font_CharHeight()*vid.height)/(float)vid.rotpixelheight); else R2D_FillBlock((sstart*vid.width)/(float)vid.rotpixelwidth, (y*vid.height)/(float)vid.rotpixelheight, ((send - sstart)*vid.width)/(float)vid.rotpixelwidth, (Font_CharHeight()*vid.height)/(float)vid.rotpixelheight); + R2D_Flush(); } } } diff --git a/engine/client/m_master.c b/engine/client/m_master.c index e819e6fdd..995b82a2f 100644 --- a/engine/client/m_master.c +++ b/engine/client/m_master.c @@ -848,6 +848,8 @@ static void SL_SliderDraw (int x, int y, menucustom_t *ths, menu_t *menu) mpic_t *pic; + R2D_ImageColours(1,1,1,1); + pic = R2D_SafeCachePic("scrollbars/slidebg.tga"); if (pic && R_GetShaderSizes(pic, NULL, NULL, false)>0) { diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index 7855a41d0..4c368eccb 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -7,7 +7,6 @@ #include "glquake.h"//fixme #endif #include "shader.h" -#include "gl_draw.h" #if !defined(NOMEDIA) #if defined(_WIN32) && !defined(WINRT) && !defined(NOMEDIAMENU) @@ -2664,25 +2663,21 @@ void Media_PlayFilm_f (void) soundcardinfo_t *capture_fakesounddevice; -/* -int recordavi_video_frame_counter; -int recordavi_audio_frame_counter; -float recordavi_frametime; //length of a frame in fractional seconds -float recordavi_videotime; -float recordavi_audiotime; -*/ -//int capturesize; -//int capturewidth; -//char *capturevideomem; -//short *captureaudiomem; -//int captureaudiosamples; + double captureframeinterval; //interval between video frames double capturelastvideotime; //time of last video frame int captureframe; +fbostate_t capturefbo; +int captureoldfbo; +qboolean capturingfbo; +texid_t capturetexture; qboolean captureframeforce; qboolean capturepaused; +extern cvar_t vid_conautoscale; cvar_t capturerate = CVAR("capturerate", "30"); +cvar_t capturewidth = CVARD("capturedemowidth", "0", "When using capturedemo, this specifies the width of the FBO image used."); +cvar_t captureheight = CVARD("capturedemoheight", "0", "When using capturedemo, this specifies the width of the FBO image used."); #if 0//defined(WINAVI) cvar_t capturedriver = CVARD("capturedriver", "avi", "The driver to use to capture the demo. avformat can be supported via a plugin.\navi: capture directly to avi (capturecodec should be a fourcc value).\nraw: capture to a series of screenshots."); cvar_t capturecodec = CVAR("capturecodec", "divx"); @@ -2690,7 +2685,7 @@ cvar_t capturecodec = CVAR("capturecodec", "divx"); cvar_t capturedriver = CVARD("capturedriver", "raw", "The driver to use to capture the demo. avformat can be supported via a plugin.\nraw: capture to a series of screenshots."); cvar_t capturecodec = CVARD("capturecodec", "tga", "the compression/encoding codec to use. With raw capturing, this should be one of tga,png,jpg,pcx (ie: screenshot extensions).\nWith (win)avi, this should be a fourcc code like divx or xvid."); #endif -cvar_t capturesound = CVAR("capturesound", "1"); +cvar_t capturesound = CVARD("capturesound", "1", "Enables the capturing of game voice. If not using capturedemo, this can be combined with cl_voip_test to capture your own voice."); cvar_t capturesoundchannels = CVAR("capturesoundchannels", "1"); cvar_t capturesoundbits = CVAR("capturesoundbits", "8"); cvar_t capturemessage = CVAR("capturemessage", ""); @@ -2864,12 +2859,12 @@ static void *QDECL capture_avi_begin (char *streamname, int videorate, int width memset(&bitmap_info_header, 0, sizeof(BITMAPINFOHEADER)); bitmap_info_header.biSize = 40; - bitmap_info_header.biWidth = vid.pixelwidth; - bitmap_info_header.biHeight = vid.pixelheight; + bitmap_info_header.biWidth = width; + bitmap_info_header.biHeight = height; bitmap_info_header.biPlanes = 1; bitmap_info_header.biBitCount = 24; bitmap_info_header.biCompression = BI_RGB; - bitmap_info_header.biSizeImage = vid.pixelwidth*vid.pixelheight * 3; + bitmap_info_header.biSizeImage = width*height * 3; memset(&stream_header, 0, sizeof(stream_header)); @@ -2877,7 +2872,7 @@ static void *QDECL capture_avi_begin (char *streamname, int videorate, int width stream_header.fccHandler = ctx->codec_fourcc; stream_header.dwScale = 100; stream_header.dwRate = (unsigned long)(0.5 + 100.0/captureframeinterval); - SetRect(&stream_header.rcFrame, 0, 0, vid.pixelwidth, vid.pixelheight); + SetRect(&stream_header.rcFrame, 0, 0, width, height); hr = qAVIFileCreateStreamA(ctx->file, &ctx->uncompressed_video_stream, &stream_header); if (FAILED(hr)) @@ -2990,6 +2985,30 @@ static media_encoder_funcs_t capture_avi = }; #endif +#ifdef _DEBUG +static void QDECL capture_null_end(void *vctx) +{ +} +static void *QDECL capture_null_begin (char *streamname, int videorate, int width, int height, int *sndkhz, int *sndchannels, int *sndbits) +{ + return (void*)~0; +} +static void QDECL capture_null_video(void *vctx, void *vdata, int frame, int width, int height) +{ +} +static void QDECL capture_null_audio(void *vctx, void *data, int bytes) +{ +} +static media_encoder_funcs_t capture_null = +{ + "null", + capture_null_begin, + capture_null_video, + capture_null_audio, + capture_null_end +}; +#endif + static media_encoder_funcs_t *pluginencodersfunc[8]; static struct plugin_s *pluginencodersplugin[8]; qboolean Media_RegisterEncoder(struct plugin_s *plug, media_encoder_funcs_t *funcs) @@ -3015,9 +3034,10 @@ qboolean Media_UnregisterEncoder(struct plugin_s *plug, media_encoder_funcs_t *f for (i = 0; i < sizeof(pluginencodersfunc)/sizeof(pluginencodersfunc[0]); i++) { + if (pluginencodersplugin[i]) if (pluginencodersfunc[i] == funcs || (!funcs && pluginencodersplugin[i] == plug)) { - if (currentcapture_funcs == funcs) + if (currentcapture_funcs == pluginencodersfunc[i]) Media_StopRecordFilm_f(); success = true; pluginencodersfunc[i] = NULL; @@ -3163,7 +3183,38 @@ skipframe: if (y < scr_con_current) y = scr_con_current; if (y > vid.height-8) y = vid.height-8; - Draw_FunString((strlen(capturemessage.string)+1)*8, y, S_COLOR_RED"RECORDING"); + +#ifdef GLQUAKE + if (capturingfbo) + { + shader_t *pic; + GLBE_FBO_Pop(captureoldfbo); + vid.framebuffer = NULL; + GL_Set2D(false); + + pic = R_RegisterShader("capturdemofeedback", SUF_NONE, + "{\n" + "program default2d\n" + "{\n" + "map $diffuse\n" + "}\n" + "}\n"); + pic->defaulttextures->base = capturetexture; + //pulse green slightly, so its a bit more obvious + R2D_ImageColours(1, 1+0.2*sin(realtime), 1, 1); + R2D_Image(0, 0, vid.width, vid.height, 0, 1, 1, 0, pic); + R2D_ImageColours(1, 1, 1, 1); + Draw_FunString(0, 0, S_COLOR_RED"RECORDING"); + if (R2D_Flush) + R2D_Flush(); + + captureoldfbo = GLBE_FBO_Push(&capturefbo); + vid.framebuffer = capturetexture; + GL_Set2D(false); + } + else +#endif + Draw_FunString((strlen(capturemessage.string)+1)*8, y, S_COLOR_RED"RECORDING"); } } @@ -3320,22 +3371,21 @@ void Media_StopRecordFilm_f (void) currentcapture_funcs->capture_end(currentcapture_ctx); currentcapture_ctx = NULL; currentcapture_funcs = NULL; + +#ifdef GLQUAKE + if (capturingfbo) + GLBE_FBO_Pop(captureoldfbo); +#endif + vid.framebuffer = NULL; + capturingfbo = false; + + Cvar_ForceCallback(&vid_conautoscale); } -void Media_RecordFilm_f (void) +static void Media_RecordFilm (char *recordingname, qboolean demo) { int sndkhz, sndchannels, sndbits; int i; - if (Cmd_Argc() != 2) - { - Con_Printf("capture \nRecords video output in an avi file.\nUse capturerate and capturecodec to configure.\n"); - return; - } - - if (Cmd_IsInsecure()) //err... don't think so sonny. - return; - - Media_StopRecordFilm_f(); if (capturerate.value<=0) @@ -3382,18 +3432,47 @@ void Media_RecordFilm_f (void) sndchannels = 0; sndbits = 0; } + +#ifdef GLQUAKE + if (demo && capturewidth.ival && captureheight.ival && qrenderer == QR_OPENGL && gl_config.ext_framebuffer_objects) + { + capturingfbo = true; + capturetexture = R2D_RT_Configure("$democapture", capturewidth.ival, captureheight.ival, TF_BGRA32); + captureoldfbo = GLBE_FBO_Update(&capturefbo, FBO_RB_DEPTH, &capturetexture, 1, r_nulltex, capturewidth.ival, captureheight.ival, 0); + vid.fbpwidth = capturewidth.ival; + vid.fbpheight = captureheight.ival; + vid.framebuffer = capturetexture; + } +#endif + + recordingdemo = demo; if (!currentcapture_funcs->capture_begin) currentcapture_ctx = NULL; else - currentcapture_ctx = currentcapture_funcs->capture_begin(Cmd_Argv(1), capturerate.value, vid.pixelwidth, vid.pixelheight, &sndkhz, &sndchannels, &sndbits); + currentcapture_ctx = currentcapture_funcs->capture_begin(recordingname, capturerate.value, vid.fbpwidth, vid.fbpheight, &sndkhz, &sndchannels, &sndbits); if (!currentcapture_ctx) { + recordingdemo = false; currentcapture_funcs = NULL; Con_Printf("Unable to initialise capture driver\n"); } else if (sndkhz) Media_InitFakeSoundDevice(sndkhz, sndchannels, sndbits); + + Cvar_ForceCallback(&vid_conautoscale); +} +static void Media_RecordFilm_f (void) +{ + if (Cmd_Argc() != 2) + { + Con_Printf("capture \nRecords video output in an avi file.\nUse capturerate and capturecodec to configure.\n"); + return; + } + if (Cmd_IsInsecure()) //err... don't think so sonny. + return; + + Media_RecordFilm(Cmd_Argv(1), false); } void Media_CaptureDemoEnd(void) { @@ -3414,22 +3493,20 @@ void Media_RecordDemo_f(void) return; } + CL_Stopdemo_f(); //capturing failed for some reason + CL_PlayDemo(Cmd_Argv(1), false); if (!cls.demoplayback) { Con_Printf("unable to play demo, not capturing\n"); return; } - //FIXME: mamke sure it loaded okay - if (Cmd_Argc() > 2) - Cmd_ShiftArgs(1, false); - Media_RecordFilm_f(); + //FIXME: make sure it loaded okay + Media_RecordFilm(Cmd_Argv(Cmd_Argc()>2?2:1), true); scr_con_current=0; Key_Dest_Remove(kdm_console|kdm_emenu|kdm_gmenu); - if (currentcapture_funcs) - recordingdemo = true; - else + if (!currentcapture_funcs) CL_Stopdemo_f(); //capturing failed for some reason } @@ -4137,6 +4214,9 @@ void Media_Init(void) Media_RegisterEncoder(NULL, &capture_avi); #endif Media_RegisterEncoder(NULL, &capture_raw); +#ifdef _DEBUG + Media_RegisterEncoder(NULL, &capture_null); +#endif Cmd_AddCommand("playvideo", Media_PlayFilm_f); Cmd_AddCommand("playfilm", Media_PlayFilm_f); @@ -4164,7 +4244,6 @@ void Media_Init(void) media_playlisttypes = MEDIA_PLAYLIST | MEDIA_GAMEMUSIC | MEDIA_CVARLIST; -#if defined(GLQUAKE) Cmd_AddCommand("capture", Media_RecordFilm_f); Cmd_AddCommand("capturedemo", Media_RecordDemo_f); Cmd_AddCommand("capturestop", Media_StopRecordFilm_f); @@ -4173,6 +4252,8 @@ void Media_Init(void) Cvar_Register(&capturemessage, "AVI capture controls"); Cvar_Register(&capturesound, "AVI capture controls"); Cvar_Register(&capturerate, "AVI capture controls"); + Cvar_Register(&capturewidth, "AVI capture controls"); + Cvar_Register(&captureheight, "AVI capture controls"); Cvar_Register(&capturedriver, "AVI capture controls"); Cvar_Register(&capturecodec, "AVI capture controls"); @@ -4183,8 +4264,6 @@ void Media_Init(void) S_RegisterSoundInputPlugin(S_LoadMP3Sound); #endif -#endif - #ifdef WINAMP Cvar_Register(&media_hijackwinamp, "Media player things"); #endif diff --git a/engine/client/merged.h b/engine/client/merged.h index a52f2b2d7..23bb35428 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -91,6 +91,7 @@ void R2D_ImageColours(float r, float g, float b, float a); void R2D_ImagePaletteColour(unsigned int i, float a); void R2D_FillBlock(float x, float y, float w, float h); void R2D_Line(float x1, float y1, float x2, float y2, mpic_t *pic); +extern void (*R2D_Flush)(void); extern void (*Draw_Init) (void); @@ -226,7 +227,7 @@ typedef struct image_s char *ident; //allocated on end char *subpath; //allocated on end int regsequence; - int width; + int width; //this is the logical size. the physical size is not considered important (except for render targets, which should not be loaded from disk). int height; int status; //TEX_ unsigned int flags; diff --git a/engine/client/net_master.c b/engine/client/net_master.c index a143a2987..c3c50821e 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -2936,6 +2936,8 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor *nl = '\0'; details.players[clnum].isspec = false; + details.players[clnum].team[0] = 0; + details.players[clnum].skin[0] = 0; token = msg; if (!token) diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index b1f382f31..7d341b39d 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -19,7 +19,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "quakedef.h" -#include "gl_draw.h" /* diff --git a/engine/client/r_2d.c b/engine/client/r_2d.c index ee751d410..6d2f03949 100644 --- a/engine/client/r_2d.c +++ b/engine/client/r_2d.c @@ -1045,18 +1045,27 @@ void R2D_Console_Resize(void) float ang, rad; extern cvar_t gl_screenangle; + int fbwidth = vid.pixelwidth; + int fbheight = vid.pixelheight; + + if (vid.framebuffer) + { + fbwidth = vid.framebuffer->width; + fbheight = vid.framebuffer->height; + } + ang = (gl_screenangle.value>0?(gl_screenangle.value+45):(gl_screenangle.value-45))/90; ang = (int)ang * 90; if (ang) { rad = (ang * M_PI) / 180; - vid.rotpixelwidth = fabs(cos(rad)) * (vid.pixelwidth) + fabs(sin(rad)) * (vid.pixelheight); - vid.rotpixelheight = fabs(sin(rad)) * (vid.pixelwidth) + fabs(cos(rad)) * (vid.pixelheight); + vid.rotpixelwidth = fabs(cos(rad)) * (fbwidth) + fabs(sin(rad)) * (fbheight); + vid.rotpixelheight = fabs(sin(rad)) * (fbwidth) + fabs(cos(rad)) * (fbheight); } else { - vid.rotpixelwidth = vid.pixelwidth; - vid.rotpixelheight = vid.pixelheight; + vid.rotpixelwidth = fbwidth; + vid.rotpixelheight = fbheight; } cwidth = vid_conwidth.value; diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index a4d06ab45..99c57681e 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -2476,7 +2476,6 @@ void Surf_Clear(model_t *mod) } mod->numtextures = 0; - BZ_Free(mod->shadowbatches); mod->numshadowbatches = 0; mod->shadowbatches = NULL; diff --git a/engine/client/vid.h b/engine/client/vid.h index dd035b472..039d58805 100644 --- a/engine/client/vid.h +++ b/engine/client/vid.h @@ -68,6 +68,7 @@ typedef struct unsigned fbvheight; /*virtual 2d height*/ unsigned fbpwidth; /*virtual 2d width*/ unsigned fbpheight; /*virtual 2d height*/ + struct image_s *framebuffer; /*the framebuffer fbo (set by democapture)*/ unsigned width; /*virtual 2d screen width*/ unsigned height; /*virtual 2d screen height*/ diff --git a/engine/client/view.c b/engine/client/view.c index 02c9756da..5c21991eb 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -23,7 +23,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "winquake.h" #include "glquake.h" -#include "gl_draw.h" #include // for isdigit(); @@ -1125,7 +1124,7 @@ void V_ApplyAFov(playerview_t *pv) //attempt to retain a classic fov if (ws*r_refdef.vrect.width < (r_refdef.vrect.height*640)/432) { - r_refdef.fov_y = CalcFov(afov, (ws*r_refdef.vrect.width*vid.pixelwidth)/vid.width, (r_refdef.vrect.height*vid.pixelheight)/vid.height); + r_refdef.fov_y = CalcFov(afov, (ws*r_refdef.vrect.width*r_refdef.pxrect.width)/vid.width, (r_refdef.vrect.height*r_refdef.pxrect.height)/vid.height); r_refdef.fov_x = afov;//CalcFov(r_refdef.fov_y, 432, 640); } else diff --git a/engine/common/fs.c b/engine/common/fs.c index f4f91d176..65d7e9785 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -2822,9 +2822,11 @@ void FS_PureMode(int puremode, char *purenamelist, char *purecrclist, char *refn { qboolean pureflush; +#ifndef CLIENTONLY //if we're the server, we can't be impure. if (sv.state) return; +#endif if (puremode == fs_puremode && fs_pureseed == pureseed) { diff --git a/engine/d3d/d3d_shader.c b/engine/d3d/d3d_shader.c index b0363a2d0..3210de7e6 100644 --- a/engine/d3d/d3d_shader.c +++ b/engine/d3d/d3d_shader.c @@ -254,13 +254,12 @@ static int D3D9Shader_FindUniform(union programhandle_u *h, int type, const char return -1; } -static void D3D9Shader_ProgAutoFields(program_t *prog, const char *progname, char **cvarnames, int *cvartypes) +static void D3D9Shader_ProgAutoFields(program_t *prog, const char *progname, cvar_t **cvarrefs, char **cvarnames, int *cvartypes) { struct programpermu_s *pp; unsigned int i, p; int uniformloc; char tmpname[128]; - cvar_t *cvar[128]; static const char *defaultsamplers[] = { @@ -293,8 +292,6 @@ static void D3D9Shader_ProgAutoFields(program_t *prog, const char *progname, cha prog->defaulttextures = 0; prog->numsamplers = 0; - memset(cvar, 0, sizeof(cvar)); - for (p = 0; p < PERMUTATIONS; p++) { int maxparms = 0; @@ -322,32 +319,34 @@ static void D3D9Shader_ProgAutoFields(program_t *prog, const char *progname, cha } } - for (i = 0; cvarnames[i] && i < countof(cvar); i++) + for (i = 0; cvarnames[i]; i++) { - if (!cvar[i]) - { - for (p = 0; cvarnames[i][p] && (unsigned char)cvarnames[i][p] > 32 && p < sizeof(tmpname)-1; p++) - tmpname[p] = cvarnames[i][p]; - tmpname[p] = 0; - cvar[i] = Cvar_FindVar(tmpname); - if (!cvar[i]) - continue; - cvar[i]->flags |= CVAR_SHADERSYSTEM; - } - - uniformloc = D3D9Shader_FindUniform(&prog->permu[p].h, 1, va("cvar_%s", tmpname)); + if (!cvarrefs[i]) + continue; + //just directly sets uniforms. can't cope with cvars dynamically changing. + cvarrefs[i]->flags |= CVAR_SHADERSYSTEM; + + uniformloc = D3D9Shader_FindUniform(&prog->permu[p].h, 1, va("cvar_%s", cvarnames[i])); if (uniformloc != -1) { - vec4_t v = {cvar[i]->value, 0, 0, 0}; - IDirect3DDevice9_SetVertexShader(pD3DDev9, prog->permu[p].h.hlsl.vert); - IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, 0, v, 1); + if (cvartypes[i] == SP_CVARI) + { + int v[4] = {cvarrefs[i]->ival, 0, 0, 0}; + IDirect3DDevice9_SetVertexShaderConstantI(pD3DDev9, 0, v, 1); + } + else + IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, 0, cvarrefs[i]->vec4, 1); } - uniformloc = D3D9Shader_FindUniform(&prog->permu[p].h, 2, va("cvar_%s", tmpname)); + uniformloc = D3D9Shader_FindUniform(&prog->permu[p].h, 2, va("cvar_%s", cvarnames[i])); if (uniformloc != -1) { - vec4_t v = {cvar[i]->value, 0, 0, 0}; - IDirect3DDevice9_SetPixelShader(pD3DDev9, prog->permu[p].h.hlsl.frag); - IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, 0, v, 1); + if (cvartypes[i] == SP_CVARI) + { + int v[4] = {cvarrefs[i]->ival, 0, 0, 0}; + IDirect3DDevice9_SetPixelShaderConstantI(pD3DDev9, 0, v, 1); + } + else + IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, 0, cvarrefs[i]->vec4, 1); } } diff --git a/engine/d3d/vid_d3d.c b/engine/d3d/vid_d3d.c index b9895eb50..891536113 100644 --- a/engine/d3d/vid_d3d.c +++ b/engine/d3d/vid_d3d.c @@ -892,6 +892,11 @@ void D3D9_Set2D (void) vid.fbvheight = vid.height; vid.fbpwidth = vid.pixelwidth; vid.fbpheight = vid.pixelheight; + + r_refdef.pxrect.x = 0; + r_refdef.pxrect.y = 0; + r_refdef.pxrect.width = vid.fbpwidth; + r_refdef.pxrect.height = vid.fbpheight; } static int d3d9error(int i) @@ -1002,9 +1007,7 @@ static void (D3D9_SCR_UpdateScreen) (void) { Editor_Draw(); V_UpdatePalette (false); -#if defined(_WIN32) && defined(GLQUAKE) Media_RecordFrame(); -#endif R2D_BrightenScreen(); if (key_dest == key_console) @@ -1020,9 +1023,7 @@ static void (D3D9_SCR_UpdateScreen) (void) { M_Draw(0); // V_UpdatePalette (false); -#if defined(_WIN32) Media_RecordFrame(); -#endif // R2D_BrightenScreen(); IDirect3DDevice9_EndScene(pD3DDev9); IDirect3DDevice9_Present(pD3DDev9, NULL, NULL, NULL, NULL); @@ -1076,9 +1077,7 @@ static void (D3D9_SCR_UpdateScreen) (void) SCR_DrawTwoDimensional(uimenu, nohud); V_UpdatePalette (false); -#if defined(_WIN32) && defined(GLQUAKE) Media_RecordFrame(); -#endif RSpeedEnd(RSPEED_TOTALREFRESH); RSpeedShow(); @@ -1169,7 +1168,7 @@ static void D3D9_SetupViewPortProjection(void) fov_x = r_refdef.fov_x;//+sin(cl.time)*5; fov_y = r_refdef.fov_y;//-sin(cl.time+1)*5; - if (r_waterwarp.value<0 && r_viewcontents & FTECONTENTS_FLUID) + if ((r_refdef.flags & RDF_UNDERWATER) && !(r_refdef.flags & RDF_WATERWARP)) { fov_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value); fov_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value); @@ -1192,6 +1191,23 @@ static void (D3D9_R_RenderView) (void) { Surf_SetupFrame(); + //check if we can do underwater warp + if (cls.protocol != CP_QUAKE2) //quake2 tells us directly + { + if (r_viewcontents & FTECONTENTS_FLUID) + r_refdef.flags |= RDF_UNDERWATER; + else + r_refdef.flags &= ~RDF_UNDERWATER; + } + if (r_refdef.flags & RDF_UNDERWATER) + { + extern cvar_t r_projection; + if (!r_waterwarp.value || r_projection.ival) + r_refdef.flags &= ~RDF_UNDERWATER; //no warp at all +// else if (r_waterwarp.value > 0 && scenepp_waterwarp) +// r_refdef.flags |= RDF_WATERWARP; //try fullscreen warp instead if we can + } + D3D9_SetupViewPortProjection(); // if (r_clear.ival && !(r_refdef.flags & RDF_NOWORLDMODEL)) diff --git a/engine/d3d/vid_d3d11.c b/engine/d3d/vid_d3d11.c index 87af9e6b7..47123c2c1 100644 --- a/engine/d3d/vid_d3d11.c +++ b/engine/d3d/vid_d3d11.c @@ -1184,6 +1184,11 @@ void D3D11_Set2D (void) vid.fbpheight = vid.pixelheight; D3D11BE_Scissor(NULL); + + r_refdef.pxrect.x = 0; + r_refdef.pxrect.y = 0; + r_refdef.pxrect.width = vid.fbpwidth; + r_refdef.pxrect.height = vid.fbpheight; } static void (D3D11_SCR_UpdateScreen) (void) @@ -1257,9 +1262,7 @@ static void (D3D11_SCR_UpdateScreen) (void) { Editor_Draw(); V_UpdatePalette (false); -#if defined(_WIN32) && defined(GLQUAKE) Media_RecordFrame(); -#endif R2D_BrightenScreen(); if (key_dest == key_console) @@ -1275,9 +1278,7 @@ static void (D3D11_SCR_UpdateScreen) (void) { M_Draw(0); // V_UpdatePalette (false); -#if defined(_WIN32) Media_RecordFrame(); -#endif // R2D_BrightenScreen(); // IDirect3DDevice9_EndScene(pD3DDev9); D3D11_PresentOrCrash(); @@ -1339,9 +1340,7 @@ static void (D3D11_SCR_UpdateScreen) (void) V_UpdatePalette (false); -#if defined(_WIN32) && defined(GLQUAKE) Media_RecordFrame(); -#endif RSpeedEnd(RSPEED_TOTALREFRESH); RSpeedShow(); @@ -1419,7 +1418,7 @@ static void D3D11_SetupViewPort(void) fov_x = r_refdef.fov_x;//+sin(cl.time)*5; fov_y = r_refdef.fov_y;//-sin(cl.time+1)*5; - if (r_waterwarp.value<0 && r_viewcontents & FTECONTENTS_FLUID) + if ((r_refdef.flags & RDF_UNDERWATER) && !(r_refdef.flags & RDF_WATERWARP)) { fov_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value); fov_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value); @@ -1447,6 +1446,23 @@ static void (D3D11_R_RenderView) (void) else ID3D11DeviceContext_ClearDepthStencilView(d3ddevctx, fb_backdepthstencil, D3D11_CLEAR_DEPTH, 1, 0); //is it faster to clear the stencil too? + //check if we can do underwater warp + if (cls.protocol != CP_QUAKE2) //quake2 tells us directly + { + if (r_viewcontents & FTECONTENTS_FLUID) + r_refdef.flags |= RDF_UNDERWATER; + else + r_refdef.flags &= ~RDF_UNDERWATER; + } + if (r_refdef.flags & RDF_UNDERWATER) + { + extern cvar_t r_projection; + if (!r_waterwarp.value || r_projection.ival) + r_refdef.flags &= ~RDF_UNDERWATER; //no warp at all +// else if (r_waterwarp.value > 0 && scenepp_waterwarp) +// r_refdef.flags |= RDF_WATERWARP; //try fullscreen warp instead if we can + } + D3D11_SetupViewPort(); //unlike gl, we clear colour beforehand, because that seems more sane. //always clear depth diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index beffa1f9a..48cbd6e4f 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -134,7 +134,14 @@ void GL_Set2D (qboolean flipped) float w = vid.width, h = vid.height; qboolean fbo = !!*r_refdef.rt_destcolour[0].texname; - if (fbo) + if (vid.framebuffer) + { + vid.fbvwidth = vid.width; + vid.fbvheight = vid.height; + vid.fbpwidth = vid.framebuffer->width; + vid.fbpheight = vid.framebuffer->height; + } + else if (fbo) { R2D_RT_GetTexture(r_refdef.rt_destcolour[0].texname, &vid.fbpwidth, &vid.fbpheight); vid.fbvwidth = vid.fbpwidth; diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index ba7ab7de9..c0edf04e7 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -25,7 +25,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "glquake.h" #include "renderque.h" #include "shader.h" -#include "gl_draw.h" void R_RenderBrushPoly (msurface_t *fa); @@ -1697,10 +1696,11 @@ void GLR_RenderView (void) texid_t sourcetex = r_nulltex; shader_t *custompostproc = NULL; float renderscale = r_renderscale.value; //extreme, but whatever + int oldfbo = 0; checkglerror(); - if (r_norefresh.value || !vid.pixelwidth || !vid.pixelheight) + if (r_norefresh.value || !vid.fbpwidth || !vid.fbpwidth) return; //when loading/bugged, its possible that the world is still loading. @@ -1811,13 +1811,21 @@ void GLR_RenderView (void) flags |= FBO_TEX_DEPTH; else flags |= FBO_RB_DEPTH; - GLBE_FBO_Update(&fbo_gameview, flags, col, mrt, depth, vid.fbpwidth, vid.fbpheight, 0); + oldfbo = GLBE_FBO_Update(&fbo_gameview, flags, col, mrt, depth, vid.fbpwidth, vid.fbpheight, 0); } else if ((r_refdef.flags & (RDF_ALLPOSTPROC)) || renderscale != 1) { //the game needs to be drawn to a texture for post processing - vid.fbpwidth = (r_refdef.vrect.width * vid.pixelwidth) / vid.width; - vid.fbpheight = (r_refdef.vrect.height * vid.pixelheight) / vid.height; + if (1)//vid.framebuffer) + { + vid.fbpwidth = (r_refdef.vrect.width * r_refdef.pxrect.width) / vid.width; + vid.fbpheight = (r_refdef.vrect.height * r_refdef.pxrect.width) / vid.height; + } + else + { + vid.fbpwidth = (r_refdef.vrect.width * vid.pixelwidth) / vid.width; + vid.fbpheight = (r_refdef.vrect.height * vid.pixelheight) / vid.height; + } vid.fbpwidth *= renderscale; vid.fbpheight *= renderscale; @@ -1831,9 +1839,16 @@ void GLR_RenderView (void) sourcetex = R2D_RT_Configure("rt/$lastgameview", vid.fbpwidth, vid.fbpheight, /*(r_refdef.flags&RDF_BLOOM)?TF_RGBA16F:*/TF_RGBA32); - GLBE_FBO_Update(&fbo_gameview, FBO_RB_DEPTH, &sourcetex, 1, r_nulltex, vid.fbpwidth, vid.fbpheight, 0); + oldfbo = GLBE_FBO_Update(&fbo_gameview, FBO_RB_DEPTH, &sourcetex, 1, r_nulltex, vid.fbpwidth, vid.fbpheight, 0); dofbo = true; } + else if (vid.framebuffer) + { + vid.fbvwidth = vid.width; + vid.fbvheight = vid.height; + vid.fbpwidth = vid.framebuffer->width; + vid.fbpheight = vid.framebuffer->height; + } else { vid.fbvwidth = vid.width; @@ -1902,12 +1917,10 @@ void GLR_RenderView (void) //update stuff now that we're not rendering the 3d scene if (dofbo) - GLBE_RenderToTextureUpdate2d(true); - else - { - GLBE_RenderToTextureUpdate2d(false); - GL_Set2D (false); - } + GLBE_FBO_Pop(oldfbo); + + GLBE_RenderToTextureUpdate2d(false); + GL_Set2D (false); // SCENE POST PROCESSING diff --git a/engine/gl/gl_screen.c b/engine/gl/gl_screen.c index c730cf3d0..b67a554cf 100644 --- a/engine/gl/gl_screen.c +++ b/engine/gl/gl_screen.c @@ -249,13 +249,8 @@ char *GLVID_GetRGBInfo(int prepadbytes, int *truewidth, int *trueheight) int i, c; qbyte *ret; - *truewidth = vid.pixelwidth; - *trueheight = vid.pixelheight; - - if (*r_refdef.rt_destcolour[0].texname) - { - R2D_RT_GetTexture(r_refdef.rt_destcolour[0].texname, truewidth, trueheight); - } + *truewidth = vid.fbpwidth; + *trueheight = vid.fbpheight; /*if (1) { @@ -275,7 +270,7 @@ char *GLVID_GetRGBInfo(int prepadbytes, int *truewidth, int *trueheight) } BZ_Free(p); } - else*/ if (gl_config.gles || (vid.pixelwidth&3)) + else*/ if (gl_config.gles || (*truewidth&3)) { qbyte *p; diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 225dfee23..9fb4c24e9 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -585,7 +585,7 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int // to = MULTICAST_ALL; //don't let things crash if the world model went away. can happen in broadcasts when reloading video with the map no longer available causing the server to die with the resulting broadcast messages about players dropping or gib effects appearing - if (sv.world.worldmodel->loadstate != MLS_LOADED) + if (sv.world.worldmodel->loadstate != MLS_LOADED || !sv.world.worldmodel->nodes) { switch(to) {