]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/renderer/tr_backend.cpp
Various Mac OS X tweaks to get this to build. Probably breaking things.
[icculus/iodoom3.git] / neo / renderer / tr_backend.cpp
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
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.
13
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.
18
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/>.
21
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.
23
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.
25
26 ===========================================================================
27 */
28 #include "../idlib/precompiled.h"
29 #pragma hdrstop
30
31 #include "tr_local.h"
32
33
34 frameData_t             *frameData;
35 backEndState_t  backEnd;
36
37
38 /*
39 ======================
40 RB_SetDefaultGLState
41
42 This should initialize all GL state that any part of the entire program
43 may touch, including the editor.
44 ======================
45 */
46 void RB_SetDefaultGLState( void ) {
47         int             i;
48
49         RB_LogComment( "--- R_SetDefaultGLState ---\n" );
50
51         qglClearDepth( 1.0f );
52         qglColor4f (1,1,1,1);
53
54         // the vertex array is always enabled
55         qglEnableClientState( GL_VERTEX_ARRAY );
56         qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
57         qglDisableClientState( GL_COLOR_ARRAY );
58
59         //
60         // make sure our GL state vector is set correctly
61         //
62         memset( &backEnd.glState, 0, sizeof( backEnd.glState ) );
63         backEnd.glState.forceGlState = true;
64
65         qglColorMask( 1, 1, 1, 1 );
66
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 );
74
75         qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
76         qglDepthMask( GL_TRUE );
77         qglDepthFunc( GL_ALWAYS );
78  
79         qglCullFace( GL_FRONT_AND_BACK );
80         qglShadeModel( GL_SMOOTH );
81
82         if ( r_useScissor.GetBool() ) {
83                 qglScissor( 0, 0, glConfig.vidWidth, glConfig.vidHeight );
84         }
85
86         for ( i = glConfig.maxTextureUnits - 1 ; i >= 0 ; i-- ) {
87                 GL_SelectTexture( i );
88
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 );
94
95                 GL_TexEnv( GL_MODULATE );
96                 qglDisable( GL_TEXTURE_2D );
97                 if ( glConfig.texture3DAvailable ) {
98                         qglDisable( GL_TEXTURE_3D );
99                 }
100                 if ( glConfig.cubeMapAvailable ) {
101                         qglDisable( GL_TEXTURE_CUBE_MAP_EXT );
102                 }
103         }
104 }
105
106
107 /*
108 ====================
109 RB_LogComment
110 ====================
111 */
112 void RB_LogComment( const char *comment, ... ) {
113    va_list marker;
114
115         if ( !tr.logFile ) {
116                 return;
117         }
118
119         fprintf( tr.logFile, "// " );
120         va_start( marker, comment );
121         vfprintf( tr.logFile, comment, marker );
122         va_end( marker );
123 }
124
125
126 //=============================================================================
127
128
129
130 /*
131 ====================
132 GL_SelectTexture
133 ====================
134 */
135 void GL_SelectTexture( int unit ) {
136         if ( backEnd.glState.currenttmu == unit ) {
137                 return;
138         }
139
140         if ( unit < 0 || unit >= glConfig.maxTextureUnits && unit >= glConfig.maxTextureImageUnits ) {
141                 common->Warning( "GL_SelectTexture: unit = %i", unit );
142                 return;
143         }
144
145         qglActiveTextureARB( GL_TEXTURE0_ARB + unit );
146         qglClientActiveTextureARB( GL_TEXTURE0_ARB + unit );
147         RB_LogComment( "glActiveTextureARB( %i );\nglClientActiveTextureARB( %i );\n", unit, unit );
148
149         backEnd.glState.currenttmu = unit;
150 }
151
152
153 /*
154 ====================
155 GL_Cull
156
157 This handles the flipping needed when the view being
158 rendered is a mirored view.
159 ====================
160 */
161 void GL_Cull( int cullType ) {
162         if ( backEnd.glState.faceCulling == cullType ) {
163                 return;
164         }
165
166         if ( cullType == CT_TWO_SIDED ) {
167                 qglDisable( GL_CULL_FACE );
168         } else  {
169                 if ( backEnd.glState.faceCulling == CT_TWO_SIDED ) {
170                         qglEnable( GL_CULL_FACE );
171                 }
172
173                 if ( cullType == CT_BACK_SIDED ) {
174                         if ( backEnd.viewDef->isMirror ) {
175                                 qglCullFace( GL_FRONT );
176                         } else {
177                                 qglCullFace( GL_BACK );
178                         }
179                 } else {
180                         if ( backEnd.viewDef->isMirror ) {
181                                 qglCullFace( GL_BACK );
182                         } else {
183                                 qglCullFace( GL_FRONT );
184                         }
185                 }
186         }
187
188         backEnd.glState.faceCulling = cullType;
189 }
190
191 /*
192 ====================
193 GL_TexEnv
194 ====================
195 */
196 void GL_TexEnv( int env ) {
197         tmu_t   *tmu;
198
199         tmu = &backEnd.glState.tmu[backEnd.glState.currenttmu];
200         if ( env == tmu->texEnv ) {
201                 return;
202         }
203
204         tmu->texEnv = env;
205
206         switch ( env ) {
207         case GL_COMBINE_EXT:
208         case GL_MODULATE:
209         case GL_REPLACE:
210         case GL_DECAL:
211         case GL_ADD:
212                 qglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env );
213                 break;
214         default:
215                 common->Error( "GL_TexEnv: invalid env '%d' passed\n", env );
216                 break;
217         }
218 }
219
220 /*
221 =================
222 GL_ClearStateDelta
223
224 Clears the state delta bits, so the next GL_State
225 will set every item
226 =================
227 */
228 void GL_ClearStateDelta( void ) {
229         backEnd.glState.forceGlState = true;
230 }
231
232 /*
233 ====================
234 GL_State
235
236 This routine is responsible for setting the most commonly changed state
237 ====================
238 */
239 void GL_State( int stateBits ) {
240         int     diff;
241         
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
245                 diff = -1;
246                 backEnd.glState.forceGlState = false;
247         } else {
248                 diff = stateBits ^ backEnd.glState.glStateBits;
249                 if ( !diff ) {
250                         return;
251                 }
252         }
253
254         //
255         // check depthFunc bits
256         //
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 );
262                 } else {
263                         qglDepthFunc( GL_LEQUAL );
264                 }
265         }
266
267
268         //
269         // check blend bits
270         //
271         if ( diff & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) {
272                 GLenum srcFactor, dstFactor;
273
274                 switch ( stateBits & GLS_SRCBLEND_BITS ) {
275                 case GLS_SRCBLEND_ZERO:
276                         srcFactor = GL_ZERO;
277                         break;
278                 case GLS_SRCBLEND_ONE:
279                         srcFactor = GL_ONE;
280                         break;
281                 case GLS_SRCBLEND_DST_COLOR:
282                         srcFactor = GL_DST_COLOR;
283                         break;
284                 case GLS_SRCBLEND_ONE_MINUS_DST_COLOR:
285                         srcFactor = GL_ONE_MINUS_DST_COLOR;
286                         break;
287                 case GLS_SRCBLEND_SRC_ALPHA:
288                         srcFactor = GL_SRC_ALPHA;
289                         break;
290                 case GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA:
291                         srcFactor = GL_ONE_MINUS_SRC_ALPHA;
292                         break;
293                 case GLS_SRCBLEND_DST_ALPHA:
294                         srcFactor = GL_DST_ALPHA;
295                         break;
296                 case GLS_SRCBLEND_ONE_MINUS_DST_ALPHA:
297                         srcFactor = GL_ONE_MINUS_DST_ALPHA;
298                         break;
299                 case GLS_SRCBLEND_ALPHA_SATURATE:
300                         srcFactor = GL_SRC_ALPHA_SATURATE;
301                         break;
302                 default:
303                         srcFactor = GL_ONE;             // to get warning to shut up
304                         common->Error( "GL_State: invalid src blend state bits\n" );
305                         break;
306                 }
307
308                 switch ( stateBits & GLS_DSTBLEND_BITS ) {
309                 case GLS_DSTBLEND_ZERO:
310                         dstFactor = GL_ZERO;
311                         break;
312                 case GLS_DSTBLEND_ONE:
313                         dstFactor = GL_ONE;
314                         break;
315                 case GLS_DSTBLEND_SRC_COLOR:
316                         dstFactor = GL_SRC_COLOR;
317                         break;
318                 case GLS_DSTBLEND_ONE_MINUS_SRC_COLOR:
319                         dstFactor = GL_ONE_MINUS_SRC_COLOR;
320                         break;
321                 case GLS_DSTBLEND_SRC_ALPHA:
322                         dstFactor = GL_SRC_ALPHA;
323                         break;
324                 case GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA:
325                         dstFactor = GL_ONE_MINUS_SRC_ALPHA;
326                         break;
327                 case GLS_DSTBLEND_DST_ALPHA:
328                         dstFactor = GL_DST_ALPHA;
329                         break;
330                 case GLS_DSTBLEND_ONE_MINUS_DST_ALPHA:
331                         dstFactor = GL_ONE_MINUS_DST_ALPHA;
332                         break;
333                 default:
334                         dstFactor = GL_ONE;             // to get warning to shut up
335                         common->Error( "GL_State: invalid dst blend state bits\n" );
336                         break;
337                 }
338
339                 qglBlendFunc( srcFactor, dstFactor );
340         }
341
342         //
343         // check depthmask
344         //
345         if ( diff & GLS_DEPTHMASK ) {
346                 if ( stateBits & GLS_DEPTHMASK ) {
347                         qglDepthMask( GL_FALSE );
348                 } else {
349                         qglDepthMask( GL_TRUE );
350                 }
351         }
352
353         //
354         // check colormask
355         //
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 );
363         }
364
365         //
366         // fill/line mode
367         //
368         if ( diff & GLS_POLYMODE_LINE ) {
369                 if ( stateBits & GLS_POLYMODE_LINE ) {
370                         qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
371                 } else {
372                         qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
373                 }
374         }
375
376         //
377         // alpha test
378         //
379         if ( diff & GLS_ATEST_BITS ) {
380                 switch ( stateBits & GLS_ATEST_BITS ) {
381                 case 0:
382                         qglDisable( GL_ALPHA_TEST );
383                         break;
384                 case GLS_ATEST_EQ_255:
385                         qglEnable( GL_ALPHA_TEST );
386                         qglAlphaFunc( GL_EQUAL, 1 );
387                         break;
388                 case GLS_ATEST_LT_128:
389                         qglEnable( GL_ALPHA_TEST );
390                         qglAlphaFunc( GL_LESS, 0.5 );
391                         break;
392                 case GLS_ATEST_GE_128:
393                         qglEnable( GL_ALPHA_TEST );
394                         qglAlphaFunc( GL_GEQUAL, 0.5 );
395                         break;
396                 default:
397                         assert( 0 );
398                         break;
399                 }
400         }
401
402         backEnd.glState.glStateBits = stateBits;
403 }
404
405
406
407
408 /*
409 ============================================================================
410
411 RENDER BACK END THREAD FUNCTIONS
412
413 ============================================================================
414 */
415
416 /*
417 =============
418 RB_SetGL2D
419
420 This is not used by the normal game paths, just by some tools
421 =============
422 */
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 );
428         }
429         qglMatrixMode( GL_PROJECTION );
430     qglLoadIdentity();
431         qglOrtho( 0, 640, 480, 0, 0, 1 );               // always assume 640x480 virtual coordinates
432         qglMatrixMode( GL_MODELVIEW );
433     qglLoadIdentity();
434
435         GL_State( GLS_DEPTHFUNC_ALWAYS |
436                           GLS_SRCBLEND_SRC_ALPHA |
437                           GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
438
439         GL_Cull( CT_TWO_SIDED );
440
441         qglDisable( GL_DEPTH_TEST );
442         qglDisable( GL_STENCIL_TEST );
443 }
444
445
446
447 /*
448 =============
449 RB_SetBuffer
450
451 =============
452 */
453 static void     RB_SetBuffer( const void *data ) {
454         const setBufferCommand_t        *cmd;
455
456         // see which draw buffer we want to render the frame to
457
458         cmd = (const setBufferCommand_t *)data;
459
460         backEnd.frameCount = cmd->frameCount;
461
462         qglDrawBuffer( cmd->buffer );
463
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() ) {
468                 float c[3];
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 );
475                 } else {
476                         qglClearColor( 0.4f, 0.0f, 0.25f, 1.0f );
477                 }
478                 qglClear( GL_COLOR_BUFFER_BIT );
479         }
480 }
481
482 /*
483 ===============
484 RB_ShowImages
485
486 Draw all the images to the screen, on top of whatever
487 was there.  This is used to test for texture thrashing.
488 ===============
489 */
490 void RB_ShowImages( void ) {
491         int             i;
492         idImage *image;
493         float   x, y, w, h;
494         int             start, end;
495
496         RB_SetGL2D();
497
498         //qglClearColor( 0.2, 0.2, 0.2, 1 );
499         //qglClear( GL_COLOR_BUFFER_BIT );
500
501         qglFinish();
502
503         start = Sys_Milliseconds();
504
505         for ( i = 0 ; i < globalImages->images.Num() ; i++ ) {
506                 image = globalImages->images[i];
507
508                 if ( image->texnum == idImage::TEXTURE_NOT_LOADED && image->partialImage == NULL ) {
509                         continue;
510                 }
511
512                 w = glConfig.vidWidth / 20;
513                 h = glConfig.vidHeight / 15;
514                 x = i % 20 * w;
515                 y = i / 20 * h;
516
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;
521                 }
522
523                 image->Bind();
524                 qglBegin (GL_QUADS);
525                 qglTexCoord2f( 0, 0 );
526                 qglVertex2f( x, y );
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 );
533                 qglEnd();
534         }
535
536         qglFinish();
537
538         end = Sys_Milliseconds();
539         common->Printf( "%i msec to draw all images\n", end - start );
540 }
541
542
543 /*
544 =============
545 RB_SwapBuffers
546
547 =============
548 */
549 const void      RB_SwapBuffers( const void *data ) {
550         // texture swapping test
551         if ( r_showImages.GetInteger() != 0 ) {
552                 RB_ShowImages();
553         }
554
555         // force a gl sync if requested
556         if ( r_finish.GetBool() ) {
557                 qglFinish();
558         }
559
560     RB_LogComment( "***************** RB_SwapBuffers *****************\n\n\n" );
561
562         // don't flip if drawing to front buffer
563         if ( !r_frontBuffer.GetBool() ) {
564             GLimp_SwapBuffers();
565         }
566 }
567
568 /*
569 =============
570 RB_CopyRender
571
572 Copy part of the current framebuffer to an image
573 =============
574 */
575 const void      RB_CopyRender( const void *data ) {
576         const copyRenderCommand_t       *cmd;
577
578         cmd = (const copyRenderCommand_t *)data;
579
580         if ( r_skipCopyTexture.GetBool() ) {
581                 return;
582         }
583
584     RB_LogComment( "***************** RB_CopyRender *****************\n" );
585
586         if (cmd->image) {
587                 cmd->image->CopyFramebuffer( cmd->x, cmd->y, cmd->imageWidth, cmd->imageHeight, false );
588         }
589 }
590
591 /*
592 ====================
593 RB_ExecuteBackEndCommands
594
595 This function will be called syncronously if running without
596 smp extensions, or asyncronously by another thread.
597 ====================
598 */
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;
603
604         if ( cmds->commandId == RC_NOP && !cmds->next ) {
605                 return;
606         }
607
608         backEndStartTime = Sys_Milliseconds();
609
610         // needed for editor rendering
611         RB_SetDefaultGLState();
612
613         // upload any image loads that have completed
614         globalImages->CompleteBackgroundImageLoads();
615
616         for ( ; cmds ; cmds = (const emptyCommand_t *)cmds->next ) {
617                 switch ( cmds->commandId ) {
618                 case RC_NOP:
619                         break;
620                 case RC_DRAW_VIEW:
621                         RB_DrawView( cmds );
622                         if ( ((const drawSurfsCommand_t *)cmds)->viewDef->viewEntitys ) {
623                                 c_draw3d++;
624                         }
625                         else {
626                                 c_draw2d++;
627                         }
628                         break;
629                 case RC_SET_BUFFER:
630                         RB_SetBuffer( cmds );
631                         c_setBuffers++;
632                         break;
633                 case RC_SWAP_BUFFERS:
634                         RB_SwapBuffers( cmds );
635                         c_swapBuffers++;
636                         break;
637                 case RC_COPY_RENDER:
638                         RB_CopyRender( cmds );
639                         c_copyRenders++;
640                         break;
641                 default:
642                         common->Error( "RB_ExecuteBackEndCommands: bad commandId" );
643                         break;
644                 }
645         }
646
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;
650
651         // stop rendering on this thread
652         backEndFinishTime = Sys_Milliseconds();
653         backEnd.pc.msec = backEndFinishTime - backEndStartTime;
654
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;
658         }
659 }