12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- 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
- #include "../idlib/precompiled.h"
- #include "tr_local.h"
- idRenderSystemLocal tr;
- idRenderSystem * renderSystem = &tr;
- /*
- =====================
- R_PerformanceCounters
- This prints both front and back end counters, so it should
- only be called when the back end thread is idle.
- =====================
- */
- static void R_PerformanceCounters() {
- if ( r_showPrimitives.GetInteger() != 0 ) {
- common->Printf( "views:%i draws:%i tris:%i (shdw:%i)\n",
- tr.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
- );
- }
- if ( r_showDynamic.GetBool() ) {
- common->Printf( "callback:%i md5:%i dfrmVerts:%i dfrmTris:%i tangTris:%i guis:%i\n",
- tr.pc.c_entityDefCallbacks,
- tr.pc.c_generateMd5,
- tr.pc.c_deformedVerts,
- tr.pc.c_deformedIndexes/3,
- tr.pc.c_tangentIndexes/3,
- tr.pc.c_guiSurfs
- );
- }
- if ( r_showCull.GetBool() ) {
- common->Printf( "%i box in %i box out\n",
- tr.pc.c_box_cull_in, tr.pc.c_box_cull_out );
- }
-
- if ( r_showAddModel.GetBool() ) {
- common->Printf( "callback:%i createInteractions:%i createShadowVolumes:%i\n",
- tr.pc.c_entityDefCallbacks, tr.pc.c_createInteractions, tr.pc.c_createShadowVolumes );
- common->Printf( "viewEntities:%i shadowEntities:%i viewLights:%i\n", tr.pc.c_visibleViewEntities,
- tr.pc.c_shadowViewEntities, tr.pc.c_viewLights );
- }
- if ( r_showUpdates.GetBool() ) {
- common->Printf( "entityUpdates:%i entityRefs:%i lightUpdates:%i lightRefs:%i\n",
- tr.pc.c_entityUpdates, tr.pc.c_entityReferences,
- tr.pc.c_lightUpdates, tr.pc.c_lightReferences );
- }
- if ( r_showMemory.GetBool() ) {
- common->Printf( "frameData: %i (%i)\n", frameData->frameMemoryAllocated.GetValue(), frameData->highWaterAllocated );
- }
- memset( &tr.pc, 0, sizeof( tr.pc ) );
- memset( &backEnd.pc, 0, sizeof( backEnd.pc ) );
- }
- /*
- ====================
- RenderCommandBuffers
- ====================
- */
- void idRenderSystemLocal::RenderCommandBuffers( const emptyCommand_t * const cmdHead ) {
- // if there isn't a draw view command, do nothing to avoid swapping a bad frame
- bool hasView = false;
- 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 ) {
- hasView = true;
- break;
- }
- }
- if ( !hasView ) {
- return;
- }
- // 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.
- // r_skipRender is usually more usefull, because it will still
- // draw 2D graphics
- if ( !r_skipBackEnd.GetBool() ) {
- if ( glConfig.timerQueryAvailable ) {
- if ( tr.timerQueryId == 0 ) {
- qglGenQueriesARB( 1, & tr.timerQueryId );
- }
- qglBeginQueryARB( GL_TIME_ELAPSED_EXT, tr.timerQueryId );
- RB_ExecuteBackEndCommands( cmdHead );
- qglEndQueryARB( GL_TIME_ELAPSED_EXT );
- qglFlush();
- } else {
- RB_ExecuteBackEndCommands( cmdHead );
- }
- }
- // pass in null for now - we may need to do some map specific hackery in the future
- resolutionScale.InitForMap( NULL );
- }
- /*
- ============
- R_GetCommandBuffer
- Returns memory for a command buffer (stretchPicCommand_t,
- drawSurfsCommand_t, etc) and links it to the end of the
- current command chain.
- ============
- */
- void *R_GetCommandBuffer( int bytes ) {
- emptyCommand_t *cmd;
- cmd = (emptyCommand_t *)R_FrameAlloc( bytes, FRAME_ALLOC_DRAW_COMMAND );
- cmd->next = NULL;
- frameData->cmdTail->next = &cmd->commandId;
- frameData->cmdTail = cmd;
- return (void *)cmd;
- }
- /*
- =================
- R_ViewStatistics
- =================
- */
- static void R_ViewStatistics( viewDef_t *parms ) {
- // report statistics about this view
- if ( !r_showSurfaces.GetBool() ) {
- return;
- }
- common->Printf( "view:%p surfs:%i\n", parms, parms->numDrawSurfs );
- }
- /*
- =============
- R_AddDrawViewCmd
- This is the main 3D rendering command. A single scene may
- have multiple views if a mirror, portal, or dynamic texture is present.
- =============
- */
- void R_AddDrawViewCmd( viewDef_t *parms, bool guiOnly ) {
- drawSurfsCommand_t *cmd;
- cmd = (drawSurfsCommand_t *)R_GetCommandBuffer( sizeof( *cmd ) );
- cmd->commandId = ( guiOnly ) ? RC_DRAW_VIEW_GUI : RC_DRAW_VIEW_3D;
- cmd->viewDef = parms;
- tr.pc.c_numViews++;
- R_ViewStatistics( parms );
- }
- /*
- =============
- R_AddPostProcess
- This issues the command to do a post process after all the views have
- been rendered.
- =============
- */
- void R_AddDrawPostProcess( viewDef_t * parms ) {
- postProcessCommand_t * cmd = (postProcessCommand_t *)R_GetCommandBuffer( sizeof( *cmd ) );
- cmd->commandId = RC_POST_PROCESS;
- cmd->viewDef = parms;
- }
- //=================================================================================
- /*
- =============
- R_CheckCvars
- See if some cvars that we watch have changed
- =============
- */
- static void R_CheckCvars() {
- // gamma stuff
- if ( r_gamma.IsModified() || r_brightness.IsModified() ) {
- r_gamma.ClearModified();
- r_brightness.ClearModified();
- R_SetColorMappings();
- }
- // filtering
- if ( r_maxAnisotropicFiltering.IsModified() || r_useTrilinearFiltering.IsModified() || r_lodBias.IsModified() ) {
- idLib::Printf( "Updating texture filter parameters.\n" );
- r_maxAnisotropicFiltering.ClearModified();
- r_useTrilinearFiltering.ClearModified();
- r_lodBias.ClearModified();
- for ( int i = 0 ; i < globalImages->images.Num() ; i++ ) {
- if ( globalImages->images[i] ) {
- globalImages->images[i]->Bind();
- globalImages->images[i]->SetTexParameters();
- }
- }
- }
- extern idCVar r_useSeamlessCubeMap;
- if ( r_useSeamlessCubeMap.IsModified() ) {
- r_useSeamlessCubeMap.ClearModified();
- if ( glConfig.seamlessCubeMapAvailable ) {
- if ( r_useSeamlessCubeMap.GetBool() ) {
- qglEnable( GL_TEXTURE_CUBE_MAP_SEAMLESS );
- } else {
- qglDisable( GL_TEXTURE_CUBE_MAP_SEAMLESS );
- }
- }
- }
- extern idCVar r_useSRGB;
- if ( r_useSRGB.IsModified() ) {
- r_useSRGB.ClearModified();
- if ( glConfig.sRGBFramebufferAvailable ) {
- if ( r_useSRGB.GetBool() ) {
- qglEnable( GL_FRAMEBUFFER_SRGB );
- } else {
- qglDisable( GL_FRAMEBUFFER_SRGB );
- }
- }
- }
- if ( r_multiSamples.IsModified() ) {
- if ( r_multiSamples.GetInteger() > 0 ) {
- qglEnable( GL_MULTISAMPLE_ARB );
- } else {
- qglDisable( GL_MULTISAMPLE_ARB );
- }
- }
- // check for changes to logging state
- GLimp_EnableLogging( r_logFile.GetInteger() != 0 );
- }
- /*
- =============
- idRenderSystemLocal::idRenderSystemLocal
- =============
- */
- idRenderSystemLocal::idRenderSystemLocal() :
- unitSquareTriangles( NULL ),
- zeroOneCubeTriangles( NULL ),
- testImageTriangles( NULL ) {
- Clear();
- }
- /*
- =============
- idRenderSystemLocal::~idRenderSystemLocal
- =============
- */
- idRenderSystemLocal::~idRenderSystemLocal() {
- }
- /*
- =============
- idRenderSystemLocal::SetColor
- =============
- */
- void idRenderSystemLocal::SetColor( const idVec4 & rgba ) {
- currentColorNativeBytesOrder = LittleLong( PackColor( rgba ) );
- }
- /*
- =============
- idRenderSystemLocal::GetColor
- =============
- */
- uint32 idRenderSystemLocal::GetColor() {
- return LittleLong( currentColorNativeBytesOrder );
- }
- /*
- =============
- idRenderSystemLocal::SetGLState
- =============
- */
- void idRenderSystemLocal::SetGLState( const uint64 glState ) {
- currentGLState = glState;
- }
- /*
- =============
- idRenderSystemLocal::DrawFilled
- =============
- */
- void idRenderSystemLocal::DrawFilled( const idVec4 & color, float x, float y, float w, float h ) {
- SetColor( color );
- DrawStretchPic( x, y, w, h, 0.0f, 0.0f, 1.0f, 1.0f, whiteMaterial );
- }
- /*
- =============
- idRenderSystemLocal::DrawStretchPic
- =============
- */
- 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 );
- }
- /*
- =============
- idRenderSystemLocal::DrawStretchPic
- =============
- */
- static triIndex_t quadPicIndexes[6] = { 3, 0, 2, 2, 0, 1 };
- void idRenderSystemLocal::DrawStretchPic( const idVec4 & topLeft, const idVec4 & topRight, const idVec4 & bottomRight, const idVec4 & bottomLeft, const idMaterial * material ) {
- if ( !R_IsInitialized() ) {
- return;
- }
- if ( material == NULL ) {
- return;
- }
- idDrawVert * verts = guiModel->AllocTris( 4, quadPicIndexes, 6, material, currentGLState, STEREO_DEPTH_TYPE_NONE );
- if ( verts == NULL ) {
- return;
- }
- ALIGNTYPE16 idDrawVert localVerts[4];
- 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();
- 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();
- 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();
- 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();
- WriteDrawVerts16( verts, localVerts, 4 );
- }
- /*
- =============
- idRenderSystemLocal::DrawStretchTri
- =============
- */
- void idRenderSystemLocal::DrawStretchTri( const idVec2 & p1, const idVec2 & p2, const idVec2 & p3, const idVec2 & t1, const idVec2 & t2, const idVec2 & t3, const idMaterial *material ) {
- if ( !R_IsInitialized() ) {
- return;
- }
- if ( material == NULL ) {
- return;
- }
- triIndex_t tempIndexes[3] = { 1, 0, 2 };
- idDrawVert * verts = guiModel->AllocTris( 3, tempIndexes, 3, material, currentGLState, STEREO_DEPTH_TYPE_NONE );
- if ( verts == NULL ) {
- return;
- }
- ALIGNTYPE16 idDrawVert localVerts[3];
- 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();
- 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();
- 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();
- WriteDrawVerts16( verts, localVerts, 3 );
- }
- /*
- =============
- idRenderSystemLocal::AllocTris
- =============
- */
- idDrawVert * idRenderSystemLocal::AllocTris( int numVerts, const triIndex_t * indexes, int numIndexes, const idMaterial * material, const stereoDepthType_t stereoType ) {
- return guiModel->AllocTris( numVerts, indexes, numIndexes, material, currentGLState, stereoType );
- }
- /*
- =====================
- idRenderSystemLocal::DrawSmallChar
- small chars are drawn at native screen resolution
- =====================
- */
- void idRenderSystemLocal::DrawSmallChar( int x, int y, int ch ) {
- int row, col;
- float frow, fcol;
- float size;
- ch &= 255;
- if ( ch == ' ' ) {
- return;
- }
- if ( y < -SMALLCHAR_HEIGHT ) {
- return;
- }
- row = ch >> 4;
- col = ch & 15;
- frow = row * 0.0625f;
- fcol = col * 0.0625f;
- size = 0.0625f;
- DrawStretchPic( x, y, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT,
- fcol, frow,
- fcol + size, frow + size,
- charSetMaterial );
- }
- /*
- ==================
- 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
- ==================
- */
- void idRenderSystemLocal::DrawSmallStringExt( int x, int y, const char *string, const idVec4 &setColor, bool forceColor ) {
- idVec4 color;
- const unsigned char *s;
- int xx;
- // draw the colored text
- s = (const unsigned char*)string;
- xx = x;
- SetColor( setColor );
- while ( *s ) {
- if ( idStr::IsColor( (const char*)s ) ) {
- if ( !forceColor ) {
- if ( *(s+1) == C_COLOR_DEFAULT ) {
- SetColor( setColor );
- } else {
- color = idStr::ColorForIndex( *(s+1) );
- color[3] = setColor[3];
- SetColor( color );
- }
- }
- s += 2;
- continue;
- }
- DrawSmallChar( xx, y, *s );
- xx += SMALLCHAR_WIDTH;
- s++;
- }
- SetColor( colorWhite );
- }
- /*
- =====================
- idRenderSystemLocal::DrawBigChar
- =====================
- */
- void idRenderSystemLocal::DrawBigChar( int x, int y, int ch ) {
- int row, col;
- float frow, fcol;
- float size;
- ch &= 255;
- if ( ch == ' ' ) {
- return;
- }
- if ( y < -BIGCHAR_HEIGHT ) {
- return;
- }
- row = ch >> 4;
- col = ch & 15;
- frow = row * 0.0625f;
- fcol = col * 0.0625f;
- size = 0.0625f;
- DrawStretchPic( x, y, BIGCHAR_WIDTH, BIGCHAR_HEIGHT,
- fcol, frow,
- fcol + size, frow + size,
- charSetMaterial );
- }
- /*
- ==================
- 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
- ==================
- */
- void idRenderSystemLocal::DrawBigStringExt( int x, int y, const char *string, const idVec4 &setColor, bool forceColor ) {
- idVec4 color;
- const char *s;
- int xx;
- // draw the colored text
- s = string;
- xx = x;
- SetColor( setColor );
- while ( *s ) {
- if ( idStr::IsColor( s ) ) {
- if ( !forceColor ) {
- if ( *(s+1) == C_COLOR_DEFAULT ) {
- SetColor( setColor );
- } else {
- color = idStr::ColorForIndex( *(s+1) );
- 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()
- ====================
- */
- const emptyCommand_t * idRenderSystemLocal::SwapCommandBuffers(
- uint64 * frontEndMicroSec,
- uint64 * backEndMicroSec,
- uint64 * shadowMicroSec,
- uint64 * gpuMicroSec ) {
- SwapCommandBuffers_FinishRendering( frontEndMicroSec, backEndMicroSec, shadowMicroSec, gpuMicroSec );
- return SwapCommandBuffers_FinishCommandBuffers();
- }
- /*
- =====================
- idRenderSystemLocal::SwapCommandBuffers_FinishRendering
- =====================
- */
- void idRenderSystemLocal::SwapCommandBuffers_FinishRendering(
- uint64 * frontEndMicroSec,
- uint64 * backEndMicroSec,
- uint64 * shadowMicroSec,
- uint64 * gpuMicroSec ) {
- SCOPED_PROFILE_EVENT( "SwapCommandBuffers" );
- if ( gpuMicroSec != NULL ) {
- *gpuMicroSec = 0; // until shown otherwise
- }
- if ( !R_IsInitialized() ) {
- return;
- }
- // After coming back from an autoswap, we won't have anything to render
- if ( frameData->cmdHead->next != NULL ) {
- // 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
- void GL_BlockingSwapBuffers();
- GL_BlockingSwapBuffers();
- }
- // read back the start and end timer queries from the previous frame
- if ( glConfig.timerQueryAvailable ) {
- uint64 drawingTimeNanoseconds = 0;
- if ( tr.timerQueryId != 0 ) {
- qglGetQueryObjectui64vEXT( tr.timerQueryId, GL_QUERY_RESULT, &drawingTimeNanoseconds );
- }
- if ( gpuMicroSec != NULL ) {
- *gpuMicroSec = drawingTimeNanoseconds / 1000;
- }
- }
- //------------------------------
- // save out timing information
- if ( frontEndMicroSec != NULL ) {
- *frontEndMicroSec = pc.frontEndMicroSec;
- }
- if ( backEndMicroSec != NULL ) {
- *backEndMicroSec = backEnd.pc.totalMicroSec;
- }
- if ( shadowMicroSec != NULL ) {
- *shadowMicroSec = backEnd.pc.shadowMicroSec;
- }
- // print any other statistics and clear all of them
- R_PerformanceCounters();
- // check for dynamic changes that require some initialization
- R_CheckCvars();
- // check for errors
- GL_CheckErrors();
- }
- /*
- =====================
- idRenderSystemLocal::SwapCommandBuffers_FinishCommandBuffers
- =====================
- */
- const emptyCommand_t * idRenderSystemLocal::SwapCommandBuffers_FinishCommandBuffers() {
- if ( !R_IsInitialized() ) {
- return NULL;
- }
- // close any gui drawing
- guiModel->EmitFullScreen();
- guiModel->Clear();
- // unmap the buffer objects so they can be used by the GPU
- vertexCache.BeginBackEnd();
- // save off this command buffer
- const emptyCommand_t * commandBufferHead = frameData->cmdHead;
- // copy the code-used drawsurfs that were
- // allocated at the start of the buffer memory to the backEnd referenced locations
- backEnd.unitSquareSurface = tr.unitSquareSurface_;
- backEnd.zeroOneCubeSurface = tr.zeroOneCubeSurface_;
- backEnd.testImageSurface = tr.testImageSurface_;
- // use the other buffers next frame, because another CPU
- // may still be rendering into the current buffers
- R_ToggleSmpFrame();
- // possibly change the stereo3D mode
- // PC
- if ( glConfig.nativeScreenWidth == 1280 && glConfig.nativeScreenHeight == 1470 ) {
- glConfig.stereo3Dmode = STEREO3D_HDMI_720;
- } else {
- glConfig.stereo3Dmode = GetStereoScopicRenderingMode();
- }
- // prepare the new command buffer
- guiModel->BeginFrame();
- //------------------------------
- // 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 );
- R_InitDrawSurfFromTri( tr.testImageSurface_, *tr.testImageTriangles );
- // 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;
- // this is the ONLY place this is modified
- frameCount++;
- // just in case we did a common->Error while this
- // was set
- guiRecursionLevel = 0;
- // 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;
- setBufferCommand_t * cmd2 = (setBufferCommand_t *)R_GetCommandBuffer( sizeof( *cmd2 ) );
- cmd2->commandId = RC_SET_BUFFER;
- cmd2->buffer = (int)GL_BACK;
- // the old command buffer can now be rendered, while the new one can
- // be built in parallel
- return commandBufferHead;
- }
- /*
- =====================
- idRenderSystemLocal::WriteDemoPics
- =====================
- */
- void idRenderSystemLocal::WriteDemoPics() {
- common->WriteDemo()->WriteInt( DS_RENDER );
- common->WriteDemo()->WriteInt( DC_GUI_MODEL );
- }
- /*
- =====================
- idRenderSystemLocal::DrawDemoPics
- =====================
- */
- void idRenderSystemLocal::DrawDemoPics() {
- }
- /*
- =====================
- idRenderSystemLocal::GetCroppedViewport
- Returns the current cropped pixel coordinates
- =====================
- */
- void idRenderSystemLocal::GetCroppedViewport( idScreenRect * viewport ) {
- *viewport = renderCrops[currentRenderCrop];
- }
- /*
- ========================
- idRenderSystemLocal::PerformResolutionScaling
- The 3D 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.
- ========================
- */
- void idRenderSystemLocal::PerformResolutionScaling( int& newWidth, int& newHeight ) {
- float xScale = 1.0f;
- float yScale = 1.0f;
- resolutionScale.GetCurrentResolutionScale( xScale, yScale );
- newWidth = idMath::Ftoi( GetWidth() * xScale );
- newHeight = idMath::Ftoi( GetHeight() * yScale );
- }
- /*
- ================
- idRenderSystemLocal::CropRenderSize
- ================
- */
- void idRenderSystemLocal::CropRenderSize( int width, int height ) {
- if ( !R_IsInitialized() ) {
- return;
- }
- // close any gui drawing before changing the size
- guiModel->EmitFullScreen();
- guiModel->Clear();
- if ( width < 1 || height < 1 ) {
- common->Error( "CropRenderSize: bad sizes" );
- }
- if ( common->WriteDemo() ) {
- common->WriteDemo()->WriteInt( DS_RENDER );
- common->WriteDemo()->WriteInt( DC_CROP_RENDER );
- common->WriteDemo()->WriteInt( width );
- common->WriteDemo()->WriteInt( height );
- if ( r_showDemo.GetBool() ) {
- common->Printf( "write DC_CROP_RENDER\n" );
- }
- }
- idScreenRect & previous = renderCrops[currentRenderCrop];
- currentRenderCrop++;
- idScreenRect & current = renderCrops[currentRenderCrop];
- current.x1 = previous.x1;
- current.x2 = previous.x1 + width - 1;
- current.y1 = previous.y2 - height + 1;
- current.y2 = previous.y2;
- }
- /*
- ================
- idRenderSystemLocal::UnCrop
- ================
- */
- void idRenderSystemLocal::UnCrop() {
- if ( !R_IsInitialized() ) {
- return;
- }
- if ( currentRenderCrop < 1 ) {
- common->Error( "idRenderSystemLocal::UnCrop: currentRenderCrop < 1" );
- }
- // close any gui drawing
- guiModel->EmitFullScreen();
- guiModel->Clear();
- currentRenderCrop--;
- if ( common->WriteDemo() ) {
- common->WriteDemo()->WriteInt( DS_RENDER );
- common->WriteDemo()->WriteInt( DC_UNCROP_RENDER );
- if ( r_showDemo.GetBool() ) {
- common->Printf( "write DC_UNCROP\n" );
- }
- }
- }
- /*
- ================
- idRenderSystemLocal::CaptureRenderToImage
- ================
- */
- void idRenderSystemLocal::CaptureRenderToImage( const char *imageName, bool clearColorAfterCopy ) {
- if ( !R_IsInitialized() ) {
- return;
- }
- guiModel->EmitFullScreen();
- guiModel->Clear();
- if ( common->WriteDemo() ) {
- common->WriteDemo()->WriteInt( DS_RENDER );
- common->WriteDemo()->WriteInt( DC_CAPTURE_RENDER );
- common->WriteDemo()->WriteHashString( imageName );
- if ( r_showDemo.GetBool() ) {
- common->Printf( "write DC_CAPTURE_RENDER: %s\n", imageName );
- }
- }
- idImage * image = globalImages->GetImage( imageName );
- if ( image == NULL ) {
- image = globalImages->AllocImage( imageName );
- }
- idScreenRect & rc = renderCrops[currentRenderCrop];
- copyRenderCommand_t *cmd = (copyRenderCommand_t *)R_GetCommandBuffer( sizeof( *cmd ) );
- 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;
- guiModel->Clear();
- }
- /*
- ==============
- idRenderSystemLocal::CaptureRenderToFile
- ==============
- */
- void idRenderSystemLocal::CaptureRenderToFile( const char *fileName, bool fixAlpha ) {
- if ( !R_IsInitialized() ) {
- return;
- }
- idScreenRect & rc = renderCrops[currentRenderCrop];
- guiModel->EmitFullScreen();
- guiModel->Clear();
- RenderCommandBuffers( frameData->cmdHead );
- qglReadBuffer( GL_BACK );
- // include extra space for OpenGL padding to word boundaries
- int c = ( rc.GetWidth() + 3 ) * rc.GetHeight();
- byte *data = (byte *)R_StaticAlloc( c * 3 );
-
- qglReadPixels( rc.x1, rc.y1, rc.GetWidth(), rc.GetHeight(), GL_RGB, GL_UNSIGNED_BYTE, data );
- byte *data2 = (byte *)R_StaticAlloc( c * 4 );
- for ( int i = 0 ; i < c ; i++ ) {
- 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;
- }
- R_WriteTGA( fileName, data2, rc.GetWidth(), rc.GetHeight(), true );
- R_StaticFree( data );
- R_StaticFree( data2 );
- }
- /*
- ==============
- idRenderSystemLocal::AllocRenderWorld
- ==============
- */
- idRenderWorld *idRenderSystemLocal::AllocRenderWorld() {
- idRenderWorldLocal *rw;
- rw = new (TAG_RENDER) idRenderWorldLocal;
- worlds.Append( rw );
- return rw;
- }
- /*
- ==============
- idRenderSystemLocal::FreeRenderWorld
- ==============
- */
- void idRenderSystemLocal::FreeRenderWorld( idRenderWorld *rw ) {
- if ( primaryWorld == rw ) {
- primaryWorld = NULL;
- }
- worlds.Remove( static_cast<idRenderWorldLocal *>(rw) );
- delete rw;
- }
- /*
- ==============
- idRenderSystemLocal::PrintMemInfo
- ==============
- */
- void idRenderSystemLocal::PrintMemInfo( MemInfo_t *mi ) {
- // sum up image totals
- globalImages->PrintMemInfo( mi );
- // sum up model totals
- renderModelManager->PrintMemInfo( mi );
- // compute render totals
- }
- /*
- ===============
- idRenderSystemLocal::UploadImage
- ===============
- */
- bool idRenderSystemLocal::UploadImage( const char *imageName, const byte *data, int width, int height ) {
- idImage *image = globalImages->GetImage( imageName );
- if ( !image ) {
- return false;
- }
- image->UploadScratch( data, width, height );
- return true;
- }
|