2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2020-05-09 15:38:00 +00:00
Copyright ( C ) 2013 - 2020 Robert Beckebans
2016-07-15 06:36:34 +00:00
Copyright ( C ) 2014 - 2016 Kot in Action Creative Artel
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
Doom 3 BFG Edition Source Code 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 3 of the License , or
( at your option ) any later version .
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 BFG Edition Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# pragma hdrstop
2012-12-22 15:18:19 +00:00
# include "precompiled.h"
2012-11-26 18:58:24 +00:00
2017-09-03 08:22:36 +00:00
# include "RenderCommon.h"
2020-03-29 15:12:11 +00:00
# include "../framework/Common_local.h"
# include "../imgui/BFGimgui.h"
2012-11-26 18:58:24 +00:00
idRenderSystemLocal tr ;
2012-11-28 15:47:07 +00:00
idRenderSystem * renderSystem = & tr ;
2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = =
R_PerformanceCounters
This prints both front and back end counters , so it should
only be called when the back end thread is idle .
= = = = = = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderSystemLocal : : PrintPerformanceCounters ( )
2012-11-28 15:47:07 +00:00
{
if ( r_showPrimitives . GetInteger ( ) ! = 0 )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " views:%i draws:%i tris:%i (shdw:%i) \n " ,
2017-09-03 21:17:44 +00:00
pc . c_numViews ,
backend . pc . c_drawElements + backend . pc . c_shadowElements ,
( backend . pc . c_drawIndexes + backend . pc . c_shadowIndexes ) / 3 ,
backend . pc . c_shadowIndexes / 3
2012-11-28 15:47:07 +00:00
) ;
2012-11-26 18:58:24 +00:00
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( r_showDynamic . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " callback:%i md5:%i dfrmVerts:%i dfrmTris:%i tangTris:%i guis:%i \n " ,
2017-09-03 21:17:44 +00:00
pc . c_entityDefCallbacks ,
pc . c_generateMd5 ,
pc . c_deformedVerts ,
pc . c_deformedIndexes / 3 ,
pc . c_tangentIndexes / 3 ,
pc . c_guiSurfs
2012-11-28 15:47:07 +00:00
) ;
2012-11-26 18:58:24 +00:00
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( r_showCull . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " %i box in %i box out \n " ,
2017-09-03 21:17:44 +00:00
pc . c_box_cull_in , pc . c_box_cull_out ) ;
2012-11-26 18:58:24 +00:00
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( r_showAddModel . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " callback:%i createInteractions:%i createShadowVolumes:%i \n " ,
2017-09-03 21:17:44 +00:00
pc . c_entityDefCallbacks , pc . c_createInteractions , pc . c_createShadowVolumes ) ;
common - > Printf ( " viewEntities:%i shadowEntities:%i viewLights:%i \n " , pc . c_visibleViewEntities ,
pc . c_shadowViewEntities , pc . c_viewLights ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( r_showUpdates . GetBool ( ) )
{
common - > Printf ( " entityUpdates:%i entityRefs:%i lightUpdates:%i lightRefs:%i \n " ,
2017-09-03 21:17:44 +00:00
pc . c_entityUpdates , pc . c_entityReferences ,
pc . c_lightUpdates , pc . c_lightReferences ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( r_showMemory . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " frameData: %i (%i) \n " , frameData - > frameMemoryAllocated . GetValue ( ) , frameData - > highWaterAllocated ) ;
}
2019-11-11 19:27:44 +00:00
2017-09-03 21:17:44 +00:00
memset ( & pc , 0 , sizeof ( pc ) ) ;
memset ( & backend . pc , 0 , sizeof ( backend . pc ) ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = =
RenderCommandBuffers
= = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : RenderCommandBuffers ( const emptyCommand_t * const cmdHead )
{
2012-11-26 18:58:24 +00:00
// if there isn't a draw view command, do nothing to avoid swapping a bad frame
bool hasView = false ;
2012-11-28 15:47:07 +00:00
for ( const emptyCommand_t * cmd = cmdHead ; cmd ; cmd = ( const emptyCommand_t * ) cmd - > next )
{
if ( cmd - > commandId = = RC_DRAW_VIEW_3D | | cmd - > commandId = = RC_DRAW_VIEW_GUI )
{
2012-11-26 18:58:24 +00:00
hasView = true ;
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( ! hasView )
{
2012-11-26 18:58:24 +00:00
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// r_skipBackEnd allows the entire time of the back end
// to be removed from performance measurements, although
// nothing will be drawn to the screen. If the prints
// are going to a file, or r_skipBackEnd is later disabled,
// usefull data can be received.
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// r_skipRender is usually more usefull, because it will still
// draw 2D graphics
2012-11-28 15:47:07 +00:00
if ( ! r_skipBackEnd . GetBool ( ) )
{
2021-04-19 18:31:15 +00:00
// SRS - For OSX skip total rendering time query due to missing GL_TIMESTAMP support in Apple OpenGL 4.1, will calculate it inside SwapCommandBuffers_FinishRendering instead
# if !defined(USE_VULKAN) && !defined(__APPLE__)
2012-11-28 15:47:07 +00:00
if ( glConfig . timerQueryAvailable )
{
2020-05-09 14:48:55 +00:00
if ( glcontext . renderLogMainBlockTimeQueryIds [ glcontext . frameParity ] [ MRB_GPU_TIME ] = = 0 )
2012-11-28 15:47:07 +00:00
{
2020-05-09 14:48:55 +00:00
glCreateQueries ( GL_TIMESTAMP , 2 , & glcontext . renderLogMainBlockTimeQueryIds [ glcontext . frameParity ] [ MRB_GPU_TIME ] ) ;
2012-11-26 18:58:24 +00:00
}
2020-05-09 14:48:55 +00:00
glQueryCounter ( glcontext . renderLogMainBlockTimeQueryIds [ glcontext . frameParity ] [ MRB_GPU_TIME * 2 + 0 ] , GL_TIMESTAMP ) ;
2017-09-09 12:57:48 +00:00
backend . ExecuteBackEndCommands ( cmdHead ) ;
2020-05-09 14:48:55 +00:00
glQueryCounter ( glcontext . renderLogMainBlockTimeQueryIds [ glcontext . frameParity ] [ MRB_GPU_TIME * 2 + 1 ] , GL_TIMESTAMP ) ;
glcontext . renderLogMainBlockTimeQueryIssued [ glcontext . frameParity ] [ MRB_GPU_TIME * 2 + 1 ] + + ;
2012-12-17 16:30:59 +00:00
glFlush ( ) ;
2012-11-28 15:47:07 +00:00
}
else
2014-08-20 09:09:02 +00:00
# endif
2012-11-28 15:47:07 +00:00
{
2017-09-09 12:57:48 +00:00
backend . ExecuteBackEndCommands ( cmdHead ) ;
2012-11-26 18:58:24 +00:00
}
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// pass in null for now - we may need to do some map specific hackery in the future
resolutionScale . InitForMap ( NULL ) ;
}
/*
= = = = = = = = = = = =
R_GetCommandBuffer
2012-11-28 15:47:07 +00:00
Returns memory for a command buffer ( stretchPicCommand_t ,
2012-11-26 18:58:24 +00:00
drawSurfsCommand_t , etc ) and links it to the end of the
current command chain .
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void * R_GetCommandBuffer ( int bytes )
{
emptyCommand_t * cmd ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
cmd = ( emptyCommand_t * ) R_FrameAlloc ( bytes , FRAME_ALLOC_DRAW_COMMAND ) ;
2012-11-26 18:58:24 +00:00
cmd - > next = NULL ;
frameData - > cmdTail - > next = & cmd - > commandId ;
frameData - > cmdTail = cmd ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
return ( void * ) cmd ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = =
R_ViewStatistics
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
static void R_ViewStatistics ( viewDef_t * parms )
{
2012-11-26 18:58:24 +00:00
// report statistics about this view
2012-11-28 15:47:07 +00:00
if ( ! r_showSurfaces . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
common - > Printf ( " view:%p surfs:%i \n " , parms , parms - > numDrawSurfs ) ;
}
/*
= = = = = = = = = = = = =
R_AddDrawViewCmd
This is the main 3 D rendering command . A single scene may
have multiple views if a mirror , portal , or dynamic texture is present .
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void R_AddDrawViewCmd ( viewDef_t * parms , bool guiOnly )
{
drawSurfsCommand_t * cmd ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
cmd = ( drawSurfsCommand_t * ) R_GetCommandBuffer ( sizeof ( * cmd ) ) ;
2012-11-26 18:58:24 +00:00
cmd - > commandId = ( guiOnly ) ? RC_DRAW_VIEW_GUI : RC_DRAW_VIEW_3D ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
cmd - > viewDef = parms ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
tr . pc . c_numViews + + ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
R_ViewStatistics ( parms ) ;
}
/*
= = = = = = = = = = = = =
R_AddPostProcess
This issues the command to do a post process after all the views have
been rendered .
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void R_AddDrawPostProcess ( viewDef_t * parms )
{
postProcessCommand_t * cmd = ( postProcessCommand_t * ) R_GetCommandBuffer ( sizeof ( * cmd ) ) ;
2012-11-26 18:58:24 +00:00
cmd - > commandId = RC_POST_PROCESS ;
cmd - > viewDef = parms ;
}
//=================================================================================
/*
= = = = = = = = = = = = =
idRenderSystemLocal : : idRenderSystemLocal
= = = = = = = = = = = = =
*/
idRenderSystemLocal : : idRenderSystemLocal ( ) :
unitSquareTriangles ( NULL ) ,
zeroOneCubeTriangles ( NULL ) ,
2020-05-20 16:24:45 +00:00
zeroOneSphereTriangles ( NULL ) ,
2018-10-05 19:43:55 +00:00
testImageTriangles ( NULL ) ,
bInitialized ( false )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
Clear ( ) ;
}
/*
= = = = = = = = = = = = =
idRenderSystemLocal : : ~ idRenderSystemLocal
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idRenderSystemLocal : : ~ idRenderSystemLocal ( )
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = =
idRenderSystemLocal : : SetColor
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : SetColor ( const idVec4 & rgba )
{
2012-11-26 18:58:24 +00:00
currentColorNativeBytesOrder = LittleLong ( PackColor ( rgba ) ) ;
}
/*
= = = = = = = = = = = = =
idRenderSystemLocal : : GetColor
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
uint32 idRenderSystemLocal : : GetColor ( )
{
2012-11-26 18:58:24 +00:00
return LittleLong ( currentColorNativeBytesOrder ) ;
}
/*
= = = = = = = = = = = = =
idRenderSystemLocal : : SetGLState
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : SetGLState ( const uint64 glState )
{
2012-11-26 18:58:24 +00:00
currentGLState = glState ;
}
/*
= = = = = = = = = = = = =
idRenderSystemLocal : : DrawFilled
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : DrawFilled ( const idVec4 & color , float x , float y , float w , float h )
{
2012-11-26 18:58:24 +00:00
SetColor ( color ) ;
DrawStretchPic ( x , y , w , h , 0.0f , 0.0f , 1.0f , 1.0f , whiteMaterial ) ;
}
/*
= = = = = = = = = = = = =
idRenderSystemLocal : : DrawStretchPic
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : DrawStretchPic ( float x , float y , float w , float h , float s1 , float t1 , float s2 , float t2 , const idMaterial * material )
{
DrawStretchPic ( idVec4 ( x , y , s1 , t1 ) , idVec4 ( x + w , y , s2 , t1 ) , idVec4 ( x + w , y + h , s2 , t2 ) , idVec4 ( x , y + h , s1 , t2 ) , material ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = =
idRenderSystemLocal : : DrawStretchPic
= = = = = = = = = = = = =
*/
static triIndex_t quadPicIndexes [ 6 ] = { 3 , 0 , 2 , 2 , 0 , 1 } ;
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : DrawStretchPic ( const idVec4 & topLeft , const idVec4 & topRight , const idVec4 & bottomRight , const idVec4 & bottomLeft , const idMaterial * material )
{
2018-10-05 19:43:55 +00:00
if ( ! IsInitialized ( ) )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( material = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
idDrawVert * verts = guiModel - > AllocTris ( 4 , quadPicIndexes , 6 , material , currentGLState , STEREO_DEPTH_TYPE_NONE ) ;
if ( verts = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
ALIGNTYPE16 idDrawVert localVerts [ 4 ] ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
localVerts [ 0 ] . Clear ( ) ;
localVerts [ 0 ] . xyz [ 0 ] = topLeft . x ;
localVerts [ 0 ] . xyz [ 1 ] = topLeft . y ;
localVerts [ 0 ] . SetTexCoord ( topLeft . z , topLeft . w ) ;
localVerts [ 0 ] . SetNativeOrderColor ( currentColorNativeBytesOrder ) ;
localVerts [ 0 ] . ClearColor2 ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
localVerts [ 1 ] . Clear ( ) ;
localVerts [ 1 ] . xyz [ 0 ] = topRight . x ;
localVerts [ 1 ] . xyz [ 1 ] = topRight . y ;
localVerts [ 1 ] . SetTexCoord ( topRight . z , topRight . w ) ;
localVerts [ 1 ] . SetNativeOrderColor ( currentColorNativeBytesOrder ) ;
localVerts [ 1 ] . ClearColor2 ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
localVerts [ 2 ] . Clear ( ) ;
localVerts [ 2 ] . xyz [ 0 ] = bottomRight . x ;
localVerts [ 2 ] . xyz [ 1 ] = bottomRight . y ;
localVerts [ 2 ] . SetTexCoord ( bottomRight . z , bottomRight . w ) ;
localVerts [ 2 ] . SetNativeOrderColor ( currentColorNativeBytesOrder ) ;
localVerts [ 2 ] . ClearColor2 ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
localVerts [ 3 ] . Clear ( ) ;
localVerts [ 3 ] . xyz [ 0 ] = bottomLeft . x ;
localVerts [ 3 ] . xyz [ 1 ] = bottomLeft . y ;
localVerts [ 3 ] . SetTexCoord ( bottomLeft . z , bottomLeft . w ) ;
localVerts [ 3 ] . SetNativeOrderColor ( currentColorNativeBytesOrder ) ;
localVerts [ 3 ] . ClearColor2 ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
WriteDrawVerts16 ( verts , localVerts , 4 ) ;
}
/*
= = = = = = = = = = = = =
idRenderSystemLocal : : DrawStretchTri
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : DrawStretchTri ( const idVec2 & p1 , const idVec2 & p2 , const idVec2 & p3 , const idVec2 & t1 , const idVec2 & t2 , const idVec2 & t3 , const idMaterial * material )
{
2018-10-05 19:43:55 +00:00
if ( ! IsInitialized ( ) )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( material = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
triIndex_t tempIndexes [ 3 ] = { 1 , 0 , 2 } ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
idDrawVert * verts = guiModel - > AllocTris ( 3 , tempIndexes , 3 , material , currentGLState , STEREO_DEPTH_TYPE_NONE ) ;
if ( verts = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
ALIGNTYPE16 idDrawVert localVerts [ 3 ] ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
localVerts [ 0 ] . Clear ( ) ;
localVerts [ 0 ] . xyz [ 0 ] = p1 . x ;
localVerts [ 0 ] . xyz [ 1 ] = p1 . y ;
localVerts [ 0 ] . SetTexCoord ( t1 ) ;
localVerts [ 0 ] . SetNativeOrderColor ( currentColorNativeBytesOrder ) ;
localVerts [ 0 ] . ClearColor2 ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
localVerts [ 1 ] . Clear ( ) ;
localVerts [ 1 ] . xyz [ 0 ] = p2 . x ;
localVerts [ 1 ] . xyz [ 1 ] = p2 . y ;
localVerts [ 1 ] . SetTexCoord ( t2 ) ;
localVerts [ 1 ] . SetNativeOrderColor ( currentColorNativeBytesOrder ) ;
localVerts [ 1 ] . ClearColor2 ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
localVerts [ 2 ] . Clear ( ) ;
localVerts [ 2 ] . xyz [ 0 ] = p3 . x ;
localVerts [ 2 ] . xyz [ 1 ] = p3 . y ;
localVerts [ 2 ] . SetTexCoord ( t3 ) ;
localVerts [ 2 ] . SetNativeOrderColor ( currentColorNativeBytesOrder ) ;
localVerts [ 2 ] . ClearColor2 ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
WriteDrawVerts16 ( verts , localVerts , 3 ) ;
}
/*
= = = = = = = = = = = = =
idRenderSystemLocal : : AllocTris
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idDrawVert * idRenderSystemLocal : : AllocTris ( int numVerts , const triIndex_t * indexes , int numIndexes , const idMaterial * material , const stereoDepthType_t stereoType )
{
2012-11-26 18:58:24 +00:00
return guiModel - > AllocTris ( numVerts , indexes , numIndexes , material , currentGLState , stereoType ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idRenderSystemLocal : : DrawSmallChar
small chars are drawn at native screen resolution
= = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : DrawSmallChar ( int x , int y , int ch )
{
2012-11-26 18:58:24 +00:00
int row , col ;
float frow , fcol ;
float size ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
ch & = 255 ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( ch = = ' ' )
{
2012-11-26 18:58:24 +00:00
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( y < - SMALLCHAR_HEIGHT )
{
2012-11-26 18:58:24 +00:00
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
row = ch > > 4 ;
col = ch & 15 ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
frow = row * 0.0625f ;
fcol = col * 0.0625f ;
size = 0.0625f ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
DrawStretchPic ( x , y , SMALLCHAR_WIDTH , SMALLCHAR_HEIGHT ,
2012-11-28 15:47:07 +00:00
fcol , frow ,
fcol + size , frow + size ,
charSetMaterial ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
idRenderSystemLocal : : DrawSmallStringExt
Draws a multi - colored string with a drop shadow , optionally forcing
to a fixed color .
Coordinates are at 640 by 480 virtual resolution
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : DrawSmallStringExt ( int x , int y , const char * string , const idVec4 & setColor , bool forceColor )
{
2012-11-26 18:58:24 +00:00
idVec4 color ;
2012-11-28 15:47:07 +00:00
const unsigned char * s ;
2012-11-26 18:58:24 +00:00
int xx ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// draw the colored text
2012-11-28 15:47:07 +00:00
s = ( const unsigned char * ) string ;
2012-11-26 18:58:24 +00:00
xx = x ;
SetColor ( setColor ) ;
2012-11-28 15:47:07 +00:00
while ( * s )
{
if ( idStr : : IsColor ( ( const char * ) s ) )
{
if ( ! forceColor )
{
if ( * ( s + 1 ) = = C_COLOR_DEFAULT )
{
2012-11-26 18:58:24 +00:00
SetColor ( setColor ) ;
2012-11-28 15:47:07 +00:00
}
else
{
color = idStr : : ColorForIndex ( * ( s + 1 ) ) ;
2012-11-26 18:58:24 +00:00
color [ 3 ] = setColor [ 3 ] ;
SetColor ( color ) ;
}
}
s + = 2 ;
continue ;
}
DrawSmallChar ( xx , y , * s ) ;
xx + = SMALLCHAR_WIDTH ;
s + + ;
}
SetColor ( colorWhite ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idRenderSystemLocal : : DrawBigChar
= = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : DrawBigChar ( int x , int y , int ch )
{
2012-11-26 18:58:24 +00:00
int row , col ;
float frow , fcol ;
float size ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
ch & = 255 ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( ch = = ' ' )
{
2012-11-26 18:58:24 +00:00
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( y < - BIGCHAR_HEIGHT )
{
2012-11-26 18:58:24 +00:00
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
row = ch > > 4 ;
col = ch & 15 ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
frow = row * 0.0625f ;
fcol = col * 0.0625f ;
size = 0.0625f ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
DrawStretchPic ( x , y , BIGCHAR_WIDTH , BIGCHAR_HEIGHT ,
2012-11-28 15:47:07 +00:00
fcol , frow ,
fcol + size , frow + size ,
charSetMaterial ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
idRenderSystemLocal : : DrawBigStringExt
Draws a multi - colored string with a drop shadow , optionally forcing
to a fixed color .
Coordinates are at 640 by 480 virtual resolution
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : DrawBigStringExt ( int x , int y , const char * string , const idVec4 & setColor , bool forceColor )
{
2012-11-26 18:58:24 +00:00
idVec4 color ;
2012-11-28 15:47:07 +00:00
const char * s ;
2012-11-26 18:58:24 +00:00
int xx ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// draw the colored text
s = string ;
xx = x ;
SetColor ( setColor ) ;
2012-11-28 15:47:07 +00:00
while ( * s )
{
if ( idStr : : IsColor ( s ) )
{
if ( ! forceColor )
{
if ( * ( s + 1 ) = = C_COLOR_DEFAULT )
{
2012-11-26 18:58:24 +00:00
SetColor ( setColor ) ;
2012-11-28 15:47:07 +00:00
}
else
{
color = idStr : : ColorForIndex ( * ( s + 1 ) ) ;
2012-11-26 18:58:24 +00:00
color [ 3 ] = setColor [ 3 ] ;
SetColor ( color ) ;
}
}
s + = 2 ;
continue ;
}
DrawBigChar ( xx , y , * s ) ;
xx + = BIGCHAR_WIDTH ;
s + + ;
}
SetColor ( colorWhite ) ;
}
//======================================================================================
/*
= = = = = = = = = = = = = = = = = = = =
idRenderSystemLocal : : SwapCommandBuffers
Performs final closeout of any gui models being defined .
Waits for the previous GPU rendering to complete and vsync .
Returns the head of the linked command list that was just closed off .
Returns timing information from the previous frame .
After this is called , new command buffers can be built up in parallel
with the rendering of the closed off command buffers by RenderCommandBuffers ( )
= = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const emptyCommand_t * idRenderSystemLocal : : SwapCommandBuffers (
uint64 * frontEndMicroSec ,
uint64 * backEndMicroSec ,
uint64 * shadowMicroSec ,
2020-03-29 15:12:11 +00:00
uint64 * gpuMicroSec ,
backEndCounters_t * bc ,
performanceCounters_t * pc
)
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
2020-03-29 15:12:11 +00:00
SwapCommandBuffers_FinishRendering ( frontEndMicroSec , backEndMicroSec , shadowMicroSec , gpuMicroSec , bc , pc ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
return SwapCommandBuffers_FinishCommandBuffers ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idRenderSystemLocal : : SwapCommandBuffers_FinishRendering
= = = = = = = = = = = = = = = = = = = = =
*/
2020-03-29 15:12:11 +00:00
# define FPS_FRAMES 6
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : SwapCommandBuffers_FinishRendering (
uint64 * frontEndMicroSec ,
uint64 * backEndMicroSec ,
uint64 * shadowMicroSec ,
2020-03-29 15:12:11 +00:00
uint64 * gpuMicroSec ,
backEndCounters_t * bc ,
performanceCounters_t * pc
)
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
SCOPED_PROFILE_EVENT ( " SwapCommandBuffers " ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( gpuMicroSec ! = NULL )
{
2012-11-26 18:58:24 +00:00
* gpuMicroSec = 0 ; // until shown otherwise
}
2019-11-11 19:27:44 +00:00
2018-10-05 19:43:55 +00:00
if ( ! IsInitialized ( ) )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
return ;
}
2019-11-11 19:27:44 +00:00
2020-07-14 16:35:00 +00:00
//GL_CheckErrors();
2012-11-26 18:58:24 +00:00
// After coming back from an autoswap, we won't have anything to render
2018-10-06 15:21:49 +00:00
//if( frameData && frameData->cmdHead->next != NULL )
2021-05-01 13:59:46 +00:00
// keep capturing envprobes completely in the background
// and only update the screen when we update the progress bar in the console
if ( ! takingEnvprobe )
2012-11-28 15:47:07 +00:00
{
2021-05-06 11:31:58 +00:00
# if !IMGUI_BFGUI
2016-02-07 16:19:07 +00:00
ImGuiHook : : Render ( ) ;
2020-05-04 15:22:51 +00:00
# endif
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// wait for our fence to hit, which means the swap has actually happened
// We must do this before clearing any resources the GPU may be using
2018-10-06 15:21:49 +00:00
backend . GL_BlockingSwapBuffers ( ) ;
2012-11-26 18:58:24 +00:00
}
2019-11-11 19:27:44 +00:00
2020-05-04 23:21:29 +00:00
# if defined(USE_VULKAN)
if ( gpuMicroSec ! = NULL )
{
* gpuMicroSec = backend . pc . gpuMicroSec ;
}
# else
2012-11-26 18:58:24 +00:00
// read back the start and end timer queries from the previous frame
2012-11-28 15:47:07 +00:00
if ( glConfig . timerQueryAvailable )
{
2020-05-09 14:48:55 +00:00
GLuint64EXT gpuStartNanoseconds = 0 ;
GLuint64EXT gpuEndNanoseconds = 0 ;
if ( glcontext . renderLogMainBlockTimeQueryIssued [ glcontext . frameParity ^ 1 ] [ MRB_GPU_TIME * 2 + 1 ] > 0 )
{
glGetQueryObjectui64vEXT ( glcontext . renderLogMainBlockTimeQueryIds [ glcontext . frameParity ^ 1 ] [ MRB_GPU_TIME * 2 + 0 ] , GL_QUERY_RESULT , & gpuStartNanoseconds ) ;
glGetQueryObjectui64vEXT ( glcontext . renderLogMainBlockTimeQueryIds [ glcontext . frameParity ^ 1 ] [ MRB_GPU_TIME * 2 + 1 ] , GL_QUERY_RESULT , & gpuEndNanoseconds ) ;
backend . pc . gpuMicroSec = ( gpuEndNanoseconds - gpuStartNanoseconds ) / 1000 ;
if ( gpuMicroSec ! = NULL )
{
* gpuMicroSec = backend . pc . gpuMicroSec ;
}
}
if ( glcontext . renderLogMainBlockTimeQueryIssued [ glcontext . frameParity ^ 1 ] [ MRB_FILL_DEPTH_BUFFER * 2 + 1 ] > 0 )
{
glGetQueryObjectui64vEXT ( glcontext . renderLogMainBlockTimeQueryIds [ glcontext . frameParity ^ 1 ] [ MRB_FILL_DEPTH_BUFFER * 2 + 0 ] , GL_QUERY_RESULT , & gpuStartNanoseconds ) ;
glGetQueryObjectui64vEXT ( glcontext . renderLogMainBlockTimeQueryIds [ glcontext . frameParity ^ 1 ] [ MRB_FILL_DEPTH_BUFFER * 2 + 1 ] , GL_QUERY_RESULT , & gpuEndNanoseconds ) ;
2019-11-11 19:27:44 +00:00
2020-05-09 14:48:55 +00:00
backend . pc . gpuDepthMicroSec = ( gpuEndNanoseconds - gpuStartNanoseconds ) / 1000 ;
}
if ( glcontext . renderLogMainBlockTimeQueryIssued [ glcontext . frameParity ^ 1 ] [ MRB_SSAO_PASS * 2 + 1 ] > 0 )
2012-11-28 15:47:07 +00:00
{
2020-05-09 14:48:55 +00:00
glGetQueryObjectui64vEXT ( glcontext . renderLogMainBlockTimeQueryIds [ glcontext . frameParity ^ 1 ] [ MRB_SSAO_PASS * 2 + 0 ] , GL_QUERY_RESULT , & gpuStartNanoseconds ) ;
glGetQueryObjectui64vEXT ( glcontext . renderLogMainBlockTimeQueryIds [ glcontext . frameParity ^ 1 ] [ MRB_SSAO_PASS * 2 + 1 ] , GL_QUERY_RESULT , & gpuEndNanoseconds ) ;
backend . pc . gpuScreenSpaceAmbientOcclusionMicroSec = ( gpuEndNanoseconds - gpuStartNanoseconds ) / 1000 ;
}
if ( glcontext . renderLogMainBlockTimeQueryIssued [ glcontext . frameParity ^ 1 ] [ MRB_AMBIENT_PASS * 2 + 1 ] > 0 )
{
glGetQueryObjectui64vEXT ( glcontext . renderLogMainBlockTimeQueryIds [ glcontext . frameParity ^ 1 ] [ MRB_AMBIENT_PASS * 2 + 0 ] , GL_QUERY_RESULT , & gpuStartNanoseconds ) ;
glGetQueryObjectui64vEXT ( glcontext . renderLogMainBlockTimeQueryIds [ glcontext . frameParity ^ 1 ] [ MRB_AMBIENT_PASS * 2 + 1 ] , GL_QUERY_RESULT , & gpuEndNanoseconds ) ;
backend . pc . gpuAmbientPassMicroSec = ( gpuEndNanoseconds - gpuStartNanoseconds ) / 1000 ;
}
if ( glcontext . renderLogMainBlockTimeQueryIssued [ glcontext . frameParity ^ 1 ] [ MRB_DRAW_INTERACTIONS * 2 + 1 ] > 0 )
{
glGetQueryObjectui64vEXT ( glcontext . renderLogMainBlockTimeQueryIds [ glcontext . frameParity ^ 1 ] [ MRB_DRAW_INTERACTIONS * 2 + 0 ] , GL_QUERY_RESULT , & gpuStartNanoseconds ) ;
glGetQueryObjectui64vEXT ( glcontext . renderLogMainBlockTimeQueryIds [ glcontext . frameParity ^ 1 ] [ MRB_DRAW_INTERACTIONS * 2 + 1 ] , GL_QUERY_RESULT , & gpuEndNanoseconds ) ;
backend . pc . gpuInteractionsMicroSec = ( gpuEndNanoseconds - gpuStartNanoseconds ) / 1000 ;
}
if ( glcontext . renderLogMainBlockTimeQueryIssued [ glcontext . frameParity ^ 1 ] [ MRB_DRAW_SHADER_PASSES * 2 + 1 ] > 0 )
{
glGetQueryObjectui64vEXT ( glcontext . renderLogMainBlockTimeQueryIds [ glcontext . frameParity ^ 1 ] [ MRB_DRAW_SHADER_PASSES * 2 + 0 ] , GL_QUERY_RESULT , & gpuStartNanoseconds ) ;
glGetQueryObjectui64vEXT ( glcontext . renderLogMainBlockTimeQueryIds [ glcontext . frameParity ^ 1 ] [ MRB_DRAW_SHADER_PASSES * 2 + 1 ] , GL_QUERY_RESULT , & gpuEndNanoseconds ) ;
backend . pc . gpuShaderPassMicroSec = ( gpuEndNanoseconds - gpuStartNanoseconds ) / 1000 ;
}
if ( glcontext . renderLogMainBlockTimeQueryIssued [ glcontext . frameParity ^ 1 ] [ MRB_POSTPROCESS * 2 + 1 ] > 0 )
{
glGetQueryObjectui64vEXT ( glcontext . renderLogMainBlockTimeQueryIds [ glcontext . frameParity ^ 1 ] [ MRB_POSTPROCESS * 2 + 0 ] , GL_QUERY_RESULT , & gpuStartNanoseconds ) ;
glGetQueryObjectui64vEXT ( glcontext . renderLogMainBlockTimeQueryIds [ glcontext . frameParity ^ 1 ] [ MRB_POSTPROCESS * 2 + 1 ] , GL_QUERY_RESULT , & gpuEndNanoseconds ) ;
backend . pc . gpuPostProcessingMicroSec = ( gpuEndNanoseconds - gpuStartNanoseconds ) / 1000 ;
2012-11-26 18:58:24 +00:00
}
2021-04-29 13:20:45 +00:00
2021-04-19 18:31:15 +00:00
// SRS - For OSX OpenGL calculate total rendering time vs direct measurement due to missing GL_TIMESTAMP support in Apple OpenGL 4.1
# if defined(__APPLE__)
2021-04-29 13:20:45 +00:00
backend . pc . gpuMicroSec = backend . pc . gpuDepthMicroSec + backend . pc . gpuScreenSpaceAmbientOcclusionMicroSec + backend . pc . gpuAmbientPassMicroSec + backend . pc . gpuInteractionsMicroSec + backend . pc . gpuShaderPassMicroSec + backend . pc . gpuPostProcessingMicroSec + commonLocal . GetRendererIdleMicroseconds ( ) ;
if ( gpuMicroSec ! = NULL )
{
* gpuMicroSec = backend . pc . gpuMicroSec ;
}
2021-04-19 18:31:15 +00:00
# endif
2020-05-04 23:21:29 +00:00
2020-05-09 14:48:55 +00:00
for ( int i = 0 ; i < MRB_TOTAL_QUERIES ; i + + )
2012-11-28 15:47:07 +00:00
{
2020-05-09 14:48:55 +00:00
glcontext . renderLogMainBlockTimeQueryIssued [ glcontext . frameParity ^ 1 ] [ i ] = 0 ;
2012-11-26 18:58:24 +00:00
}
}
2018-10-03 19:14:28 +00:00
# endif
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
//------------------------------
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// save out timing information
2012-11-28 15:47:07 +00:00
if ( frontEndMicroSec ! = NULL )
{
2020-03-29 15:12:11 +00:00
* frontEndMicroSec = this - > pc . frontEndMicroSec ;
2012-11-26 18:58:24 +00:00
}
2020-03-29 15:12:11 +00:00
2012-11-28 15:47:07 +00:00
if ( backEndMicroSec ! = NULL )
{
2020-05-04 23:21:29 +00:00
* backEndMicroSec = backend . pc . cpuTotalMicroSec ;
2012-11-26 18:58:24 +00:00
}
2020-03-29 15:12:11 +00:00
2012-11-28 15:47:07 +00:00
if ( shadowMicroSec ! = NULL )
{
2020-05-04 23:21:29 +00:00
* shadowMicroSec = backend . pc . cpuShadowMicroSec ;
2012-11-26 18:58:24 +00:00
}
2019-11-11 19:27:44 +00:00
2020-03-29 15:12:11 +00:00
// RB: TODO clean up the above and just pass entire backend and performance stats before they get cleared
if ( bc ! = NULL )
{
* bc = backend . pc ;
}
if ( pc ! = NULL )
{
* pc = this - > pc ;
}
2012-11-26 18:58:24 +00:00
// print any other statistics and clear all of them
2017-09-03 21:17:44 +00:00
PrintPerformanceCounters ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// check for dynamic changes that require some initialization
2017-09-10 11:32:44 +00:00
backend . CheckCVars ( ) ;
2019-11-11 19:27:44 +00:00
2015-12-20 11:28:46 +00:00
// RB: resize HDR buffers
Framebuffer : : CheckFramebuffers ( ) ;
// RB end
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// check for errors
2012-11-26 18:58:24 +00:00
GL_CheckErrors ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idRenderSystemLocal : : SwapCommandBuffers_FinishCommandBuffers
= = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const emptyCommand_t * idRenderSystemLocal : : SwapCommandBuffers_FinishCommandBuffers ( )
{
2018-10-05 19:43:55 +00:00
if ( ! IsInitialized ( ) )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
return NULL ;
}
2019-11-11 19:27:44 +00:00
2020-05-04 15:22:51 +00:00
// RB: general GUI system path to treat ImGui surfaces in the renderer frontend like SWF
// this calls io.RenderDrawListsFn
2021-05-06 11:31:58 +00:00
# if IMGUI_BFGUI
2020-05-04 15:22:51 +00:00
ImGuiHook : : Render ( ) ;
# endif
2012-11-26 18:58:24 +00:00
// close any gui drawing
guiModel - > EmitFullScreen ( ) ;
guiModel - > Clear ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// unmap the buffer objects so they can be used by the GPU
vertexCache . BeginBackEnd ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// save off this command buffer
2012-11-28 15:47:07 +00:00
const emptyCommand_t * commandBufferHead = frameData - > cmdHead ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// copy the code-used drawsurfs that were
// allocated at the start of the buffer memory to the backEnd referenced locations
2017-09-03 21:17:44 +00:00
backend . unitSquareSurface = tr . unitSquareSurface_ ;
backend . zeroOneCubeSurface = tr . zeroOneCubeSurface_ ;
2020-05-20 16:24:45 +00:00
backend . zeroOneSphereSurface = tr . zeroOneSphereSurface_ ;
2017-09-03 21:17:44 +00:00
backend . testImageSurface = tr . testImageSurface_ ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// use the other buffers next frame, because another CPU
// may still be rendering into the current buffers
R_ToggleSmpFrame ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// possibly change the stereo3D mode
// PC
2016-10-24 22:58:43 +00:00
UpdateStereo3DMode ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// prepare the new command buffer
guiModel - > BeginFrame ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
//------------------------------
// Make sure that geometry used by code is present in the buffer cache.
// These use frame buffer cache (not static) because they may be used during
// map loads.
//
// It is important to do this first, so if the buffers overflow during
// scene generation, the basic surfaces needed for drawing the buffers will
// always be present.
//------------------------------
R_InitDrawSurfFromTri ( tr . unitSquareSurface_ , * tr . unitSquareTriangles ) ;
R_InitDrawSurfFromTri ( tr . zeroOneCubeSurface_ , * tr . zeroOneCubeTriangles ) ;
2020-05-20 16:24:45 +00:00
R_InitDrawSurfFromTri ( tr . zeroOneSphereSurface_ , * tr . zeroOneSphereTriangles ) ;
2012-11-26 18:58:24 +00:00
R_InitDrawSurfFromTri ( tr . testImageSurface_ , * tr . testImageTriangles ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// Reset render crop to be the full screen
renderCrops [ 0 ] . x1 = 0 ;
renderCrops [ 0 ] . y1 = 0 ;
renderCrops [ 0 ] . x2 = GetWidth ( ) - 1 ;
renderCrops [ 0 ] . y2 = GetHeight ( ) - 1 ;
currentRenderCrop = 0 ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// this is the ONLY place this is modified
frameCount + + ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// just in case we did a common->Error while this
// was set
guiRecursionLevel = 0 ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// the first rendering will be used for commands like
// screenshot, rather than a possible subsequent remote
// or mirror render
// primaryWorld = NULL;
// set the time for shader effects in 2D rendering
frameShaderTime = Sys_Milliseconds ( ) * 0.001 ;
2019-11-11 19:27:44 +00:00
2018-11-02 10:00:05 +00:00
# if 1 //!defined(USE_VULKAN)
2018-10-03 19:14:28 +00:00
// RB: TODO RC_SET_BUFFER is not handled in OpenGL
2012-11-28 15:47:07 +00:00
setBufferCommand_t * cmd2 = ( setBufferCommand_t * ) R_GetCommandBuffer ( sizeof ( * cmd2 ) ) ;
2012-11-26 18:58:24 +00:00
cmd2 - > commandId = RC_SET_BUFFER ;
2019-11-11 19:27:44 +00:00
2018-11-02 10:00:05 +00:00
# if defined(USE_VULKAN)
cmd2 - > buffer = 0 ;
# else
2012-11-28 15:47:07 +00:00
cmd2 - > buffer = ( int ) GL_BACK ;
2018-11-02 10:00:05 +00:00
# endif
2019-11-11 19:27:44 +00:00
2018-10-03 19:14:28 +00:00
# endif
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// the old command buffer can now be rendered, while the new one can
// be built in parallel
return commandBufferHead ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idRenderSystemLocal : : WriteDemoPics
= = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : WriteDemoPics ( )
{
2012-11-26 18:58:24 +00:00
common - > WriteDemo ( ) - > WriteInt ( DS_RENDER ) ;
common - > WriteDemo ( ) - > WriteInt ( DC_GUI_MODEL ) ;
}
2016-07-15 06:36:34 +00:00
/*
= = = = = = = = = = = = = = = = = = = = =
idRenderSystemLocal : : WriteEndFrame
= = = = = = = = = = = = = = = = = = = = =
*/
void idRenderSystemLocal : : WriteEndFrame ( )
{
common - > WriteDemo ( ) - > WriteInt ( DS_RENDER ) ;
common - > WriteDemo ( ) - > WriteInt ( DC_END_FRAME ) ;
}
2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = =
idRenderSystemLocal : : DrawDemoPics
= = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : DrawDemoPics ( )
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = =
idRenderSystemLocal : : GetCroppedViewport
Returns the current cropped pixel coordinates
= = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : GetCroppedViewport ( idScreenRect * viewport )
{
2012-11-26 18:58:24 +00:00
* viewport = renderCrops [ currentRenderCrop ] ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idRenderSystemLocal : : PerformResolutionScaling
The 3 D rendering size can be smaller than the full window resolution to reduce
fill rate requirements while still allowing the GUIs to be full resolution .
In split screen mode the rendering size is also smaller .
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : PerformResolutionScaling ( int & newWidth , int & newHeight )
{
2012-11-26 18:58:24 +00:00
float xScale = 1.0f ;
float yScale = 1.0f ;
resolutionScale . GetCurrentResolutionScale ( xScale , yScale ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
newWidth = idMath : : Ftoi ( GetWidth ( ) * xScale ) ;
newHeight = idMath : : Ftoi ( GetHeight ( ) * yScale ) ;
}
/*
= = = = = = = = = = = = = = = =
idRenderSystemLocal : : CropRenderSize
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : CropRenderSize ( int width , int height )
{
2018-10-05 19:43:55 +00:00
if ( ! IsInitialized ( ) )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// close any gui drawing before changing the size
guiModel - > EmitFullScreen ( ) ;
guiModel - > Clear ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( width < 1 | | height < 1 )
{
2012-11-26 18:58:24 +00:00
common - > Error ( " CropRenderSize: bad sizes " ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( common - > WriteDemo ( ) )
{
2012-11-26 18:58:24 +00:00
common - > WriteDemo ( ) - > WriteInt ( DS_RENDER ) ;
common - > WriteDemo ( ) - > WriteInt ( DC_CROP_RENDER ) ;
common - > WriteDemo ( ) - > WriteInt ( width ) ;
common - > WriteDemo ( ) - > WriteInt ( height ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( r_showDemo . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " write DC_CROP_RENDER \n " ) ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
idScreenRect & previous = renderCrops [ currentRenderCrop ] ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
currentRenderCrop + + ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
idScreenRect & current = renderCrops [ currentRenderCrop ] ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
current . x1 = previous . x1 ;
current . x2 = previous . x1 + width - 1 ;
current . y1 = previous . y2 - height + 1 ;
current . y2 = previous . y2 ;
}
/*
= = = = = = = = = = = = = = = =
idRenderSystemLocal : : UnCrop
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : UnCrop ( )
{
2018-10-05 19:43:55 +00:00
if ( ! IsInitialized ( ) )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( currentRenderCrop < 1 )
{
2012-11-26 18:58:24 +00:00
common - > Error ( " idRenderSystemLocal::UnCrop: currentRenderCrop < 1 " ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// close any gui drawing
guiModel - > EmitFullScreen ( ) ;
guiModel - > Clear ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
currentRenderCrop - - ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( common - > WriteDemo ( ) )
{
2012-11-26 18:58:24 +00:00
common - > WriteDemo ( ) - > WriteInt ( DS_RENDER ) ;
common - > WriteDemo ( ) - > WriteInt ( DC_UNCROP_RENDER ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( r_showDemo . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " write DC_UNCROP \n " ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idRenderSystemLocal : : CaptureRenderToImage
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : CaptureRenderToImage ( const char * imageName , bool clearColorAfterCopy )
{
2018-10-05 19:43:55 +00:00
if ( ! IsInitialized ( ) )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
return ;
}
guiModel - > EmitFullScreen ( ) ;
guiModel - > Clear ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( common - > WriteDemo ( ) )
{
2012-11-26 18:58:24 +00:00
common - > WriteDemo ( ) - > WriteInt ( DS_RENDER ) ;
common - > WriteDemo ( ) - > WriteInt ( DC_CAPTURE_RENDER ) ;
common - > WriteDemo ( ) - > WriteHashString ( imageName ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( r_showDemo . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " write DC_CAPTURE_RENDER: %s \n " , imageName ) ;
}
}
2020-05-16 15:40:30 +00:00
idImage * image = globalImages - > GetImage ( imageName ) ;
2012-11-28 15:47:07 +00:00
if ( image = = NULL )
{
2012-11-26 18:58:24 +00:00
image = globalImages - > AllocImage ( imageName ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
idScreenRect & rc = renderCrops [ currentRenderCrop ] ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
copyRenderCommand_t * cmd = ( copyRenderCommand_t * ) R_GetCommandBuffer ( sizeof ( * cmd ) ) ;
2012-11-26 18:58:24 +00:00
cmd - > commandId = RC_COPY_RENDER ;
cmd - > x = rc . x1 ;
cmd - > y = rc . y1 ;
cmd - > imageWidth = rc . GetWidth ( ) ;
cmd - > imageHeight = rc . GetHeight ( ) ;
cmd - > image = image ;
cmd - > clearColorAfterCopy = clearColorAfterCopy ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
guiModel - > Clear ( ) ;
}
/*
= = = = = = = = = = = = = =
idRenderSystemLocal : : CaptureRenderToFile
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : CaptureRenderToFile ( const char * fileName , bool fixAlpha )
{
2018-10-05 19:43:55 +00:00
if ( ! IsInitialized ( ) )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
idScreenRect & rc = renderCrops [ currentRenderCrop ] ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
guiModel - > EmitFullScreen ( ) ;
guiModel - > Clear ( ) ;
2020-05-16 15:40:30 +00:00
2012-11-26 18:58:24 +00:00
RenderCommandBuffers ( frameData - > cmdHead ) ;
2019-11-11 19:27:44 +00:00
2018-10-03 19:14:28 +00:00
# if !defined(USE_VULKAN)
2012-12-17 16:30:59 +00:00
glReadBuffer ( GL_BACK ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// include extra space for OpenGL padding to word boundaries
int c = ( rc . GetWidth ( ) + 3 ) * rc . GetHeight ( ) ;
2012-11-28 15:47:07 +00:00
byte * data = ( byte * ) R_StaticAlloc ( c * 3 ) ;
2019-11-11 19:27:44 +00:00
2012-12-17 16:30:59 +00:00
glReadPixels ( rc . x1 , rc . y1 , rc . GetWidth ( ) , rc . GetHeight ( ) , GL_RGB , GL_UNSIGNED_BYTE , data ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
byte * data2 = ( byte * ) R_StaticAlloc ( c * 4 ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < c ; i + + )
{
2012-11-26 18:58:24 +00:00
data2 [ i * 4 ] = data [ i * 3 ] ;
data2 [ i * 4 + 1 ] = data [ i * 3 + 1 ] ;
data2 [ i * 4 + 2 ] = data [ i * 3 + 2 ] ;
data2 [ i * 4 + 3 ] = 0xff ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
R_WriteTGA ( fileName , data2 , rc . GetWidth ( ) , rc . GetHeight ( ) , true ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
R_StaticFree ( data ) ;
R_StaticFree ( data2 ) ;
2018-10-03 19:14:28 +00:00
# endif
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = =
idRenderSystemLocal : : AllocRenderWorld
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idRenderWorld * idRenderSystemLocal : : AllocRenderWorld ( )
{
idRenderWorldLocal * rw ;
rw = new ( TAG_RENDER ) idRenderWorldLocal ;
2012-11-26 18:58:24 +00:00
worlds . Append ( rw ) ;
return rw ;
}
/*
= = = = = = = = = = = = = =
idRenderSystemLocal : : FreeRenderWorld
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : FreeRenderWorld ( idRenderWorld * rw )
{
if ( primaryWorld = = rw )
{
2012-11-26 18:58:24 +00:00
primaryWorld = NULL ;
}
2012-11-28 15:47:07 +00:00
worlds . Remove ( static_cast < idRenderWorldLocal * > ( rw ) ) ;
2012-11-26 18:58:24 +00:00
delete rw ;
}
/*
= = = = = = = = = = = = = =
idRenderSystemLocal : : PrintMemInfo
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderSystemLocal : : PrintMemInfo ( MemInfo_t * mi )
{
2012-11-26 18:58:24 +00:00
// sum up image totals
globalImages - > PrintMemInfo ( mi ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// sum up model totals
renderModelManager - > PrintMemInfo ( mi ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// compute render totals
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = =
idRenderSystemLocal : : UploadImage
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idRenderSystemLocal : : UploadImage ( const char * imageName , const byte * data , int width , int height )
{
idImage * image = globalImages - > GetImage ( imageName ) ;
if ( ! image )
{
2012-11-26 18:58:24 +00:00
return false ;
}
image - > UploadScratch ( data , width , height ) ;
return true ;
}