6c5de8e8b1
Added Z_EXT_PF_ONGROUND + Z_EXT_PF_SOLID for compat (not enabled serverside due to conflicts with pext - just a define away). Fixed bug with loading screens switching sizes part way through loading. Added hexen2 rain effect. Fix hexen2 model texture alphas not working. Fix potential linux crash from excessively long stdin lines. Added cl_rollalpha cvar. Fixed quirk where the player would slide along the base of steep walls/slopes. Tweaked PM_NudgePosition to be more precise, giving more reliable prediction. Fixed fread qc builtin. Tweaked random() builtin to bias slightly away from 0, so that nextthink=random()*foo; will never cause statue-monsters. Check for GL_WEBGL_depth_texture instead of just GL_OES_depth_texture, to fix compressedTex2d errors in firefox. Second attempt at blocking invariant keyword with mesa. Use xrandr for gamma where possible. This prevents reading stale XF86 gamma ramps and restoring those invalid ramps when quitting. Try to grab mouse pointers slightly faster in x11. Don't call XIFreeDeviceInfo if XIQueryDevice returned NULL. Document parm_string and startspot qc globals. Fix possible infinite loop from physics frames. QTV: stripped most of the old plugin code (because really, who has a browser that still supports either ActiveX or NPAPI). Fixed up emscripten port references. QTV: fix bug with protocol extensions not being reported to viewers. QTV: use binary websockets instead of text. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5419 fc73d0e0-1445-4013-8a0c-d673dee63da5
362 lines
8.1 KiB
C
362 lines
8.1 KiB
C
/*
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
// screen.c -- master for refresh, status bar, console, chat, notify, etc
|
|
|
|
#include "quakedef.h"
|
|
extern qboolean gammaworks;
|
|
#ifdef GLQUAKE
|
|
#include "glquake.h"
|
|
#include "shader.h"
|
|
#include "gl_draw.h"
|
|
|
|
#include <time.h>
|
|
|
|
qboolean GLSCR_UpdateScreen (void);
|
|
|
|
|
|
extern qboolean scr_drawdialog;
|
|
|
|
extern cvar_t vid_triplebuffer;
|
|
extern cvar_t scr_fov;
|
|
|
|
extern qboolean scr_initialized;
|
|
extern float oldsbar;
|
|
extern qboolean scr_drawloading;
|
|
|
|
extern cvar_t vid_conautoscale;
|
|
extern qboolean scr_con_forcedraw;
|
|
extern qboolean depthcleared;
|
|
|
|
/*
|
|
==================
|
|
SCR_UpdateScreen
|
|
|
|
This is called every frame, and can also be called explicitly to flush
|
|
text to the screen.
|
|
|
|
WARNING: be very careful calling this from elsewhere, because the refresh
|
|
needs almost the entire 256k of stack space!
|
|
==================
|
|
*/
|
|
void SCR_DrawCursor(void);
|
|
qboolean GLSCR_UpdateScreen (void)
|
|
{
|
|
int uimenu;
|
|
qboolean nohud;
|
|
qboolean noworld;
|
|
extern cvar_t vid_srgb;
|
|
|
|
r_refdef.pxrect.maxheight = vid.pixelheight;
|
|
|
|
vid.numpages = 2 + vid_triplebuffer.value;
|
|
|
|
R2D_Font_Changed();
|
|
|
|
if (vid_srgb.modified)
|
|
{
|
|
vid_srgb.modified = false;
|
|
|
|
//vid_srgb can be changed between 0 and 1, but other values need texture reloads. do that without too much extra weirdness.
|
|
if ((vid.flags & VID_SRGB_CAPABLE) && gl_config.arb_framebuffer_srgb)
|
|
{ //srgb-capable
|
|
if (vid_srgb.ival > 0 && (vid.flags & VID_SRGBAWARE))
|
|
{ //full srgb wanted (and textures are loaded)
|
|
qglEnable(GL_FRAMEBUFFER_SRGB);
|
|
vid.flags |= VID_SRGB_FB_LINEAR;
|
|
}
|
|
else if (vid_srgb.ival < 0 || (vid.flags & VID_SRGBAWARE))
|
|
{ //srgb wanted only for the framebuffer, for gamma tricks.
|
|
qglEnable(GL_FRAMEBUFFER_SRGB);
|
|
vid.flags |= VID_SRGB_FB_LINEAR;
|
|
}
|
|
else
|
|
{ //srgb not wanted...
|
|
qglDisable(GL_FRAMEBUFFER_SRGB);
|
|
vid.flags &= ~VID_SRGB_FB_LINEAR;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!scr_initialized || !con_initialized)
|
|
{
|
|
return false; // not initialized yet
|
|
}
|
|
|
|
if (scr_disabled_for_loading)
|
|
{
|
|
extern float scr_disabled_time;
|
|
if (Sys_DoubleTime() - scr_disabled_time > 60 || !Key_Dest_Has(~kdm_game))
|
|
{
|
|
//FIXME: instead of reenabling the screen, we should just draw the relevent things skipping only the game.
|
|
scr_disabled_for_loading = false;
|
|
}
|
|
else
|
|
{
|
|
// scr_drawloading = true;
|
|
SCR_DrawLoading (true);
|
|
SCR_SetUpToDrawConsole();
|
|
if (Key_Dest_Has(kdm_console))
|
|
SCR_DrawConsole(false);
|
|
// scr_drawloading = false;
|
|
if (R2D_Flush)
|
|
R2D_Flush();
|
|
VID_SwapBuffers();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
Shader_DoReload();
|
|
|
|
qglDisable(GL_SCISSOR_TEST);
|
|
#ifdef VM_UI
|
|
uimenu = UI_MenuState();
|
|
#else
|
|
uimenu = 0;
|
|
#endif
|
|
|
|
#ifdef TEXTEDITOR
|
|
if (editormodal)
|
|
{
|
|
Editor_Draw();
|
|
V_UpdatePalette (false);
|
|
Media_RecordFrame();
|
|
R2D_BrightenScreen();
|
|
|
|
if (key_dest_mask & kdm_console)
|
|
Con_DrawConsole(vid.height/2, false);
|
|
else
|
|
Con_DrawConsole(0, false);
|
|
SCR_DrawCursor();
|
|
if (R2D_Flush)
|
|
R2D_Flush();
|
|
VID_SwapBuffers();
|
|
return true;
|
|
}
|
|
#endif
|
|
if (Media_ShowFilm())
|
|
{
|
|
M_Draw(0);
|
|
V_UpdatePalette (false);
|
|
R2D_BrightenScreen();
|
|
Media_RecordFrame();
|
|
if (R2D_Flush)
|
|
R2D_Flush();
|
|
GL_Set2D (false);
|
|
VID_SwapBuffers();
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// do 3D refresh drawing, and then update the screen
|
|
//
|
|
SCR_SetUpToDrawConsole ();
|
|
|
|
noworld = false;
|
|
nohud = false;
|
|
|
|
if (r_clear.ival)
|
|
{
|
|
GL_ForceDepthWritable();
|
|
qglClearColor((r_clear.ival&1)?1:0, (r_clear.ival&2)?1:0, (r_clear.ival&4)?1:0, 1);
|
|
qglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
depthcleared = true;
|
|
}
|
|
|
|
#ifdef VM_CG
|
|
if (CG_Refresh())
|
|
nohud = true;
|
|
else
|
|
#endif
|
|
#ifdef CSQC_DAT
|
|
if (CSQC_DrawView())
|
|
nohud = true;
|
|
else
|
|
#endif
|
|
{
|
|
if (uimenu != 1)
|
|
{
|
|
if (r_worldentity.model && cls.state == ca_active)
|
|
V_RenderView (nohud);
|
|
else
|
|
{
|
|
noworld = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
GL_Set2D (false);
|
|
|
|
scr_con_forcedraw = false;
|
|
if (noworld)
|
|
{
|
|
//draw the levelshot or the conback fullscreen
|
|
if (R2D_DrawLevelshot())
|
|
;
|
|
else if (scr_con_current != vid.height)
|
|
R2D_ConsoleBackground(0, vid.height, true);
|
|
else
|
|
scr_con_forcedraw = true;
|
|
|
|
nohud = true;
|
|
}
|
|
|
|
SCR_DrawTwoDimensional(uimenu, nohud);
|
|
|
|
V_UpdatePalette (false);
|
|
R2D_BrightenScreen();
|
|
|
|
Media_RecordFrame();
|
|
|
|
RSpeedShow();
|
|
|
|
if (R2D_Flush)
|
|
R2D_Flush();
|
|
|
|
{
|
|
RSpeedMark();
|
|
VID_SwapBuffers();
|
|
RSpeedEnd(RSPEED_PRESENT);
|
|
}
|
|
|
|
//gl 4.5 / GL_ARB_robustness / GL_KHR_robustness
|
|
if (qglGetGraphicsResetStatus)
|
|
{
|
|
GLenum err = qglGetGraphicsResetStatus();
|
|
switch(err)
|
|
{
|
|
case GL_NO_ERROR:
|
|
break;
|
|
case GL_GUILTY_CONTEXT_RESET: //we did it
|
|
case GL_INNOCENT_CONTEXT_RESET: //something else broke the hardware and broke our ram
|
|
case GL_UNKNOWN_CONTEXT_RESET: //whodunit
|
|
default:
|
|
Con_Printf("OpenGL reset detected\n");
|
|
Sys_Sleep(3.0);
|
|
Cmd_ExecuteString("vid_restart", RESTRICT_LOCAL);
|
|
break;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
char *GLVID_GetRGBInfo(int *bytestride, int *truewidth, int *trueheight, enum uploadfmt *fmt)
|
|
{ //returns a BZ_Malloced array
|
|
extern qboolean gammaworks;
|
|
int i, c;
|
|
qbyte *ret;
|
|
extern qboolean r2d_canhwgamma;
|
|
|
|
*bytestride = 0;
|
|
*truewidth = vid.fbpwidth;
|
|
*trueheight = vid.fbpheight;
|
|
|
|
/*if (1)
|
|
{
|
|
float *p;
|
|
|
|
p = BZ_Malloc(vid.pixelwidth*vid.pixelheight*sizeof(float));
|
|
qglReadPixels (0, 0, vid.pixelwidth, vid.pixelheight, GL_DEPTH_COMPONENT, GL_FLOAT, p);
|
|
|
|
ret = BZ_Malloc(vid.pixelwidth*vid.pixelheight*3);
|
|
|
|
c = vid.pixelwidth*vid.pixelheight;
|
|
for (i = 1; i < c; i++)
|
|
{
|
|
ret[i*3+0]=p[i]*p[i]*p[i]*255;
|
|
ret[i*3+1]=p[i]*p[i]*p[i]*255;
|
|
ret[i*3+2]=p[i]*p[i]*p[i]*255;
|
|
}
|
|
BZ_Free(p);
|
|
}
|
|
else*/ if (gl_config.gles || (*truewidth&3))
|
|
{
|
|
qbyte *p;
|
|
|
|
//gles:
|
|
//Only two format/type parameter pairs are accepted.
|
|
//GL_RGBA/GL_UNSIGNED_BYTE is always accepted, and the other acceptable pair can be discovered by querying GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE.
|
|
//thus its simpler to only use GL_RGBA/GL_UNSIGNED_BYTE
|
|
//desktopgl:
|
|
//total line byte length must be aligned to GL_PACK_ALIGNMENT. by reading rgba instead of rgb, we can ensure the line is a multiple of 4 bytes.
|
|
|
|
ret = BZ_Malloc((*truewidth)*(*trueheight)*4);
|
|
qglReadPixels (0, 0, (*truewidth), (*trueheight), GL_RGBA, GL_UNSIGNED_BYTE, ret);
|
|
*bytestride = *truewidth*-3;
|
|
|
|
*fmt = TF_RGB24;
|
|
c = (*truewidth)*(*trueheight);
|
|
p = ret;
|
|
for (i = 1; i < c; i++)
|
|
{
|
|
p[i*3+0]=p[i*4+0];
|
|
p[i*3+1]=p[i*4+1];
|
|
p[i*3+2]=p[i*4+2];
|
|
}
|
|
ret = BZ_Realloc(ret, (*truewidth)*(*trueheight)*3);
|
|
}
|
|
#if 1//def _DEBUG
|
|
else if (!gl_config.gles && sh_config.texfmt[PTI_BGRA8])
|
|
{
|
|
*fmt = TF_BGRA32;
|
|
ret = BZ_Malloc((*truewidth)*(*trueheight)*4);
|
|
qglReadPixels (0, 0, (*truewidth), (*trueheight), GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, ret);
|
|
*bytestride = *truewidth*-4;
|
|
}
|
|
#endif
|
|
else
|
|
{
|
|
*fmt = TF_RGB24;
|
|
ret = BZ_Malloc((*truewidth)*(*trueheight)*3);
|
|
qglReadPixels (0, 0, (*truewidth), (*trueheight), GL_RGB, GL_UNSIGNED_BYTE, ret);
|
|
*bytestride = *truewidth*-3;
|
|
}
|
|
|
|
if (gammaworks && r2d_canhwgamma)
|
|
{
|
|
if (*fmt == TF_BGRA32 || *fmt == TF_RGBA32)
|
|
{
|
|
c = (*truewidth)*(*trueheight)*4;
|
|
for (i=0 ; i<c ; i+=4)
|
|
{
|
|
extern qbyte gammatable[256];
|
|
ret[i+0] = gammatable[ret[i+0]];
|
|
ret[i+1] = gammatable[ret[i+1]];
|
|
ret[i+2] = gammatable[ret[i+2]];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
c = (*truewidth)*(*trueheight)*3;
|
|
for (i=0 ; i<c ; i+=3)
|
|
{
|
|
extern qbyte gammatable[256];
|
|
ret[i+0] = gammatable[ret[i+0]];
|
|
ret[i+1] = gammatable[ret[i+1]];
|
|
ret[i+2] = gammatable[ret[i+2]];
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
#endif
|