00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "tr_local.h"
00023
00024 volatile renderCommandList_t *renderCommandList;
00025
00026 volatile qboolean renderThreadActive;
00027
00028
00029
00030
00031
00032
00033
00034 void R_PerformanceCounters( void ) {
00035 if ( !r_speeds->integer ) {
00036
00037 Com_Memset( &tr.pc, 0, sizeof( tr.pc ) );
00038 Com_Memset( &backEnd.pc, 0, sizeof( backEnd.pc ) );
00039 return;
00040 }
00041
00042 if (r_speeds->integer == 1) {
00043 ri.Printf (PRINT_ALL, "%i/%i shaders/surfs %i leafs %i verts %i/%i tris %.2f mtex %.2f dc\n",
00044 backEnd.pc.c_shaders, backEnd.pc.c_surfaces, tr.pc.c_leafs, backEnd.pc.c_vertexes,
00045 backEnd.pc.c_indexes/3, backEnd.pc.c_totalIndexes/3,
00046 R_SumOfUsedImages()/(1000000.0f), backEnd.pc.c_overDraw / (float)(glConfig.vidWidth * glConfig.vidHeight) );
00047 } else if (r_speeds->integer == 2) {
00048 ri.Printf (PRINT_ALL, "(patch) %i sin %i sclip %i sout %i bin %i bclip %i bout\n",
00049 tr.pc.c_sphere_cull_patch_in, tr.pc.c_sphere_cull_patch_clip, tr.pc.c_sphere_cull_patch_out,
00050 tr.pc.c_box_cull_patch_in, tr.pc.c_box_cull_patch_clip, tr.pc.c_box_cull_patch_out );
00051 ri.Printf (PRINT_ALL, "(md3) %i sin %i sclip %i sout %i bin %i bclip %i bout\n",
00052 tr.pc.c_sphere_cull_md3_in, tr.pc.c_sphere_cull_md3_clip, tr.pc.c_sphere_cull_md3_out,
00053 tr.pc.c_box_cull_md3_in, tr.pc.c_box_cull_md3_clip, tr.pc.c_box_cull_md3_out );
00054 } else if (r_speeds->integer == 3) {
00055 ri.Printf (PRINT_ALL, "viewcluster: %i\n", tr.viewCluster );
00056 } else if (r_speeds->integer == 4) {
00057 if ( backEnd.pc.c_dlightVertexes ) {
00058 ri.Printf (PRINT_ALL, "dlight srf:%i culled:%i verts:%i tris:%i\n",
00059 tr.pc.c_dlightSurfaces, tr.pc.c_dlightSurfacesCulled,
00060 backEnd.pc.c_dlightVertexes, backEnd.pc.c_dlightIndexes / 3 );
00061 }
00062 }
00063 else if (r_speeds->integer == 5 )
00064 {
00065 ri.Printf( PRINT_ALL, "zFar: %.0f\n", tr.viewParms.zFar );
00066 }
00067 else if (r_speeds->integer == 6 )
00068 {
00069 ri.Printf( PRINT_ALL, "flare adds:%i tests:%i renders:%i\n",
00070 backEnd.pc.c_flareAdds, backEnd.pc.c_flareTests, backEnd.pc.c_flareRenders );
00071 }
00072
00073 Com_Memset( &tr.pc, 0, sizeof( tr.pc ) );
00074 Com_Memset( &backEnd.pc, 0, sizeof( backEnd.pc ) );
00075 }
00076
00077
00078
00079
00080
00081
00082
00083 void R_InitCommandBuffers( void ) {
00084 glConfig.smpActive = qfalse;
00085 if ( r_smp->integer ) {
00086 ri.Printf( PRINT_ALL, "Trying SMP acceleration...\n" );
00087 if ( GLimp_SpawnRenderThread( RB_RenderThread ) ) {
00088 ri.Printf( PRINT_ALL, "...succeeded.\n" );
00089 glConfig.smpActive = qtrue;
00090 } else {
00091 ri.Printf( PRINT_ALL, "...failed.\n" );
00092 }
00093 }
00094 }
00095
00096
00097
00098
00099
00100
00101 void R_ShutdownCommandBuffers( void ) {
00102
00103 if ( glConfig.smpActive ) {
00104 GLimp_WakeRenderer( NULL );
00105 glConfig.smpActive = qfalse;
00106 }
00107 }
00108
00109
00110
00111
00112
00113
00114 int c_blockedOnRender;
00115 int c_blockedOnMain;
00116
00117 void R_IssueRenderCommands( qboolean runPerformanceCounters ) {
00118 renderCommandList_t *cmdList;
00119
00120 cmdList = &backEndData[tr.smpFrame]->commands;
00121 assert(cmdList);
00122
00123 *(int *)(cmdList->cmds + cmdList->used) = RC_END_OF_LIST;
00124
00125
00126 cmdList->used = 0;
00127
00128 if ( glConfig.smpActive ) {
00129
00130 if ( renderThreadActive ) {
00131 c_blockedOnRender++;
00132 if ( r_showSmp->integer ) {
00133 ri.Printf( PRINT_ALL, "R" );
00134 }
00135 } else {
00136 c_blockedOnMain++;
00137 if ( r_showSmp->integer ) {
00138 ri.Printf( PRINT_ALL, "." );
00139 }
00140 }
00141
00142
00143 GLimp_FrontEndSleep();
00144 }
00145
00146
00147
00148 if ( runPerformanceCounters ) {
00149 R_PerformanceCounters();
00150 }
00151
00152
00153 if ( !r_skipBackEnd->integer ) {
00154
00155 if ( !glConfig.smpActive ) {
00156 RB_ExecuteRenderCommands( cmdList->cmds );
00157 } else {
00158 GLimp_WakeRenderer( cmdList );
00159 }
00160 }
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 void R_SyncRenderThread( void ) {
00175 if ( !tr.registered ) {
00176 return;
00177 }
00178 R_IssueRenderCommands( qfalse );
00179
00180 if ( !glConfig.smpActive ) {
00181 return;
00182 }
00183 GLimp_FrontEndSleep();
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 void *R_GetCommandBuffer( int bytes ) {
00195 renderCommandList_t *cmdList;
00196
00197 cmdList = &backEndData[tr.smpFrame]->commands;
00198
00199
00200 if ( cmdList->used + bytes + 4 > MAX_RENDER_COMMANDS ) {
00201 if ( bytes > MAX_RENDER_COMMANDS - 4 ) {
00202 ri.Error( ERR_FATAL, "R_GetCommandBuffer: bad size %i", bytes );
00203 }
00204
00205 return NULL;
00206 }
00207
00208 cmdList->used += bytes;
00209
00210 return cmdList->cmds + cmdList->used - bytes;
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220 void R_AddDrawSurfCmd( drawSurf_t *drawSurfs, int numDrawSurfs ) {
00221 drawSurfsCommand_t *cmd;
00222
00223 cmd = R_GetCommandBuffer( sizeof( *cmd ) );
00224 if ( !cmd ) {
00225 return;
00226 }
00227 cmd->commandId = RC_DRAW_SURFS;
00228
00229 cmd->drawSurfs = drawSurfs;
00230 cmd->numDrawSurfs = numDrawSurfs;
00231
00232 cmd->refdef = tr.refdef;
00233 cmd->viewParms = tr.viewParms;
00234 }
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 void RE_SetColor( const float *rgba ) {
00245 setColorCommand_t *cmd;
00246
00247 if ( !tr.registered ) {
00248 return;
00249 }
00250 cmd = R_GetCommandBuffer( sizeof( *cmd ) );
00251 if ( !cmd ) {
00252 return;
00253 }
00254 cmd->commandId = RC_SET_COLOR;
00255 if ( !rgba ) {
00256 static float colorWhite[4] = { 1, 1, 1, 1 };
00257
00258 rgba = colorWhite;
00259 }
00260
00261 cmd->color[0] = rgba[0];
00262 cmd->color[1] = rgba[1];
00263 cmd->color[2] = rgba[2];
00264 cmd->color[3] = rgba[3];
00265 }
00266
00267
00268
00269
00270
00271
00272
00273 void RE_StretchPic ( float x, float y, float w, float h,
00274 float s1, float t1, float s2, float t2, qhandle_t hShader ) {
00275 stretchPicCommand_t *cmd;
00276
00277 if (!tr.registered) {
00278 return;
00279 }
00280 cmd = R_GetCommandBuffer( sizeof( *cmd ) );
00281 if ( !cmd ) {
00282 return;
00283 }
00284 cmd->commandId = RC_STRETCH_PIC;
00285 cmd->shader = R_GetShaderByHandle( hShader );
00286 cmd->x = x;
00287 cmd->y = y;
00288 cmd->w = w;
00289 cmd->h = h;
00290 cmd->s1 = s1;
00291 cmd->t1 = t1;
00292 cmd->s2 = s2;
00293 cmd->t2 = t2;
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 void RE_BeginFrame( stereoFrame_t stereoFrame ) {
00306 drawBufferCommand_t *cmd;
00307
00308 if ( !tr.registered ) {
00309 return;
00310 }
00311 glState.finishCalled = qfalse;
00312
00313 tr.frameCount++;
00314 tr.frameSceneNum = 0;
00315
00316
00317
00318
00319 if ( r_measureOverdraw->integer )
00320 {
00321 if ( glConfig.stencilBits < 4 )
00322 {
00323 ri.Printf( PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits );
00324 ri.Cvar_Set( "r_measureOverdraw", "0" );
00325 r_measureOverdraw->modified = qfalse;
00326 }
00327 else if ( r_shadows->integer == 2 )
00328 {
00329 ri.Printf( PRINT_ALL, "Warning: stencil shadows and overdraw measurement are mutually exclusive\n" );
00330 ri.Cvar_Set( "r_measureOverdraw", "0" );
00331 r_measureOverdraw->modified = qfalse;
00332 }
00333 else
00334 {
00335 R_SyncRenderThread();
00336 qglEnable( GL_STENCIL_TEST );
00337 qglStencilMask( ~0U );
00338 qglClearStencil( 0U );
00339 qglStencilFunc( GL_ALWAYS, 0U, ~0U );
00340 qglStencilOp( GL_KEEP, GL_INCR, GL_INCR );
00341 }
00342 r_measureOverdraw->modified = qfalse;
00343 }
00344 else
00345 {
00346
00347 if ( r_measureOverdraw->modified ) {
00348 R_SyncRenderThread();
00349 qglDisable( GL_STENCIL_TEST );
00350 }
00351 r_measureOverdraw->modified = qfalse;
00352 }
00353
00354
00355
00356
00357 if ( r_textureMode->modified ) {
00358 R_SyncRenderThread();
00359 GL_TextureMode( r_textureMode->string );
00360 r_textureMode->modified = qfalse;
00361 }
00362
00363
00364
00365
00366 if ( r_gamma->modified ) {
00367 r_gamma->modified = qfalse;
00368
00369 R_SyncRenderThread();
00370 R_SetColorMappings();
00371 }
00372
00373
00374 if ( !r_ignoreGLErrors->integer ) {
00375 int err;
00376
00377 R_SyncRenderThread();
00378 if ( ( err = qglGetError() ) != GL_NO_ERROR ) {
00379 ri.Error( ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!\n", err );
00380 }
00381 }
00382
00383
00384
00385
00386 cmd = R_GetCommandBuffer( sizeof( *cmd ) );
00387 if ( !cmd ) {
00388 return;
00389 }
00390 cmd->commandId = RC_DRAW_BUFFER;
00391
00392 if ( glConfig.stereoEnabled ) {
00393 if ( stereoFrame == STEREO_LEFT ) {
00394 cmd->buffer = (int)GL_BACK_LEFT;
00395 } else if ( stereoFrame == STEREO_RIGHT ) {
00396 cmd->buffer = (int)GL_BACK_RIGHT;
00397 } else {
00398 ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame );
00399 }
00400 } else {
00401 if ( stereoFrame != STEREO_CENTER ) {
00402 ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame );
00403 }
00404 if ( !Q_stricmp( r_drawBuffer->string, "GL_FRONT" ) ) {
00405 cmd->buffer = (int)GL_FRONT;
00406 } else {
00407 cmd->buffer = (int)GL_BACK;
00408 }
00409 }
00410 }
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 void RE_EndFrame( int *frontEndMsec, int *backEndMsec ) {
00421 swapBuffersCommand_t *cmd;
00422
00423 if ( !tr.registered ) {
00424 return;
00425 }
00426 cmd = R_GetCommandBuffer( sizeof( *cmd ) );
00427 if ( !cmd ) {
00428 return;
00429 }
00430 cmd->commandId = RC_SWAP_BUFFERS;
00431
00432 R_IssueRenderCommands( qtrue );
00433
00434
00435
00436 R_ToggleSmpFrame();
00437
00438 if ( frontEndMsec ) {
00439 *frontEndMsec = tr.frontEndMsec;
00440 }
00441 tr.frontEndMsec = 0;
00442 if ( backEndMsec ) {
00443 *backEndMsec = backEnd.pc.msec;
00444 }
00445 backEnd.pc.msec = 0;
00446 }
00447