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 backEndData_t *backEndData[SMP_FRAMES];
00025 backEndState_t backEnd;
00026
00027
00028 static float s_flipMatrix[16] = {
00029
00030
00031 0, 0, -1, 0,
00032 -1, 0, 0, 0,
00033 0, 1, 0, 0,
00034 0, 0, 0, 1
00035 };
00036
00037
00038
00039
00040
00041 void GL_Bind( image_t *image ) {
00042 int texnum;
00043
00044 if ( !image ) {
00045 ri.Printf( PRINT_WARNING, "GL_Bind: NULL image\n" );
00046 texnum = tr.defaultImage->texnum;
00047 } else {
00048 texnum = image->texnum;
00049 }
00050
00051 if ( r_nobind->integer && tr.dlightImage ) {
00052 texnum = tr.dlightImage->texnum;
00053 }
00054
00055 if ( glState.currenttextures[glState.currenttmu] != texnum ) {
00056 image->frameUsed = tr.frameCount;
00057 glState.currenttextures[glState.currenttmu] = texnum;
00058 qglBindTexture (GL_TEXTURE_2D, texnum);
00059 }
00060 }
00061
00062
00063
00064
00065 void GL_SelectTexture( int unit )
00066 {
00067 if ( glState.currenttmu == unit )
00068 {
00069 return;
00070 }
00071
00072 if ( unit == 0 )
00073 {
00074 qglActiveTextureARB( GL_TEXTURE0_ARB );
00075 GLimp_LogComment( "glActiveTextureARB( GL_TEXTURE0_ARB )\n" );
00076 qglClientActiveTextureARB( GL_TEXTURE0_ARB );
00077 GLimp_LogComment( "glClientActiveTextureARB( GL_TEXTURE0_ARB )\n" );
00078 }
00079 else if ( unit == 1 )
00080 {
00081 qglActiveTextureARB( GL_TEXTURE1_ARB );
00082 GLimp_LogComment( "glActiveTextureARB( GL_TEXTURE1_ARB )\n" );
00083 qglClientActiveTextureARB( GL_TEXTURE1_ARB );
00084 GLimp_LogComment( "glClientActiveTextureARB( GL_TEXTURE1_ARB )\n" );
00085 } else {
00086 ri.Error( ERR_DROP, "GL_SelectTexture: unit = %i", unit );
00087 }
00088
00089 glState.currenttmu = unit;
00090 }
00091
00092
00093
00094
00095
00096 void GL_BindMultitexture( image_t *image0, GLuint env0, image_t *image1, GLuint env1 ) {
00097 int texnum0, texnum1;
00098
00099 texnum0 = image0->texnum;
00100 texnum1 = image1->texnum;
00101
00102 if ( r_nobind->integer && tr.dlightImage ) {
00103 texnum0 = texnum1 = tr.dlightImage->texnum;
00104 }
00105
00106 if ( glState.currenttextures[1] != texnum1 ) {
00107 GL_SelectTexture( 1 );
00108 image1->frameUsed = tr.frameCount;
00109 glState.currenttextures[1] = texnum1;
00110 qglBindTexture( GL_TEXTURE_2D, texnum1 );
00111 }
00112 if ( glState.currenttextures[0] != texnum0 ) {
00113 GL_SelectTexture( 0 );
00114 image0->frameUsed = tr.frameCount;
00115 glState.currenttextures[0] = texnum0;
00116 qglBindTexture( GL_TEXTURE_2D, texnum0 );
00117 }
00118 }
00119
00120
00121
00122
00123
00124 void GL_Cull( int cullType ) {
00125 if ( glState.faceCulling == cullType ) {
00126 return;
00127 }
00128
00129 glState.faceCulling = cullType;
00130
00131 if ( cullType == CT_TWO_SIDED )
00132 {
00133 qglDisable( GL_CULL_FACE );
00134 }
00135 else
00136 {
00137 qglEnable( GL_CULL_FACE );
00138
00139 if ( cullType == CT_BACK_SIDED )
00140 {
00141 if ( backEnd.viewParms.isMirror )
00142 {
00143 qglCullFace( GL_FRONT );
00144 }
00145 else
00146 {
00147 qglCullFace( GL_BACK );
00148 }
00149 }
00150 else
00151 {
00152 if ( backEnd.viewParms.isMirror )
00153 {
00154 qglCullFace( GL_BACK );
00155 }
00156 else
00157 {
00158 qglCullFace( GL_FRONT );
00159 }
00160 }
00161 }
00162 }
00163
00164
00165
00166
00167 void GL_TexEnv( int env )
00168 {
00169 if ( env == glState.texEnv[glState.currenttmu] )
00170 {
00171 return;
00172 }
00173
00174 glState.texEnv[glState.currenttmu] = env;
00175
00176
00177 switch ( env )
00178 {
00179 case GL_MODULATE:
00180 qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
00181 break;
00182 case GL_REPLACE:
00183 qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
00184 break;
00185 case GL_DECAL:
00186 qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
00187 break;
00188 case GL_ADD:
00189 qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD );
00190 break;
00191 default:
00192 ri.Error( ERR_DROP, "GL_TexEnv: invalid env '%d' passed\n", env );
00193 break;
00194 }
00195 }
00196
00197
00198
00199
00200
00201
00202
00203 void GL_State( unsigned long stateBits )
00204 {
00205 unsigned long diff = stateBits ^ glState.glStateBits;
00206
00207 if ( !diff )
00208 {
00209 return;
00210 }
00211
00212
00213
00214
00215 if ( diff & GLS_DEPTHFUNC_EQUAL )
00216 {
00217 if ( stateBits & GLS_DEPTHFUNC_EQUAL )
00218 {
00219 qglDepthFunc( GL_EQUAL );
00220 }
00221 else
00222 {
00223 qglDepthFunc( GL_LEQUAL );
00224 }
00225 }
00226
00227
00228
00229
00230 if ( diff & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) )
00231 {
00232 GLenum srcFactor, dstFactor;
00233
00234 if ( stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) )
00235 {
00236 switch ( stateBits & GLS_SRCBLEND_BITS )
00237 {
00238 case GLS_SRCBLEND_ZERO:
00239 srcFactor = GL_ZERO;
00240 break;
00241 case GLS_SRCBLEND_ONE:
00242 srcFactor = GL_ONE;
00243 break;
00244 case GLS_SRCBLEND_DST_COLOR:
00245 srcFactor = GL_DST_COLOR;
00246 break;
00247 case GLS_SRCBLEND_ONE_MINUS_DST_COLOR:
00248 srcFactor = GL_ONE_MINUS_DST_COLOR;
00249 break;
00250 case GLS_SRCBLEND_SRC_ALPHA:
00251 srcFactor = GL_SRC_ALPHA;
00252 break;
00253 case GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA:
00254 srcFactor = GL_ONE_MINUS_SRC_ALPHA;
00255 break;
00256 case GLS_SRCBLEND_DST_ALPHA:
00257 srcFactor = GL_DST_ALPHA;
00258 break;
00259 case GLS_SRCBLEND_ONE_MINUS_DST_ALPHA:
00260 srcFactor = GL_ONE_MINUS_DST_ALPHA;
00261 break;
00262 case GLS_SRCBLEND_ALPHA_SATURATE:
00263 srcFactor = GL_SRC_ALPHA_SATURATE;
00264 break;
00265 default:
00266 srcFactor = GL_ONE;
00267 ri.Error( ERR_DROP, "GL_State: invalid src blend state bits\n" );
00268 break;
00269 }
00270
00271 switch ( stateBits & GLS_DSTBLEND_BITS )
00272 {
00273 case GLS_DSTBLEND_ZERO:
00274 dstFactor = GL_ZERO;
00275 break;
00276 case GLS_DSTBLEND_ONE:
00277 dstFactor = GL_ONE;
00278 break;
00279 case GLS_DSTBLEND_SRC_COLOR:
00280 dstFactor = GL_SRC_COLOR;
00281 break;
00282 case GLS_DSTBLEND_ONE_MINUS_SRC_COLOR:
00283 dstFactor = GL_ONE_MINUS_SRC_COLOR;
00284 break;
00285 case GLS_DSTBLEND_SRC_ALPHA:
00286 dstFactor = GL_SRC_ALPHA;
00287 break;
00288 case GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA:
00289 dstFactor = GL_ONE_MINUS_SRC_ALPHA;
00290 break;
00291 case GLS_DSTBLEND_DST_ALPHA:
00292 dstFactor = GL_DST_ALPHA;
00293 break;
00294 case GLS_DSTBLEND_ONE_MINUS_DST_ALPHA:
00295 dstFactor = GL_ONE_MINUS_DST_ALPHA;
00296 break;
00297 default:
00298 dstFactor = GL_ONE;
00299 ri.Error( ERR_DROP, "GL_State: invalid dst blend state bits\n" );
00300 break;
00301 }
00302
00303 qglEnable( GL_BLEND );
00304 qglBlendFunc( srcFactor, dstFactor );
00305 }
00306 else
00307 {
00308 qglDisable( GL_BLEND );
00309 }
00310 }
00311
00312
00313
00314
00315 if ( diff & GLS_DEPTHMASK_TRUE )
00316 {
00317 if ( stateBits & GLS_DEPTHMASK_TRUE )
00318 {
00319 qglDepthMask( GL_TRUE );
00320 }
00321 else
00322 {
00323 qglDepthMask( GL_FALSE );
00324 }
00325 }
00326
00327
00328
00329
00330 if ( diff & GLS_POLYMODE_LINE )
00331 {
00332 if ( stateBits & GLS_POLYMODE_LINE )
00333 {
00334 qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
00335 }
00336 else
00337 {
00338 qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
00339 }
00340 }
00341
00342
00343
00344
00345 if ( diff & GLS_DEPTHTEST_DISABLE )
00346 {
00347 if ( stateBits & GLS_DEPTHTEST_DISABLE )
00348 {
00349 qglDisable( GL_DEPTH_TEST );
00350 }
00351 else
00352 {
00353 qglEnable( GL_DEPTH_TEST );
00354 }
00355 }
00356
00357
00358
00359
00360 if ( diff & GLS_ATEST_BITS )
00361 {
00362 switch ( stateBits & GLS_ATEST_BITS )
00363 {
00364 case 0:
00365 qglDisable( GL_ALPHA_TEST );
00366 break;
00367 case GLS_ATEST_GT_0:
00368 qglEnable( GL_ALPHA_TEST );
00369 qglAlphaFunc( GL_GREATER, 0.0f );
00370 break;
00371 case GLS_ATEST_LT_80:
00372 qglEnable( GL_ALPHA_TEST );
00373 qglAlphaFunc( GL_LESS, 0.5f );
00374 break;
00375 case GLS_ATEST_GE_80:
00376 qglEnable( GL_ALPHA_TEST );
00377 qglAlphaFunc( GL_GEQUAL, 0.5f );
00378 break;
00379 default:
00380 assert( 0 );
00381 break;
00382 }
00383 }
00384
00385 glState.glStateBits = stateBits;
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397 static void RB_Hyperspace( void ) {
00398 float c;
00399
00400 if ( !backEnd.isHyperspace ) {
00401
00402 }
00403
00404 c = ( backEnd.refdef.time & 255 ) / 255.0f;
00405 qglClearColor( c, c, c, 1 );
00406 qglClear( GL_COLOR_BUFFER_BIT );
00407
00408 backEnd.isHyperspace = qtrue;
00409 }
00410
00411
00412 static void SetViewportAndScissor( void ) {
00413 qglMatrixMode(GL_PROJECTION);
00414 qglLoadMatrixf( backEnd.viewParms.projectionMatrix );
00415 qglMatrixMode(GL_MODELVIEW);
00416
00417
00418 qglViewport( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
00419 backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight );
00420 qglScissor( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
00421 backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight );
00422 }
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 void RB_BeginDrawingView (void) {
00433 int clearBits = 0;
00434
00435
00436 if ( r_finish->integer == 1 && !glState.finishCalled ) {
00437 qglFinish ();
00438 glState.finishCalled = qtrue;
00439 }
00440 if ( r_finish->integer == 0 ) {
00441 glState.finishCalled = qtrue;
00442 }
00443
00444
00445
00446 backEnd.projection2D = qfalse;
00447
00448
00449
00450
00451 SetViewportAndScissor();
00452
00453
00454 GL_State( GLS_DEFAULT );
00455
00456 clearBits = GL_DEPTH_BUFFER_BIT;
00457
00458 if ( r_measureOverdraw->integer || r_shadows->integer == 2 )
00459 {
00460 clearBits |= GL_STENCIL_BUFFER_BIT;
00461 }
00462 if ( r_fastsky->integer && !( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) )
00463 {
00464 clearBits |= GL_COLOR_BUFFER_BIT;
00465 #ifdef _DEBUG
00466 qglClearColor( 0.8f, 0.7f, 0.4f, 1.0f );
00467 #else
00468 qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
00469 #endif
00470 }
00471 qglClear( clearBits );
00472
00473 if ( ( backEnd.refdef.rdflags & RDF_HYPERSPACE ) )
00474 {
00475 RB_Hyperspace();
00476 return;
00477 }
00478 else
00479 {
00480 backEnd.isHyperspace = qfalse;
00481 }
00482
00483 glState.faceCulling = -1;
00484
00485
00486 backEnd.skyRenderedThisView = qfalse;
00487
00488
00489 if ( backEnd.viewParms.isPortal ) {
00490 float plane[4];
00491 double plane2[4];
00492
00493 plane[0] = backEnd.viewParms.portalPlane.normal[0];
00494 plane[1] = backEnd.viewParms.portalPlane.normal[1];
00495 plane[2] = backEnd.viewParms.portalPlane.normal[2];
00496 plane[3] = backEnd.viewParms.portalPlane.dist;
00497
00498 plane2[0] = DotProduct (backEnd.viewParms.or.axis[0], plane);
00499 plane2[1] = DotProduct (backEnd.viewParms.or.axis[1], plane);
00500 plane2[2] = DotProduct (backEnd.viewParms.or.axis[2], plane);
00501 plane2[3] = DotProduct (plane, backEnd.viewParms.or.origin) - plane[3];
00502
00503 qglLoadMatrixf( s_flipMatrix );
00504 qglClipPlane (GL_CLIP_PLANE0, plane2);
00505 qglEnable (GL_CLIP_PLANE0);
00506 } else {
00507 qglDisable (GL_CLIP_PLANE0);
00508 }
00509 }
00510
00511
00512 #define MAC_EVENT_PUMP_MSEC 5
00513
00514
00515
00516
00517
00518
00519 void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
00520 shader_t *shader, *oldShader;
00521 int fogNum, oldFogNum;
00522 int entityNum, oldEntityNum;
00523 int dlighted, oldDlighted;
00524 qboolean depthRange, oldDepthRange;
00525 int i;
00526 drawSurf_t *drawSurf;
00527 int oldSort;
00528 float originalTime;
00529 #ifdef __MACOS__
00530 int macEventTime;
00531
00532 Sys_PumpEvents();
00533
00534
00535
00536 macEventTime = ri.Milliseconds() + MAC_EVENT_PUMP_MSEC;
00537 #endif
00538
00539
00540 originalTime = backEnd.refdef.floatTime;
00541
00542
00543 RB_BeginDrawingView ();
00544
00545
00546 oldEntityNum = -1;
00547 backEnd.currentEntity = &tr.worldEntity;
00548 oldShader = NULL;
00549 oldFogNum = -1;
00550 oldDepthRange = qfalse;
00551 oldDlighted = qfalse;
00552 oldSort = -1;
00553 depthRange = qfalse;
00554
00555 backEnd.pc.c_surfaces += numDrawSurfs;
00556
00557 for (i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++) {
00558 if ( drawSurf->sort == oldSort ) {
00559
00560 rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
00561 continue;
00562 }
00563 oldSort = drawSurf->sort;
00564 R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted );
00565
00566
00567
00568
00569
00570 if (shader != oldShader || fogNum != oldFogNum || dlighted != oldDlighted
00571 || ( entityNum != oldEntityNum && !shader->entityMergable ) ) {
00572 if (oldShader != NULL) {
00573 #ifdef __MACOS__ // crutch up the mac's limited buffer queue size
00574 int t;
00575
00576 t = ri.Milliseconds();
00577 if ( t > macEventTime ) {
00578 macEventTime = t + MAC_EVENT_PUMP_MSEC;
00579 Sys_PumpEvents();
00580 }
00581 #endif
00582 RB_EndSurface();
00583 }
00584 RB_BeginSurface( shader, fogNum );
00585 oldShader = shader;
00586 oldFogNum = fogNum;
00587 oldDlighted = dlighted;
00588 }
00589
00590
00591
00592
00593 if ( entityNum != oldEntityNum ) {
00594 depthRange = qfalse;
00595
00596 if ( entityNum != ENTITYNUM_WORLD ) {
00597 backEnd.currentEntity = &backEnd.refdef.entities[entityNum];
00598 backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime;
00599
00600
00601 tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
00602
00603
00604 R_RotateForEntity( backEnd.currentEntity, &backEnd.viewParms, &backEnd.or );
00605
00606
00607 if ( backEnd.currentEntity->needDlights ) {
00608 R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or );
00609 }
00610
00611 if ( backEnd.currentEntity->e.renderfx & RF_DEPTHHACK ) {
00612
00613 depthRange = qtrue;
00614 }
00615 } else {
00616 backEnd.currentEntity = &tr.worldEntity;
00617 backEnd.refdef.floatTime = originalTime;
00618 backEnd.or = backEnd.viewParms.world;
00619
00620
00621 tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
00622 R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or );
00623 }
00624
00625 qglLoadMatrixf( backEnd.or.modelMatrix );
00626
00627
00628
00629
00630 if ( oldDepthRange != depthRange ) {
00631 if ( depthRange ) {
00632 qglDepthRange (0, 0.3);
00633 } else {
00634 qglDepthRange (0, 1);
00635 }
00636 oldDepthRange = depthRange;
00637 }
00638
00639 oldEntityNum = entityNum;
00640 }
00641
00642
00643 rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
00644 }
00645
00646 backEnd.refdef.floatTime = originalTime;
00647
00648
00649 if (oldShader != NULL) {
00650 RB_EndSurface();
00651 }
00652
00653
00654 qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
00655 if ( depthRange ) {
00656 qglDepthRange (0, 1);
00657 }
00658
00659 #if 0
00660 RB_DrawSun();
00661 #endif
00662
00663 RB_ShadowFinish();
00664
00665
00666 RB_RenderFlares();
00667
00668 #ifdef __MACOS__
00669 Sys_PumpEvents();
00670 #endif
00671 }
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688 void RB_SetGL2D (void) {
00689 backEnd.projection2D = qtrue;
00690
00691
00692 qglViewport( 0, 0, glConfig.vidWidth, glConfig.vidHeight );
00693 qglScissor( 0, 0, glConfig.vidWidth, glConfig.vidHeight );
00694 qglMatrixMode(GL_PROJECTION);
00695 qglLoadIdentity ();
00696 qglOrtho (0, glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1);
00697 qglMatrixMode(GL_MODELVIEW);
00698 qglLoadIdentity ();
00699
00700 GL_State( GLS_DEPTHTEST_DISABLE |
00701 GLS_SRCBLEND_SRC_ALPHA |
00702 GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
00703
00704 qglDisable( GL_CULL_FACE );
00705 qglDisable( GL_CLIP_PLANE0 );
00706
00707
00708 backEnd.refdef.time = ri.Milliseconds();
00709 backEnd.refdef.floatTime = backEnd.refdef.time * 0.001f;
00710 }
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722 void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
00723 int i, j;
00724 int start, end;
00725
00726 if ( !tr.registered ) {
00727 return;
00728 }
00729 R_SyncRenderThread();
00730
00731
00732 qglFinish();
00733
00734 start = end = 0;
00735 if ( r_speeds->integer ) {
00736 start = ri.Milliseconds();
00737 }
00738
00739
00740 for ( i = 0 ; ( 1 << i ) < cols ; i++ ) {
00741 }
00742 for ( j = 0 ; ( 1 << j ) < rows ; j++ ) {
00743 }
00744 if ( ( 1 << i ) != cols || ( 1 << j ) != rows) {
00745 ri.Error (ERR_DROP, "Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows);
00746 }
00747
00748 GL_Bind( tr.scratchImage[client] );
00749
00750
00751 if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) {
00752 tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
00753 tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
00754 qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
00755 qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
00756 qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
00757 qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
00758 qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
00759 } else {
00760 if (dirty) {
00761
00762
00763 qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
00764 }
00765 }
00766
00767 if ( r_speeds->integer ) {
00768 end = ri.Milliseconds();
00769 ri.Printf( PRINT_ALL, "qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start );
00770 }
00771
00772 RB_SetGL2D();
00773
00774 qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight );
00775
00776 qglBegin (GL_QUADS);
00777 qglTexCoord2f ( 0.5f / cols, 0.5f / rows );
00778 qglVertex2f (x, y);
00779 qglTexCoord2f ( ( cols - 0.5f ) / cols , 0.5f / rows );
00780 qglVertex2f (x+w, y);
00781 qglTexCoord2f ( ( cols - 0.5f ) / cols, ( rows - 0.5f ) / rows );
00782 qglVertex2f (x+w, y+h);
00783 qglTexCoord2f ( 0.5f / cols, ( rows - 0.5f ) / rows );
00784 qglVertex2f (x, y+h);
00785 qglEnd ();
00786 }
00787
00788 void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
00789
00790 GL_Bind( tr.scratchImage[client] );
00791
00792
00793 if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) {
00794 tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
00795 tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
00796 qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
00797 qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
00798 qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
00799 qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
00800 qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
00801 } else {
00802 if (dirty) {
00803
00804
00805 qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
00806 }
00807 }
00808 }
00809
00810
00811
00812
00813
00814
00815
00816
00817 const void *RB_SetColor( const void *data ) {
00818 const setColorCommand_t *cmd;
00819
00820 cmd = (const setColorCommand_t *)data;
00821
00822 backEnd.color2D[0] = cmd->color[0] * 255;
00823 backEnd.color2D[1] = cmd->color[1] * 255;
00824 backEnd.color2D[2] = cmd->color[2] * 255;
00825 backEnd.color2D[3] = cmd->color[3] * 255;
00826
00827 return (const void *)(cmd + 1);
00828 }
00829
00830
00831
00832
00833
00834
00835 const void *RB_StretchPic ( const void *data ) {
00836 const stretchPicCommand_t *cmd;
00837 shader_t *shader;
00838 int numVerts, numIndexes;
00839
00840 cmd = (const stretchPicCommand_t *)data;
00841
00842 if ( !backEnd.projection2D ) {
00843 RB_SetGL2D();
00844 }
00845
00846 shader = cmd->shader;
00847 if ( shader != tess.shader ) {
00848 if ( tess.numIndexes ) {
00849 RB_EndSurface();
00850 }
00851 backEnd.currentEntity = &backEnd.entity2D;
00852 RB_BeginSurface( shader, 0 );
00853 }
00854
00855 RB_CHECKOVERFLOW( 4, 6 );
00856 numVerts = tess.numVertexes;
00857 numIndexes = tess.numIndexes;
00858
00859 tess.numVertexes += 4;
00860 tess.numIndexes += 6;
00861
00862 tess.indexes[ numIndexes ] = numVerts + 3;
00863 tess.indexes[ numIndexes + 1 ] = numVerts + 0;
00864 tess.indexes[ numIndexes + 2 ] = numVerts + 2;
00865 tess.indexes[ numIndexes + 3 ] = numVerts + 2;
00866 tess.indexes[ numIndexes + 4 ] = numVerts + 0;
00867 tess.indexes[ numIndexes + 5 ] = numVerts + 1;
00868
00869 *(int *)tess.vertexColors[ numVerts ] =
00870 *(int *)tess.vertexColors[ numVerts + 1 ] =
00871 *(int *)tess.vertexColors[ numVerts + 2 ] =
00872 *(int *)tess.vertexColors[ numVerts + 3 ] = *(int *)backEnd.color2D;
00873
00874 tess.xyz[ numVerts ][0] = cmd->x;
00875 tess.xyz[ numVerts ][1] = cmd->y;
00876 tess.xyz[ numVerts ][2] = 0;
00877
00878 tess.texCoords[ numVerts ][0][0] = cmd->s1;
00879 tess.texCoords[ numVerts ][0][1] = cmd->t1;
00880
00881 tess.xyz[ numVerts + 1 ][0] = cmd->x + cmd->w;
00882 tess.xyz[ numVerts + 1 ][1] = cmd->y;
00883 tess.xyz[ numVerts + 1 ][2] = 0;
00884
00885 tess.texCoords[ numVerts + 1 ][0][0] = cmd->s2;
00886 tess.texCoords[ numVerts + 1 ][0][1] = cmd->t1;
00887
00888 tess.xyz[ numVerts + 2 ][0] = cmd->x + cmd->w;
00889 tess.xyz[ numVerts + 2 ][1] = cmd->y + cmd->h;
00890 tess.xyz[ numVerts + 2 ][2] = 0;
00891
00892 tess.texCoords[ numVerts + 2 ][0][0] = cmd->s2;
00893 tess.texCoords[ numVerts + 2 ][0][1] = cmd->t2;
00894
00895 tess.xyz[ numVerts + 3 ][0] = cmd->x;
00896 tess.xyz[ numVerts + 3 ][1] = cmd->y + cmd->h;
00897 tess.xyz[ numVerts + 3 ][2] = 0;
00898
00899 tess.texCoords[ numVerts + 3 ][0][0] = cmd->s1;
00900 tess.texCoords[ numVerts + 3 ][0][1] = cmd->t2;
00901
00902 return (const void *)(cmd + 1);
00903 }
00904
00905
00906
00907
00908
00909
00910
00911
00912 const void *RB_DrawSurfs( const void *data ) {
00913 const drawSurfsCommand_t *cmd;
00914
00915
00916 if ( tess.numIndexes ) {
00917 RB_EndSurface();
00918 }
00919
00920 cmd = (const drawSurfsCommand_t *)data;
00921
00922 backEnd.refdef = cmd->refdef;
00923 backEnd.viewParms = cmd->viewParms;
00924
00925 RB_RenderDrawSurfList( cmd->drawSurfs, cmd->numDrawSurfs );
00926
00927 return (const void *)(cmd + 1);
00928 }
00929
00930
00931
00932
00933
00934
00935
00936
00937 const void *RB_DrawBuffer( const void *data ) {
00938 const drawBufferCommand_t *cmd;
00939
00940 cmd = (const drawBufferCommand_t *)data;
00941
00942 qglDrawBuffer( cmd->buffer );
00943
00944
00945 if ( r_clear->integer ) {
00946 qglClearColor( 1, 0, 0.5, 1 );
00947 qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
00948 }
00949
00950 return (const void *)(cmd + 1);
00951 }
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963 void RB_ShowImages( void ) {
00964 int i;
00965 image_t *image;
00966 float x, y, w, h;
00967 int start, end;
00968
00969 if ( !backEnd.projection2D ) {
00970 RB_SetGL2D();
00971 }
00972
00973 qglClear( GL_COLOR_BUFFER_BIT );
00974
00975 qglFinish();
00976
00977 start = ri.Milliseconds();
00978
00979 for ( i=0 ; i<tr.numImages ; i++ ) {
00980 image = tr.images[i];
00981
00982 w = glConfig.vidWidth / 20;
00983 h = glConfig.vidHeight / 15;
00984 x = i % 20 * w;
00985 y = i / 20 * h;
00986
00987
00988 if ( r_showImages->integer == 2 ) {
00989 w *= image->uploadWidth / 512.0f;
00990 h *= image->uploadHeight / 512.0f;
00991 }
00992
00993 GL_Bind( image );
00994 qglBegin (GL_QUADS);
00995 qglTexCoord2f( 0, 0 );
00996 qglVertex2f( x, y );
00997 qglTexCoord2f( 1, 0 );
00998 qglVertex2f( x + w, y );
00999 qglTexCoord2f( 1, 1 );
01000 qglVertex2f( x + w, y + h );
01001 qglTexCoord2f( 0, 1 );
01002 qglVertex2f( x, y + h );
01003 qglEnd();
01004 }
01005
01006 qglFinish();
01007
01008 end = ri.Milliseconds();
01009 ri.Printf( PRINT_ALL, "%i msec to draw all images\n", end - start );
01010
01011 }
01012
01013
01014
01015
01016
01017
01018
01019
01020 const void *RB_SwapBuffers( const void *data ) {
01021 const swapBuffersCommand_t *cmd;
01022
01023
01024 if ( tess.numIndexes ) {
01025 RB_EndSurface();
01026 }
01027
01028
01029 if ( r_showImages->integer ) {
01030 RB_ShowImages();
01031 }
01032
01033 cmd = (const swapBuffersCommand_t *)data;
01034
01035
01036
01037 if ( r_measureOverdraw->integer ) {
01038 int i;
01039 long sum = 0;
01040 unsigned char *stencilReadback;
01041
01042 stencilReadback = ri.Hunk_AllocateTempMemory( glConfig.vidWidth * glConfig.vidHeight );
01043 qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback );
01044
01045 for ( i = 0; i < glConfig.vidWidth * glConfig.vidHeight; i++ ) {
01046 sum += stencilReadback[i];
01047 }
01048
01049 backEnd.pc.c_overDraw += sum;
01050 ri.Hunk_FreeTempMemory( stencilReadback );
01051 }
01052
01053
01054 if ( !glState.finishCalled ) {
01055 qglFinish();
01056 }
01057
01058 GLimp_LogComment( "***************** RB_SwapBuffers *****************\n\n\n" );
01059
01060 GLimp_EndFrame();
01061
01062 backEnd.projection2D = qfalse;
01063
01064 return (const void *)(cmd + 1);
01065 }
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075 void RB_ExecuteRenderCommands( const void *data ) {
01076 int t1, t2;
01077
01078 t1 = ri.Milliseconds ();
01079
01080 if ( !r_smp->integer || data == backEndData[0]->commands.cmds ) {
01081 backEnd.smpFrame = 0;
01082 } else {
01083 backEnd.smpFrame = 1;
01084 }
01085
01086 while ( 1 ) {
01087 switch ( *(const int *)data ) {
01088 case RC_SET_COLOR:
01089 data = RB_SetColor( data );
01090 break;
01091 case RC_STRETCH_PIC:
01092 data = RB_StretchPic( data );
01093 break;
01094 case RC_DRAW_SURFS:
01095 data = RB_DrawSurfs( data );
01096 break;
01097 case RC_DRAW_BUFFER:
01098 data = RB_DrawBuffer( data );
01099 break;
01100 case RC_SWAP_BUFFERS:
01101 data = RB_SwapBuffers( data );
01102 break;
01103 case RC_SCREENSHOT:
01104 data = RB_TakeScreenshotCmd( data );
01105 break;
01106
01107 case RC_END_OF_LIST:
01108 default:
01109
01110 t2 = ri.Milliseconds ();
01111 backEnd.pc.msec = t2 - t1;
01112 return;
01113 }
01114 }
01115
01116 }
01117
01118
01119
01120
01121
01122
01123
01124 void RB_RenderThread( void ) {
01125 const void *data;
01126
01127
01128 while ( 1 ) {
01129
01130 data = GLimp_RendererSleep();
01131
01132 if ( !data ) {
01133 return;
01134 }
01135
01136 renderThreadActive = qtrue;
01137
01138 RB_ExecuteRenderCommands( data );
01139
01140 renderThreadActive = qfalse;
01141 }
01142 }
01143