1
0
Fork 0
forked from fte/fteqw

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
This commit is contained in:
Spoike 2015-08-11 09:14:33 +00:00
parent fc691d5be8
commit 5f7243c6dc
21 changed files with 259 additions and 115 deletions

View file

@ -1758,9 +1758,12 @@ void CL_SendCmd (double frametime, qboolean mainloop)
wantfps = cl_netfps.value; wantfps = cl_netfps.value;
fullsend = true; fullsend = true;
#ifndef CLIENTONLY
if (sv.state && cls.state != ca_active) if (sv.state && cls.state != ca_active)
fullsend = -1; 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 // while we're not playing send a slow keepalive fullsend to stop mvdsv from screwing up
if (cls.state < ca_active && !cls.download) if (cls.state < ca_active && !cls.download)

View file

@ -21,7 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h" #include "quakedef.h"
#include "winquake.h" #include "winquake.h"
#include "gl_draw.h"
#include <sys/types.h> #include <sys/types.h>
#include "netinc.h" #include "netinc.h"
#include "cl_master.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. 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) if (sv.state && cls.state != ca_active)
maxfps = 0; 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. { //limit the fps freely, and expect the netfps to cope.
maxfpsignoreserver = true; maxfpsignoreserver = true;
maxfps = cl_maxfps.ival; maxfps = cl_maxfps.ival;

View file

@ -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 // cl_screen.c -- master for refresh, status bar, console, chat, notify, etc
#include "quakedef.h" #include "quakedef.h"
#include "gl_draw.h"
#ifdef GLQUAKE #ifdef GLQUAKE
#include "glquake.h"//would prefer not to have this #include "glquake.h"//would prefer not to have this
#endif #endif

View file

@ -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); 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 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_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();
} }
} }
} }

View file

