2004-08-22 15:29:09 -07:00
/*
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"
2009-11-04 13:16:50 -08:00
# ifdef GLQUAKE
2004-08-22 15:29:09 -07:00
# include "glquake.h"
2009-11-04 13:16:50 -08:00
# include "shader.h"
2010-05-01 15:47:47 -07:00
# include "gl_draw.h"
2004-08-22 15:29:09 -07:00
# include <time.h>
void GLSCR_UpdateScreen ( void ) ;
extern qboolean scr_drawdialog ;
2011-06-16 18:54:54 -07:00
extern cvar_t vid_triplebuffer ;
2004-08-22 15:29:09 -07:00
extern cvar_t scr_fov ;
extern qboolean scr_initialized ;
extern float oldsbar ;
extern qboolean scr_drawloading ;
extern int scr_chatmode ;
extern cvar_t scr_chatmodecvar ;
2009-03-02 17:52:30 -08:00
extern cvar_t vid_conautoscale ;
2009-11-04 13:16:50 -08:00
extern qboolean scr_con_forcedraw ;
2015-01-07 05:34:05 -08:00
extern qboolean depthcleared ;
2004-08-22 15:29:09 -07:00
/*
= = = = = = = = = = = = = = = = = =
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 256 k of stack space !
= = = = = = = = = = = = = = = = = =
*/
2015-02-02 00:01:53 -08:00
void SCR_DrawCursor ( void ) ;
2004-08-22 15:29:09 -07:00
void GLSCR_UpdateScreen ( void )
{
int uimenu ;
# ifdef TEXTEDITOR
2005-01-24 15:47:32 -08:00
extern qboolean editormodal ;
2004-08-22 15:29:09 -07:00
# endif
2004-12-24 00:45:56 -08:00
qboolean nohud ;
2009-04-05 17:34:32 -07:00
qboolean noworld ;
2004-12-15 11:53:30 -08:00
RSpeedMark ( ) ;
2013-11-21 15:02:28 -08:00
r_refdef . pxrect . maxheight = vid . pixelheight ;
2011-06-16 18:54:54 -07:00
vid . numpages = 2 + vid_triplebuffer . value ;
2004-08-22 15:29:09 -07:00
2013-12-29 14:48:28 -08:00
R2D_Font_Changed ( ) ;
2004-08-22 15:29:09 -07:00
if ( scr_disabled_for_loading )
{
2005-02-12 10:56:04 -08:00
extern float scr_disabled_time ;
2013-10-08 07:28:11 -07:00
if ( Sys_DoubleTime ( ) - scr_disabled_time > 60 | | ! Key_Dest_Has ( ~ kdm_game ) )
2004-08-22 15:29:09 -07:00
{
2013-10-08 07:28:11 -07:00
//FIXME: instead of reenabling the screen, we should just draw the relevent things skipping only the game.
2004-08-22 15:29:09 -07:00
scr_disabled_for_loading = false ;
}
else
2015-08-10 11:28:23 -07:00
{
2006-09-16 17:59:22 -07:00
scr_drawloading = true ;
2014-03-29 17:39:37 -07:00
SCR_DrawLoading ( true ) ;
2006-09-16 17:59:22 -07:00
scr_drawloading = false ;
2015-08-10 11:28:23 -07:00
if ( R2D_Flush )
R2D_Flush ( ) ;
2014-03-29 17:39:37 -07:00
VID_SwapBuffers ( ) ;
2004-12-15 11:53:30 -08:00
RSpeedEnd ( RSPEED_TOTALREFRESH ) ;
2004-08-22 15:29:09 -07:00
return ;
}
}
if ( ! scr_initialized | | ! con_initialized )
2004-12-15 11:53:30 -08:00
{
RSpeedEnd ( RSPEED_TOTALREFRESH ) ;
2004-08-22 15:29:09 -07:00
return ; // not initialized yet
2004-12-15 11:53:30 -08:00
}
2004-08-22 15:29:09 -07:00
2009-11-07 05:29:15 -08:00
Shader_DoReload ( ) ;
2014-03-30 01:55:06 -07:00
qglDisable ( GL_SCISSOR_TEST ) ;
2005-09-09 16:40:55 -07:00
# ifdef VM_UI
2004-08-22 15:29:09 -07:00
uimenu = UI_MenuState ( ) ;
2005-09-09 16:40:55 -07:00
# else
uimenu = 0 ;
# endif
2004-08-22 15:29:09 -07:00
# ifdef TEXTEDITOR
if ( editormodal )
{
Editor_Draw ( ) ;
2011-12-22 19:12:29 -08:00
V_UpdatePalette ( false ) ;
2009-11-04 13:16:50 -08:00
# if defined(_WIN32) && defined(GLQUAKE)
2004-08-22 15:29:09 -07:00
Media_RecordFrame ( ) ;
# endif
2010-05-01 15:47:47 -07:00
R2D_BrightenScreen ( ) ;
2005-08-03 16:14:59 -07:00
2013-10-08 07:28:11 -07:00
if ( key_dest_mask & kdm_console )
2011-05-19 21:10:46 -07:00
Con_DrawConsole ( vid . height / 2 , false ) ;
2015-02-02 00:01:53 -08:00
SCR_DrawCursor ( ) ;
2015-08-10 11:28:23 -07:00
if ( R2D_Flush )
R2D_Flush ( ) ;
2014-03-29 17:39:37 -07:00
VID_SwapBuffers ( ) ;
2004-12-15 11:53:30 -08:00
RSpeedEnd ( RSPEED_TOTALREFRESH ) ;
2004-08-22 15:29:09 -07:00
return ;
}
# endif
if ( Media_ShowFilm ( ) )
{
M_Draw ( 0 ) ;
2011-12-22 19:12:29 -08:00
V_UpdatePalette ( false ) ;
2015-12-12 11:25:15 -08:00
R2D_BrightenScreen ( ) ;
2009-11-04 13:16:50 -08:00
# if defined(_WIN32) && defined(GLQUAKE)
2004-08-22 15:29:09 -07:00
Media_RecordFrame ( ) ;
# endif
2015-08-10 11:28:23 -07:00
if ( R2D_Flush )
R2D_Flush ( ) ;
2012-10-07 21:36:10 -07:00
GL_Set2D ( false ) ;
2014-03-29 17:39:37 -07:00
VID_SwapBuffers ( ) ;
2004-12-15 11:53:30 -08:00
RSpeedEnd ( RSPEED_TOTALREFRESH ) ;
2004-08-22 15:29:09 -07:00
return ;
}
//
// do 3D refresh drawing, and then update the screen
//
SCR_SetUpToDrawConsole ( ) ;
2004-12-24 00:45:56 -08:00
2009-04-05 17:34:32 -07:00
noworld = false ;
2004-12-24 00:45:56 -08:00
nohud = false ;
2005-09-08 15:52:46 -07:00
2015-01-07 05:34:05 -08:00
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 ;
}
2004-12-24 00:45:56 -08:00
# ifdef VM_CG
if ( CG_Refresh ( ) )
nohud = true ;
else
2005-01-06 19:07:50 -08:00
# endif
# ifdef CSQC_DAT
2013-03-12 15:53:23 -07:00
if ( CSQC_DrawView ( ) )
2005-01-06 19:07:50 -08:00
nohud = true ;
else
2004-12-24 00:45:56 -08:00
# endif
2014-03-29 17:39:37 -07:00
{
2009-04-05 17:34:32 -07:00
if ( uimenu ! = 1 )
2005-05-13 03:42:48 -07:00
{
2009-04-05 17:34:32 -07:00
if ( r_worldentity . model & & cls . state = = ca_active )
V_RenderView ( ) ;
else
{
noworld = true ;
}
2005-05-13 03:42:48 -07:00
}
2014-03-29 17:39:37 -07:00
}
2004-08-22 15:29:09 -07:00
2012-01-16 23:57:46 -08:00
GL_Set2D ( false ) ;
2004-08-22 15:29:09 -07:00
2009-11-04 13:16:50 -08:00
scr_con_forcedraw = false ;
2009-04-05 17:34:32 -07:00
if ( noworld )
{
extern char levelshotname [ ] ;
//draw the levelshot or the conback fullscreen
if ( * levelshotname )
2011-03-30 18:14:01 -07:00
R2D_ScalePic ( 0 , 0 , vid . width , vid . height , R2D_SafeCachePic ( levelshotname ) ) ;
2009-11-04 13:16:50 -08:00
else if ( scr_con_current ! = vid . height )
2011-03-30 18:14:01 -07:00
R2D_ConsoleBackground ( 0 , vid . height , true ) ;
2009-11-04 13:16:50 -08:00
else
scr_con_forcedraw = true ;
2009-04-05 17:34:32 -07:00
nohud = true ;
2013-06-22 19:17:02 -07:00
}
2005-02-06 05:54:36 -08:00
2004-12-24 00:45:56 -08:00
SCR_DrawTwoDimensional ( uimenu , nohud ) ;
2004-08-22 15:29:09 -07:00
2011-12-22 19:12:29 -08:00
V_UpdatePalette ( false ) ;
2012-11-26 19:23:19 -08:00
R2D_BrightenScreen ( ) ;
2009-11-04 13:16:50 -08:00
# if defined(_WIN32) && defined(GLQUAKE)
2004-08-22 15:29:09 -07:00
Media_RecordFrame ( ) ;
# endif
2004-12-15 11:53:30 -08:00
2015-10-11 04:34:58 -07:00
RSpeedShow ( ) ;
2015-07-30 09:26:15 -07:00
if ( R2D_Flush )
R2D_Flush ( ) ;
2015-08-10 11:28:23 -07:00
RSpeedEnd ( RSPEED_TOTALREFRESH ) ;
2013-10-08 07:28:11 -07:00
RSpeedRemark ( ) ;
2014-03-29 17:39:37 -07:00
VID_SwapBuffers ( ) ;
2013-10-08 07:28:11 -07:00
RSpeedEnd ( RSPEED_FINISH ) ;
2014-10-22 12:41:20 -07:00
//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 ;
}
}
2004-08-22 15:29:09 -07:00
}
2015-08-13 19:46:38 -07:00
char * GLVID_GetRGBInfo ( int * truewidth , int * trueheight , enum uploadfmt * fmt )
2004-08-22 15:29:09 -07:00
{ //returns a BZ_Malloced array
2004-11-28 17:21:00 -08:00
extern qboolean gammaworks ;
int i , c ;
2011-03-31 16:05:19 -07:00
qbyte * ret ;
2015-08-27 20:13:45 -07:00
extern qboolean r2d_canhwgamma ;
2004-08-22 15:29:09 -07:00
2015-08-11 02:14:33 -07:00
* truewidth = vid . fbpwidth ;
* trueheight = vid . fbpheight ;
2015-02-02 00:01:53 -08:00
2012-04-24 00:59:11 -07:00
/*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 ) ;
2015-08-13 19:46:38 -07:00
ret = BZ_Malloc ( vid . pixelwidth * vid . pixelheight * 3 ) ;
2012-04-24 00:59:11 -07:00
c = vid . pixelwidth * vid . pixelheight ;
for ( i = 1 ; i < c ; i + + )
{
2015-08-13 19:46:38 -07:00
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 ;
2012-04-24 00:59:11 -07:00
}
BZ_Free ( p ) ;
}
2015-08-11 02:14:33 -07:00
else */ if ( gl_config . gles | | ( * truewidth & 3 ) )
2011-03-31 16:05:19 -07:00
{
qbyte * p ;
2015-08-13 19:46:38 -07:00
//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.
2011-03-31 16:05:19 -07:00
2015-08-13 19:46:38 -07:00
ret = BZ_Malloc ( ( * truewidth ) * ( * trueheight ) * 4 ) ;
qglReadPixels ( 0 , 0 , ( * truewidth ) , ( * trueheight ) , GL_RGBA , GL_UNSIGNED_BYTE , ret ) ;
* fmt = TF_RGB24 ;
2015-02-02 00:01:53 -08:00
c = ( * truewidth ) * ( * trueheight ) ;
2015-08-13 19:46:38 -07:00
p = ret ;
2011-03-31 16:05:19 -07:00
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 ] ;
}
2015-08-13 19:46:38 -07:00
ret = BZ_Realloc ( ret , ( * truewidth ) * ( * trueheight ) * 3 ) ;
}
2016-02-14 22:01:17 -08:00
# if 1 //def _DEBUG
else if ( ! gl_config . gles & & sh_config . texfmt [ PTI_BGRA8 ] )
2015-08-13 19:46:38 -07:00
{
* 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 ) ;
2011-03-31 16:05:19 -07:00
}
2015-08-13 19:46:38 -07:00
# endif
2011-03-31 16:05:19 -07:00
else
{
2015-08-13 19:46:38 -07:00
* fmt = TF_RGB24 ;
ret = BZ_Malloc ( ( * truewidth ) * ( * trueheight ) * 3 ) ;
qglReadPixels ( 0 , 0 , ( * truewidth ) , ( * trueheight ) , GL_RGB , GL_UNSIGNED_BYTE , ret ) ;
2011-03-31 16:05:19 -07:00
}
2004-08-22 15:29:09 -07:00
2015-08-27 20:13:45 -07:00
if ( gammaworks & & r2d_canhwgamma )
2004-11-28 17:21:00 -08:00
{
2015-08-27 20:13:45 -07:00
if ( * fmt = = TF_BGRA32 | | * fmt = = TF_RGBA32 )
2004-11-28 17:21:00 -08:00
{
2015-08-27 20:13:45 -07:00
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 ] ] ;
}
2004-11-28 17:21:00 -08:00
}
}
2004-08-22 15:29:09 -07:00
return ret ;
}
2004-12-15 11:53:30 -08:00
# endif