2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 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 Source Code. If not, please request a copy in writing from id Software at the address below.
24 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.
26 ===========================================================================
28 #include "../idlib/precompiled.h"
34 frameData_t *frameData;
35 backEndState_t backEnd;
39 ======================
42 This should initialize all GL state that any part of the entire program
43 may touch, including the editor.
44 ======================
46 void RB_SetDefaultGLState( void ) {
49 RB_LogComment( "--- R_SetDefaultGLState ---\n" );
51 qglClearDepth( 1.0f );
54 // the vertex array is always enabled
55 qglEnableClientState( GL_VERTEX_ARRAY );
56 qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
57 qglDisableClientState( GL_COLOR_ARRAY );
60 // make sure our GL state vector is set correctly
62 memset( &backEnd.glState, 0, sizeof( backEnd.glState ) );
63 backEnd.glState.forceGlState = true;
65 qglColorMask( 1, 1, 1, 1 );
67 qglEnable( GL_DEPTH_TEST );
68 qglEnable( GL_BLEND );
69 qglEnable( GL_SCISSOR_TEST );
70 qglEnable( GL_CULL_FACE );
71 qglDisable( GL_LIGHTING );
72 qglDisable( GL_LINE_STIPPLE );
73 qglDisable( GL_STENCIL_TEST );
75 qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
76 qglDepthMask( GL_TRUE );
77 qglDepthFunc( GL_ALWAYS );
79 qglCullFace( GL_FRONT_AND_BACK );
80 qglShadeModel( GL_SMOOTH );
82 if ( r_useScissor.GetBool() ) {
83 qglScissor( 0, 0, glConfig.vidWidth, glConfig.vidHeight );
86 for ( i = glConfig.maxTextureUnits - 1 ; i >= 0 ; i-- ) {
87 GL_SelectTexture( i );
89 // object linear texgen is our default
90 qglTexGenf( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
91 qglTexGenf( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
92 qglTexGenf( GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
93 qglTexGenf( GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
95 GL_TexEnv( GL_MODULATE );
96 qglDisable( GL_TEXTURE_2D );
97 if ( glConfig.texture3DAvailable ) {
98 qglDisable( GL_TEXTURE_3D );
100 if ( glConfig.cubeMapAvailable ) {
101 qglDisable( GL_TEXTURE_CUBE_MAP_EXT );
112 void RB_LogComment( const char *comment, ... ) {
119 fprintf( tr.logFile, "// " );
120 va_start( marker, comment );
121 vfprintf( tr.logFile, comment, marker );
126 //=============================================================================
135 void GL_SelectTexture( int unit ) {
136 if ( backEnd.glState.currenttmu == unit ) {
140 if ( unit < 0 || unit >= glConfig.maxTextureUnits && unit >= glConfig.maxTextureImageUnits ) {
141 common->Warning( "GL_SelectTexture: unit = %i", unit );
145 qglActiveTextureARB( GL_TEXTURE0_ARB + unit );
146 qglClientActiveTextureARB( GL_TEXTURE0_ARB + unit );
147 RB_LogComment( "glActiveTextureARB( %i );\nglClientActiveTextureARB( %i );\n", unit, unit );
149 backEnd.glState.currenttmu = unit;
157 This handles the flipping needed when the view being
158 rendered is a mirored view.
161 void GL_Cull( int cullType ) {
162 if ( backEnd.glState.faceCulling == cullType ) {
166 if ( cullType == CT_TWO_SIDED ) {
167 qglDisable( GL_CULL_FACE );
169 if ( backEnd.glState.faceCulling == CT_TWO_SIDED ) {
170 qglEnable( GL_CULL_FACE );
173 if ( cullType == CT_BACK_SIDED ) {
174 if ( backEnd.viewDef->isMirror ) {
175 qglCullFace( GL_FRONT );
177 qglCullFace( GL_BACK );
180 if ( backEnd.viewDef->isMirror ) {
181 qglCullFace( GL_BACK );
183 qglCullFace( GL_FRONT );
188 backEnd.glState.faceCulling = cullType;
196 void GL_TexEnv( int env ) {
199 tmu = &backEnd.glState.tmu[backEnd.glState.currenttmu];
200 if ( env == tmu->texEnv ) {
212 qglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env );
215 common->Error( "GL_TexEnv: invalid env '%d' passed\n", env );
224 Clears the state delta bits, so the next GL_State
228 void GL_ClearStateDelta( void ) {
229 backEnd.glState.forceGlState = true;
236 This routine is responsible for setting the most commonly changed state
239 void GL_State( int stateBits ) {
242 if ( !r_useStateCaching.GetBool() || backEnd.glState.forceGlState ) {
243 // make sure everything is set all the time, so we
244 // can see if our delta checking is screwing up
246 backEnd.glState.forceGlState = false;
248 diff = stateBits ^ backEnd.glState.glStateBits;
255 // check depthFunc bits
257 if ( diff & ( GLS_DEPTHFUNC_EQUAL | GLS_DEPTHFUNC_LESS | GLS_DEPTHFUNC_ALWAYS ) ) {
258 if ( stateBits & GLS_DEPTHFUNC_EQUAL ) {
259 qglDepthFunc( GL_EQUAL );
260 } else if ( stateBits & GLS_DEPTHFUNC_ALWAYS ) {
261 qglDepthFunc( GL_ALWAYS );
263 qglDepthFunc( GL_LEQUAL );
271 if ( diff & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) {
272 GLenum srcFactor, dstFactor;
274 switch ( stateBits & GLS_SRCBLEND_BITS ) {
275 case GLS_SRCBLEND_ZERO:
278 case GLS_SRCBLEND_ONE:
281 case GLS_SRCBLEND_DST_COLOR:
282 srcFactor = GL_DST_COLOR;
284 case GLS_SRCBLEND_ONE_MINUS_DST_COLOR:
285 srcFactor = GL_ONE_MINUS_DST_COLOR;
287 case GLS_SRCBLEND_SRC_ALPHA:
288 srcFactor = GL_SRC_ALPHA;
290 case GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA:
291 srcFactor = GL_ONE_MINUS_SRC_ALPHA;
293 case GLS_SRCBLEND_DST_ALPHA:
294 srcFactor = GL_DST_ALPHA;
296 case GLS_SRCBLEND_ONE_MINUS_DST_ALPHA:
297 srcFactor = GL_ONE_MINUS_DST_ALPHA;
299 case GLS_SRCBLEND_ALPHA_SATURATE:
300 srcFactor = GL_SRC_ALPHA_SATURATE;
303 srcFactor = GL_ONE; // to get warning to shut up
304 common->Error( "GL_State: invalid src blend state bits\n" );
308 switch ( stateBits & GLS_DSTBLEND_BITS ) {
309 case GLS_DSTBLEND_ZERO:
312 case GLS_DSTBLEND_ONE:
315 case GLS_DSTBLEND_SRC_COLOR:
316 dstFactor = GL_SRC_COLOR;
318 case GLS_DSTBLEND_ONE_MINUS_SRC_COLOR:
319 dstFactor = GL_ONE_MINUS_SRC_COLOR;
321 case GLS_DSTBLEND_SRC_ALPHA:
322 dstFactor = GL_SRC_ALPHA;
324 case GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA:
325 dstFactor = GL_ONE_MINUS_SRC_ALPHA;
327 case GLS_DSTBLEND_DST_ALPHA:
328 dstFactor = GL_DST_ALPHA;
330 case GLS_DSTBLEND_ONE_MINUS_DST_ALPHA:
331 dstFactor = GL_ONE_MINUS_DST_ALPHA;
334 dstFactor = GL_ONE; // to get warning to shut up
335 common->Error( "GL_State: invalid dst blend state bits\n" );
339 qglBlendFunc( srcFactor, dstFactor );
345 if ( diff & GLS_DEPTHMASK ) {
346 if ( stateBits & GLS_DEPTHMASK ) {
347 qglDepthMask( GL_FALSE );
349 qglDepthMask( GL_TRUE );
356 if ( diff & (GLS_REDMASK|GLS_GREENMASK|GLS_BLUEMASK|GLS_ALPHAMASK) ) {
357 GLboolean r, g, b, a;
358 r = ( stateBits & GLS_REDMASK ) ? 0 : 1;
359 g = ( stateBits & GLS_GREENMASK ) ? 0 : 1;
360 b = ( stateBits & GLS_BLUEMASK ) ? 0 : 1;
361 a = ( stateBits & GLS_ALPHAMASK ) ? 0 : 1;
362 qglColorMask( r, g, b, a );
368 if ( diff & GLS_POLYMODE_LINE ) {
369 if ( stateBits & GLS_POLYMODE_LINE ) {
370 qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
372 qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
379 if ( diff & GLS_ATEST_BITS ) {
380 switch ( stateBits & GLS_ATEST_BITS ) {
382 qglDisable( GL_ALPHA_TEST );
384 case GLS_ATEST_EQ_255:
385 qglEnable( GL_ALPHA_TEST );
386 qglAlphaFunc( GL_EQUAL, 1 );
388 case GLS_ATEST_LT_128:
389 qglEnable( GL_ALPHA_TEST );
390 qglAlphaFunc( GL_LESS, 0.5 );
392 case GLS_ATEST_GE_128:
393 qglEnable( GL_ALPHA_TEST );
394 qglAlphaFunc( GL_GEQUAL, 0.5 );
402 backEnd.glState.glStateBits = stateBits;
409 ============================================================================
411 RENDER BACK END THREAD FUNCTIONS
413 ============================================================================
420 This is not used by the normal game paths, just by some tools
423 void RB_SetGL2D( void ) {
424 // set 2D virtual screen size
425 qglViewport( 0, 0, glConfig.vidWidth, glConfig.vidHeight );
426 if ( r_useScissor.GetBool() ) {
427 qglScissor( 0, 0, glConfig.vidWidth, glConfig.vidHeight );
429 qglMatrixMode( GL_PROJECTION );
431 qglOrtho( 0, 640, 480, 0, 0, 1 ); // always assume 640x480 virtual coordinates
432 qglMatrixMode( GL_MODELVIEW );
435 GL_State( GLS_DEPTHFUNC_ALWAYS |
436 GLS_SRCBLEND_SRC_ALPHA |
437 GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
439 GL_Cull( CT_TWO_SIDED );
441 qglDisable( GL_DEPTH_TEST );
442 qglDisable( GL_STENCIL_TEST );
453 static void RB_SetBuffer( const void *data ) {
454 const setBufferCommand_t *cmd;
456 // see which draw buffer we want to render the frame to
458 cmd = (const setBufferCommand_t *)data;
460 backEnd.frameCount = cmd->frameCount;
462 qglDrawBuffer( cmd->buffer );
464 // clear screen for debugging
465 // automatically enable this with several other debug tools
466 // that might leave unrendered portions of the screen
467 if ( r_clear.GetFloat() || idStr::Length( r_clear.GetString() ) != 1 || r_lockSurfaces.GetBool() || r_singleArea.GetBool() || r_showOverDraw.GetBool() ) {
469 if ( sscanf( r_clear.GetString(), "%f %f %f", &c[0], &c[1], &c[2] ) == 3 ) {
470 qglClearColor( c[0], c[1], c[2], 1 );
471 } else if ( r_clear.GetInteger() == 2 ) {
472 qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
473 } else if ( r_showOverDraw.GetBool() ) {
474 qglClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
476 qglClearColor( 0.4f, 0.0f, 0.25f, 1.0f );
478 qglClear( GL_COLOR_BUFFER_BIT );
486 Draw all the images to the screen, on top of whatever
487 was there. This is used to test for texture thrashing.
490 void RB_ShowImages( void ) {
498 //qglClearColor( 0.2, 0.2, 0.2, 1 );
499 //qglClear( GL_COLOR_BUFFER_BIT );
503 start = Sys_Milliseconds();
505 for ( i = 0 ; i < globalImages->images.Num() ; i++ ) {
506 image = globalImages->images[i];
508 if ( image->texnum == idImage::TEXTURE_NOT_LOADED && image->partialImage == NULL ) {
512 w = glConfig.vidWidth / 20;
513 h = glConfig.vidHeight / 15;
517 // show in proportional size in mode 2
518 if ( r_showImages.GetInteger() == 2 ) {
519 w *= image->uploadWidth / 512.0f;
520 h *= image->uploadHeight / 512.0f;
525 qglTexCoord2f( 0, 0 );
527 qglTexCoord2f( 1, 0 );
528 qglVertex2f( x + w, y );
529 qglTexCoord2f( 1, 1 );
530 qglVertex2f( x + w, y + h );
531 qglTexCoord2f( 0, 1 );
532 qglVertex2f( x, y + h );
538 end = Sys_Milliseconds();
539 common->Printf( "%i msec to draw all images\n", end - start );
549 const void RB_SwapBuffers( const void *data ) {
550 // texture swapping test
551 if ( r_showImages.GetInteger() != 0 ) {
555 // force a gl sync if requested
556 if ( r_finish.GetBool() ) {
560 RB_LogComment( "***************** RB_SwapBuffers *****************\n\n\n" );
562 // don't flip if drawing to front buffer
563 if ( !r_frontBuffer.GetBool() ) {
572 Copy part of the current framebuffer to an image
575 const void RB_CopyRender( const void *data ) {
576 const copyRenderCommand_t *cmd;
578 cmd = (const copyRenderCommand_t *)data;
580 if ( r_skipCopyTexture.GetBool() ) {
584 RB_LogComment( "***************** RB_CopyRender *****************\n" );
587 cmd->image->CopyFramebuffer( cmd->x, cmd->y, cmd->imageWidth, cmd->imageHeight, false );
593 RB_ExecuteBackEndCommands
595 This function will be called syncronously if running without
596 smp extensions, or asyncronously by another thread.
599 int backEndStartTime, backEndFinishTime;
600 void RB_ExecuteBackEndCommands( const emptyCommand_t *cmds ) {
601 // r_debugRenderToTexture
602 int c_draw3d = 0, c_draw2d = 0, c_setBuffers = 0, c_swapBuffers = 0, c_copyRenders = 0;
604 if ( cmds->commandId == RC_NOP && !cmds->next ) {
608 backEndStartTime = Sys_Milliseconds();
610 // needed for editor rendering
611 RB_SetDefaultGLState();
613 // upload any image loads that have completed
614 globalImages->CompleteBackgroundImageLoads();
616 for ( ; cmds ; cmds = (const emptyCommand_t *)cmds->next ) {
617 switch ( cmds->commandId ) {
622 if ( ((const drawSurfsCommand_t *)cmds)->viewDef->viewEntitys ) {
630 RB_SetBuffer( cmds );
633 case RC_SWAP_BUFFERS:
634 RB_SwapBuffers( cmds );
638 RB_CopyRender( cmds );
642 common->Error( "RB_ExecuteBackEndCommands: bad commandId" );
647 // go back to the default texture so the editor doesn't mess up a bound image
648 qglBindTexture( GL_TEXTURE_2D, 0 );
649 backEnd.glState.tmu[0].current2DMap = -1;
651 // stop rendering on this thread
652 backEndFinishTime = Sys_Milliseconds();
653 backEnd.pc.msec = backEndFinishTime - backEndStartTime;
655 if ( r_debugRenderToTexture.GetInteger() == 1 ) {
656 common->Printf( "3d: %i, 2d: %i, SetBuf: %i, SwpBuf: %i, CpyRenders: %i, CpyFrameBuf: %i\n", c_draw3d, c_draw2d, c_setBuffers, c_swapBuffers, c_copyRenders, backEnd.c_copyFrameBuffer );
657 backEnd.c_copyFrameBuffer = 0;