@ -848,6 +848,8 @@ static void SL_SliderDraw (int x, int y, menucustom_t *ths, menu_t *menu)
mpic_t *pic; mpic_t *pic;
R2D_ImageColours(1,1,1,1);
pic = R2D_SafeCachePic("scrollbars/slidebg.tga"); pic = R2D_SafeCachePic("scrollbars/slidebg.tga");
if (pic && R_GetShaderSizes(pic, NULL, NULL, false)>0) if (pic && R_GetShaderSizes(pic, NULL, NULL, false)>0)
{ {

View file

@ -7,7 +7,6 @@
#include "glquake.h"//fixme #include "glquake.h"//fixme
#endif #endif
#include "shader.h" #include "shader.h"
#include "gl_draw.h"
#if !defined(NOMEDIA) #if !defined(NOMEDIA)
#if defined(_WIN32) && !defined(WINRT) && !defined(NOMEDIAMENU) #if defined(_WIN32) && !defined(WINRT) && !defined(NOMEDIAMENU)
@ -2664,25 +2663,21 @@ void Media_PlayFilm_f (void)
soundcardinfo_t *capture_fakesounddevice; 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 captureframeinterval; //interval between video frames
double capturelastvideotime; //time of last video frame double capturelastvideotime; //time of last video frame
int captureframe; int captureframe;
fbostate_t capturefbo;
int captureoldfbo;
qboolean capturingfbo;
texid_t capturetexture;
qboolean captureframeforce; qboolean captureframeforce;
qboolean capturepaused; qboolean capturepaused;
extern cvar_t vid_conautoscale;
cvar_t capturerate = CVAR("capturerate", "30"); 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) #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 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"); 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 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."); 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 #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 capturesoundchannels = CVAR("capturesoundchannels", "1");
cvar_t capturesoundbits = CVAR("capturesoundbits", "8"); cvar_t capturesoundbits = CVAR("capturesoundbits", "8");
cvar_t capturemessage = CVAR("capturemessage", ""); 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)); memset(&bitmap_info_header, 0, sizeof(BITMAPINFOHEADER));
bitmap_info_header.biSize = 40; bitmap_info_header.biSize = 40;
bitmap_info_header.biWidth = vid.pixelwidth; bitmap_info_header.biWidth = width;
bitmap_info_header.biHeight = vid.pixelheight; bitmap_info_header.biHeight = height;
bitmap_info_header.biPlanes = 1; bitmap_info_header.biPlanes = 1;
bitmap_info_header.biBitCount = 24; bitmap_info_header.biBitCount = 24;
bitmap_info_header.biCompression = BI_RGB; 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)); 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.fccHandler = ctx->codec_fourcc;
stream_header.dwScale = 100; stream_header.dwScale = 100;
stream_header.dwRate = (unsigned long)(0.5 + 100.0/captureframeinterval); 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); hr = qAVIFileCreateStreamA(ctx->file, &ctx->uncompressed_video_stream, &stream_header);
if (FAILED(hr)) if (FAILED(hr))
@ -2990,6 +2985,30 @@ static media_encoder_funcs_t capture_avi =
}; };
#endif #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 media_encoder_funcs_t *pluginencodersfunc[8];
static struct plugin_s *pluginencodersplugin[8]; static struct plugin_s *pluginencodersplugin[8];
qboolean Media_RegisterEncoder(struct plugin_s *plug, media_encoder_funcs_t *funcs) 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++) for (i = 0; i < sizeof(pluginencodersfunc)/sizeof(pluginencodersfunc[0]); i++)
{ {
if (pluginencodersplugin[i])
if (pluginencodersfunc[i] == funcs || (!funcs && pluginencodersplugin[i] == plug)) if (pluginencodersfunc[i] == funcs || (!funcs && pluginencodersplugin[i] == plug))
{ {
if (currentcapture_funcs == funcs) if (currentcapture_funcs == pluginencodersfunc[i])
Media_StopRecordFilm_f(); Media_StopRecordFilm_f();
success = true; success = true;
pluginencodersfunc[i] = NULL; pluginencodersfunc[i] = NULL;
@ -3163,6 +3183,37 @@ skipframe:
if (y < scr_con_current) y = scr_con_current; if (y < scr_con_current) y = scr_con_current;
if (y > vid.height-8) if (y > vid.height-8)
y = vid.height-8; y = vid.height-8;
#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"); 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_funcs->capture_end(currentcapture_ctx);
currentcapture_ctx = NULL; currentcapture_ctx = NULL;
currentcapture_funcs = 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 sndkhz, sndchannels, sndbits;
int i; int i;
if (Cmd_Argc() != 2)
{
Con_Printf("capture <filename>\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(); Media_StopRecordFilm_f();
if (capturerate.value<=0) if (capturerate.value<=0)
@ -3383,17 +3433,46 @@ void Media_RecordFilm_f (void)
sndbits = 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) if (!currentcapture_funcs->capture_begin)
currentcapture_ctx = NULL; currentcapture_ctx = NULL;
else 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) if (!currentcapture_ctx)
{ {
recordingdemo = false;
currentcapture_funcs = NULL; currentcapture_funcs = NULL;
Con_Printf("Unable to initialise capture driver\n"); Con_Printf("Unable to initialise capture driver\n");
} }
else if (sndkhz) else if (sndkhz)
Media_InitFakeSoundDevice(sndkhz, sndchannels, sndbits); Media_InitFakeSoundDevice(sndkhz, sndchannels, sndbits);
Cvar_ForceCallback(&vid_conautoscale);
}
static void Media_RecordFilm_f (void)
{
if (Cmd_Argc() != 2)
{
Con_Printf("capture <filename>\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) void Media_CaptureDemoEnd(void)
{ {
@ -3414,22 +3493,20 @@ void Media_RecordDemo_f(void)
return; return;
} }
CL_Stopdemo_f(); //capturing failed for some reason
CL_PlayDemo(Cmd_Argv(1), false); CL_PlayDemo(Cmd_Argv(1), false);
if (!cls.demoplayback) if (!cls.demoplayback)
{ {
Con_Printf("unable to play demo, not capturing\n"); Con_Printf("unable to play demo, not capturing\n");
return; return;
} }
//FIXME: mamke sure it loaded okay //FIXME: make sure it loaded okay
if (Cmd_Argc() > 2) Media_RecordFilm(Cmd_Argv(Cmd_Argc()>2?2:1), true);
Cmd_ShiftArgs(1, false);
Media_RecordFilm_f();
scr_con_current=0; scr_con_current=0;
Key_Dest_Remove(kdm_console|kdm_emenu|kdm_gmenu); Key_Dest_Remove(kdm_console|kdm_emenu|kdm_gmenu);
if (currentcapture_funcs) if (!currentcapture_funcs)
recordingdemo = true;
else
CL_Stopdemo_f(); //capturing failed for some reason CL_Stopdemo_f(); //capturing failed for some reason
} }
@ -4137,6 +4214,9 @@ void Media_Init(void)
Media_RegisterEncoder(NULL, &capture_avi); Media_RegisterEncoder(NULL, &capture_avi);
#endif #endif
Media_RegisterEncoder(NULL, &capture_raw); Media_RegisterEncoder(NULL, &capture_raw);
#ifdef _DEBUG
Media_RegisterEncoder(NULL, &capture_null);
#endif
Cmd_AddCommand("playvideo", Media_PlayFilm_f); Cmd_AddCommand("playvideo", Media_PlayFilm_f);
Cmd_AddCommand("playfilm", 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; media_playlisttypes = MEDIA_PLAYLIST | MEDIA_GAMEMUSIC | MEDIA_CVARLIST;
#if defined(GLQUAKE)
Cmd_AddCommand("capture", Media_RecordFilm_f); Cmd_AddCommand("capture", Media_RecordFilm_f);
Cmd_AddCommand("capturedemo", Media_RecordDemo_f); Cmd_AddCommand("capturedemo", Media_RecordDemo_f);
Cmd_AddCommand("capturestop", Media_StopRecordFilm_f); Cmd_AddCommand("capturestop", Media_StopRecordFilm_f);
@ -4173,6 +4252,8 @@ void Media_Init(void)
Cvar_Register(&capturemessage, "AVI capture controls"); Cvar_Register(&capturemessage, "AVI capture controls");
Cvar_Register(&capturesound, "AVI capture controls"); Cvar_Register(&capturesound, "AVI capture controls");
Cvar_Register(&capturerate, "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(&capturedriver, "AVI capture controls");
Cvar_Register(&capturecodec, "AVI capture controls"); Cvar_Register(&capturecodec, "AVI capture controls");
@ -4183,8 +4264,6 @@ void Media_Init(void)
S_RegisterSoundInputPlugin(S_LoadMP3Sound); S_RegisterSoundInputPlugin(S_LoadMP3Sound);
#endif #endif
#endif
#ifdef WINAMP #ifdef WINAMP
Cvar_Register(&media_hijackwinamp, "Media player things"); Cvar_Register(&media_hijackwinamp, "Media player things");
#endif #endif

View file

@ -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_ImagePaletteColour(unsigned int i, float a);
void R2D_FillBlock(float x, float y, float w, float h); 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); void R2D_Line(float x1, float y1, float x2, float y2, mpic_t *pic);
extern void (*R2D_Flush)(void);
extern void (*Draw_Init) (void); extern void (*Draw_Init) (void);
@ -226,7 +227,7 @@ typedef struct image_s
char *ident; //allocated on end char *ident; //allocated on end
char *subpath; //allocated on end char *subpath; //allocated on end
int regsequence; 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 height;
int status; //TEX_ int status; //TEX_
unsigned int flags; unsigned int flags;

View file

@ -2936,6 +2936,8 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor
*nl = '\0'; *nl = '\0';
details.players[clnum].isspec = false; details.players[clnum].isspec = false;
details.players[clnum].team[0] = 0;
details.players[clnum].skin[0] = 0;
token = msg; token = msg;
if (!token) if (!token)

View file

@ -19,7 +19,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#include "quakedef.h" #include "quakedef.h"
#include "gl_draw.h"
/* /*

View file

@ -1045,18 +1045,27 @@ void R2D_Console_Resize(void)
float ang, rad; float ang, rad;
extern cvar_t gl_screenangle; 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 = (gl_screenangle.value>0?(gl_screenangle.value+45):(gl_screenangle.value-45))/90;
ang = (int)ang * 90; ang = (int)ang * 90;
if (ang) if (ang)
{ {
rad = (ang * M_PI) / 180; rad = (ang * M_PI) / 180;
vid.rotpixelwidth = fabs(cos(rad)) * (vid.pixelwidth) + fabs(sin(rad)) * (vid.pixelheight); vid.rotpixelwidth = fabs(cos(rad)) * (fbwidth) + fabs(sin(rad)) * (fbheight);
vid.rotpixelheight = fabs(sin(rad)) * (vid.pixelwidth) + fabs(cos(rad)) * (vid.pixelheight); vid.rotpixelheight = fabs(sin(rad)) * (fbwidth) + fabs(cos(rad)) * (fbheight);
} }
else else
{ {
vid.rotpixelwidth = vid.pixelwidth; vid.rotpixelwidth = fbwidth;
vid.rotpixelheight = vid.pixelheight; vid.rotpixelheight = fbheight;
} }
cwidth = vid_conwidth.value; cwidth = vid_conwidth.value;

View file

@ -2476,7 +2476,6 @@ void Surf_Clear(model_t *mod)
} }
mod->numtextures = 0; mod->numtextures = 0;
BZ_Free(mod->shadowbatches); BZ_Free(mod->shadowbatches);
mod->numshadowbatches = 0; mod->numshadowbatches = 0;
mod->shadowbatches = NULL; mod->shadowbatches = NULL;

View file

@ -68,6 +68,7 @@ typedef struct
unsigned fbvheight; /*virtual 2d height*/ unsigned fbvheight; /*virtual 2d height*/
unsigned fbpwidth; /*virtual 2d width*/ unsigned fbpwidth; /*virtual 2d width*/
unsigned fbpheight; /*virtual 2d height*/ unsigned fbpheight; /*virtual 2d height*/
struct image_s *framebuffer; /*the framebuffer fbo (set by democapture)*/
unsigned width; /*virtual 2d screen width*/ unsigned width; /*virtual 2d screen width*/
unsigned height; /*virtual 2d screen height*/ unsigned height; /*virtual 2d screen height*/

View file

@ -23,7 +23,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "winquake.h" #include "winquake.h"
#include "glquake.h" #include "glquake.h"
#include "gl_draw.h"
#include <ctype.h> // for isdigit(); #include <ctype.h> // for isdigit();
@ -1125,7 +1124,7 @@ void V_ApplyAFov(playerview_t *pv)
//attempt to retain a classic fov //attempt to retain a classic fov
if (ws*r_refdef.vrect.width < (r_refdef.vrect.height*640)/432) 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); r_refdef.fov_x = afov;//CalcFov(r_refdef.fov_y, 432, 640);
} }
else else

View file

@ -2822,9 +2822,11 @@ void FS_PureMode(int puremode, char *purenamelist, char *purecrclist, char *refn
{ {
qboolean pureflush; qboolean pureflush;
#ifndef CLIENTONLY
//if we're the server, we can't be impure. //if we're the server, we can't be impure.
if (sv.state) if (sv.state)
return; return;
#endif
if (puremode == fs_puremode && fs_pureseed == pureseed) if (puremode == fs_puremode && fs_pureseed == pureseed)
{ {

View file

@ -254,13 +254,12 @@ static int D3D9Shader_FindUniform(union programhandle_u *h, int type, const char
return -1; 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; struct programpermu_s *pp;
unsigned int i, p; unsigned int i, p;
int uniformloc; int uniformloc;
char tmpname[128]; char tmpname[128];
cvar_t *cvar[128];
static const char *defaultsamplers[] = static const char *defaultsamplers[] =
{ {
@ -293,8 +292,6 @@ static void D3D9Shader_ProgAutoFields(program_t *prog, const char *progname, cha
prog->defaulttextures = 0; prog->defaulttextures = 0;
prog->numsamplers = 0; prog->numsamplers = 0;
memset(cvar, 0, sizeof(cvar));
for (p = 0; p < PERMUTATIONS; p++) for (p = 0; p < PERMUTATIONS; p++)
{ {
int maxparms = 0; 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]) if (!cvarrefs[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; continue;
cvar[i]->flags |= CVAR_SHADERSYSTEM; //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", tmpname)); uniformloc = D3D9Shader_FindUniform(&prog->permu[p].h, 1, va("cvar_%s", cvarnames[i]));
if (uniformloc != -1) if (uniformloc != -1)
{ {
vec4_t v = {cvar[i]->value, 0, 0, 0}; if (cvartypes[i] == SP_CVARI)
IDirect3DDevice9_SetVertexShader(pD3DDev9, prog->permu[p].h.hlsl.vert); {
IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, 0, v, 1); int v[4] = {cvarrefs[i]->ival, 0, 0, 0};
IDirect3DDevice9_SetVertexShaderConstantI(pD3DDev9, 0, v, 1);
} }
uniformloc = D3D9Shader_FindUniform(&prog->permu[p].h, 2, va("cvar_%s", tmpname)); else
IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, 0, cvarrefs[i]->vec4, 1);
}
uniformloc = D3D9Shader_FindUniform(&prog->permu[p].h, 2, va("cvar_%s", cvarnames[i]));
if (uniformloc != -1) if (uniformloc != -1)
{ {
vec4_t v = {cvar[i]->value, 0, 0, 0}; if (cvartypes[i] == SP_CVARI)
IDirect3DDevice9_SetPixelShader(pD3DDev9, prog->permu[p].h.hlsl.frag); {
IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, 0, v, 1); int v[4] = {cvarrefs[i]->ival, 0, 0, 0};
IDirect3DDevice9_SetPixelShaderConstantI(pD3DDev9, 0, v, 1);
}
else
IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, 0, cvarrefs[i]->vec4, 1);
} }
} }

View file

@ -892,6 +892,11 @@ void D3D9_Set2D (void)
vid.fbvheight = vid.height; vid.fbvheight = vid.height;
vid.fbpwidth = vid.pixelwidth; vid.fbpwidth = vid.pixelwidth;
vid.fbpheight = vid.pixelheight; 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) static int d3d9error(int i)
@ -1002,9 +1007,7 @@ static void (D3D9_SCR_UpdateScreen) (void)
{ {
Editor_Draw(); Editor_Draw();
V_UpdatePalette (false); V_UpdatePalette (false);
#if defined(_WIN32) && defined(GLQUAKE)
Media_RecordFrame(); Media_RecordFrame();
#endif
R2D_BrightenScreen(); R2D_BrightenScreen();
if (key_dest == key_console) if (key_dest == key_console)
@ -1020,9 +1023,7 @@ static void (D3D9_SCR_UpdateScreen) (void)
{ {
M_Draw(0); M_Draw(0);
// V_UpdatePalette (false); // V_UpdatePalette (false);
#if defined(_WIN32)
Media_RecordFrame(); Media_RecordFrame();
#endif
// R2D_BrightenScreen(); // R2D_BrightenScreen();
IDirect3DDevice9_EndScene(pD3DDev9); IDirect3DDevice9_EndScene(pD3DDev9);
IDirect3DDevice9_Present(pD3DDev9, NULL, NULL, NULL, NULL); IDirect3DDevice9_Present(pD3DDev9, NULL, NULL, NULL, NULL);
@ -1076,9 +1077,7 @@ static void (D3D9_SCR_UpdateScreen) (void)
SCR_DrawTwoDimensional(uimenu, nohud); SCR_DrawTwoDimensional(uimenu, nohud);
V_UpdatePalette (false); V_UpdatePalette (false);
#if defined(_WIN32) && defined(GLQUAKE)
Media_RecordFrame(); Media_RecordFrame();
#endif
RSpeedEnd(RSPEED_TOTALREFRESH); RSpeedEnd(RSPEED_TOTALREFRESH);
RSpeedShow(); RSpeedShow();
@ -1169,7 +1168,7 @@ static void D3D9_SetupViewPortProjection(void)
fov_x = r_refdef.fov_x;//+sin(cl.time)*5; fov_x = r_refdef.fov_x;//+sin(cl.time)*5;
fov_y = r_refdef.fov_y;//-sin(cl.time+1)*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_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value);
fov_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value); fov_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(); 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(); D3D9_SetupViewPortProjection();
// if (r_clear.ival && !(r_refdef.flags & RDF_NOWORLDMODEL)) // if (r_clear.ival && !(r_refdef.flags & RDF_NOWORLDMODEL))

View file

@ -1184,6 +1184,11 @@ void D3D11_Set2D (void)
vid.fbpheight = vid.pixelheight; vid.fbpheight = vid.pixelheight;
D3D11BE_Scissor(NULL); 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) static void (D3D11_SCR_UpdateScreen) (void)
@ -1257,9 +1262,7 @@ static void (D3D11_SCR_UpdateScreen) (void)
{ {
Editor_Draw(); Editor_Draw();
V_UpdatePalette (false); V_UpdatePalette (false);
#if defined(_WIN32) && defined(GLQUAKE)
Media_RecordFrame(); Media_RecordFrame();
#endif
R2D_BrightenScreen(); R2D_BrightenScreen();
if (key_dest == key_console) if (key_dest == key_console)
@ -1275,9 +1278,7 @@ static void (D3D11_SCR_UpdateScreen) (void)
{ {
M_Draw(0); M_Draw(0);
// V_UpdatePalette (false); // V_UpdatePalette (false);
#if defined(_WIN32)
Media_RecordFrame(); Media_RecordFrame();
#endif
// R2D_BrightenScreen(); // R2D_BrightenScreen();
// IDirect3DDevice9_EndScene(pD3DDev9); // IDirect3DDevice9_EndScene(pD3DDev9);
D3D11_PresentOrCrash(); D3D11_PresentOrCrash();
@ -1339,9 +1340,7 @@ static void (D3D11_SCR_UpdateScreen) (void)
V_UpdatePalette (false); V_UpdatePalette (false);
#if defined(_WIN32) && defined(GLQUAKE)
Media_RecordFrame(); Media_RecordFrame();
#endif
RSpeedEnd(RSPEED_TOTALREFRESH); RSpeedEnd(RSPEED_TOTALREFRESH);
RSpeedShow(); RSpeedShow();
@ -1419,7 +1418,7 @@ static void D3D11_SetupViewPort(void)
fov_x = r_refdef.fov_x;//+sin(cl.time)*5; fov_x = r_refdef.fov_x;//+sin(cl.time)*5;
fov_y = r_refdef.fov_y;//-sin(cl.time+1)*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_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value);
fov_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value); fov_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value);
@ -1447,6 +1446,23 @@ static void (D3D11_R_RenderView) (void)
else else
ID3D11DeviceContext_ClearDepthStencilView(d3ddevctx, fb_backdepthstencil, D3D11_CLEAR_DEPTH, 1, 0); //is it faster to clear the stencil too? 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(); D3D11_SetupViewPort();
//unlike gl, we clear colour beforehand, because that seems more sane. //unlike gl, we clear colour beforehand, because that seems more sane.
//always clear depth //always clear depth

View file

@ -134,7 +134,14 @@ void GL_Set2D (qboolean flipped)
float w = vid.width, h = vid.height; float w = vid.width, h = vid.height;
qboolean fbo = !!*r_refdef.rt_destcolour[0].texname; 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); R2D_RT_GetTexture(r_refdef.rt_destcolour[0].texname, &vid.fbpwidth, &vid.fbpheight);
vid.fbvwidth = vid.fbpwidth; vid.fbvwidth = vid.fbpwidth;

View file

@ -25,7 +25,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "glquake.h" #include "glquake.h"
#include "renderque.h" #include "renderque.h"
#include "shader.h" #include "shader.h"
#include "gl_draw.h"
void R_RenderBrushPoly (msurface_t *fa); void R_RenderBrushPoly (msurface_t *fa);
@ -1697,10 +1696,11 @@ void GLR_RenderView (void)
texid_t sourcetex = r_nulltex; texid_t sourcetex = r_nulltex;
shader_t *custompostproc = NULL; shader_t *custompostproc = NULL;
float renderscale = r_renderscale.value; //extreme, but whatever float renderscale = r_renderscale.value; //extreme, but whatever
int oldfbo = 0;
checkglerror(); checkglerror();
if (r_norefresh.value || !vid.pixelwidth || !vid.pixelheight) if (r_norefresh.value || !vid.fbpwidth || !vid.fbpwidth)
return; return;
//when loading/bugged, its possible that the world is still loading. //when loading/bugged, its possible that the world is still loading.
@ -1811,13 +1811,21 @@ void GLR_RenderView (void)
flags |= FBO_TEX_DEPTH; flags |= FBO_TEX_DEPTH;
else else
flags |= FBO_RB_DEPTH; 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) else if ((r_refdef.flags & (RDF_ALLPOSTPROC)) || renderscale != 1)
{ {
//the game needs to be drawn to a texture for post processing //the game needs to be drawn to a texture for post processing
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.fbpwidth = (r_refdef.vrect.width * vid.pixelwidth) / vid.width;
vid.fbpheight = (r_refdef.vrect.height * vid.pixelheight) / vid.height; vid.fbpheight = (r_refdef.vrect.height * vid.pixelheight) / vid.height;
}
vid.fbpwidth *= renderscale; vid.fbpwidth *= renderscale;
vid.fbpheight *= 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); 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; 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 else
{ {
vid.fbvwidth = vid.width; vid.fbvwidth = vid.width;
@ -1902,12 +1917,10 @@ void GLR_RenderView (void)
//update stuff now that we're not rendering the 3d scene //update stuff now that we're not rendering the 3d scene
if (dofbo) if (dofbo)
GLBE_RenderToTextureUpdate2d(true); GLBE_FBO_Pop(oldfbo);
else
{
GLBE_RenderToTextureUpdate2d(false); GLBE_RenderToTextureUpdate2d(false);
GL_Set2D (false); GL_Set2D (false);
}
// SCENE POST PROCESSING // SCENE POST PROCESSING

View file

@ -249,13 +249,8 @@ char *GLVID_GetRGBInfo(int prepadbytes, int *truewidth, int *trueheight)
int i, c; int i, c;
qbyte *ret; qbyte *ret;
*truewidth = vid.pixelwidth; *truewidth = vid.fbpwidth;
*trueheight = vid.pixelheight; *trueheight = vid.fbpheight;
if (*r_refdef.rt_destcolour[0].texname)
{
R2D_RT_GetTexture(r_refdef.rt_destcolour[0].texname, truewidth, trueheight);
}
/*if (1) /*if (1)
{ {
@ -275,7 +270,7 @@ char *GLVID_GetRGBInfo(int prepadbytes, int *truewidth, int *trueheight)
} }
BZ_Free(p); BZ_Free(p);
} }
else*/ if (gl_config.gles || (vid.pixelwidth&3)) else*/ if (gl_config.gles || (*truewidth&3))
{ {
qbyte *p; qbyte *p;

View file

@ -585,7 +585,7 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
// to = MULTICAST_ALL; // 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 //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) switch(to)
{ {