2
===========================================================================
3
Copyright (C) 1999-2005 Id Software, Inc.
5
This file is part of Quake III Arena source code.
7
Quake III Arena source code is free software; you can redistribute it
8
and/or modify it under the terms of the GNU General Public License as
9
published by the Free Software Foundation; either version 2 of the License,
10
or (at your option) any later version.
12
Quake III Arena source code is distributed in the hope that it will be
13
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with Quake III Arena source code; if not, write to the Free Software
19
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
===========================================================================
24
backEndData_t *backEndData[SMP_FRAMES];
25
backEndState_t backEnd;
28
static float s_flipMatrix[16] = {
29
// convert from our coordinate system (looking down X)
30
// to OpenGL's coordinate system (looking down -Z)
41
void GL_Bind( image_t *image ) {
45
ri.Printf( PRINT_WARNING, "GL_Bind: NULL image\n" );
46
texnum = tr.defaultImage->texnum;
48
texnum = image->texnum;
51
if ( r_nobind->integer && tr.dlightImage ) { // performance evaluation option
52
texnum = tr.dlightImage->texnum;
55
if ( glState.currenttextures[glState.currenttmu] != texnum ) {
56
image->frameUsed = tr.frameCount;
57
glState.currenttextures[glState.currenttmu] = texnum;
58
qglBindTexture (GL_TEXTURE_2D, texnum);
65
void GL_SelectTexture( int unit )
67
if ( glState.currenttmu == unit )
74
qglActiveTextureARB( GL_TEXTURE0_ARB );
75
GLimp_LogComment( "glActiveTextureARB( GL_TEXTURE0_ARB )\n" );
76
qglClientActiveTextureARB( GL_TEXTURE0_ARB );
77
GLimp_LogComment( "glClientActiveTextureARB( GL_TEXTURE0_ARB )\n" );
81
qglActiveTextureARB( GL_TEXTURE1_ARB );
82
GLimp_LogComment( "glActiveTextureARB( GL_TEXTURE1_ARB )\n" );
83
qglClientActiveTextureARB( GL_TEXTURE1_ARB );
84
GLimp_LogComment( "glClientActiveTextureARB( GL_TEXTURE1_ARB )\n" );
86
ri.Error( ERR_DROP, "GL_SelectTexture: unit = %i", unit );
89
glState.currenttmu = unit;
94
** GL_BindMultitexture
96
void GL_BindMultitexture( image_t *image0, GLuint env0, image_t *image1, GLuint env1 ) {
99
texnum0 = image0->texnum;
100
texnum1 = image1->texnum;
102
if ( r_nobind->integer && tr.dlightImage ) { // performance evaluation option
103
texnum0 = texnum1 = tr.dlightImage->texnum;
106
if ( glState.currenttextures[1] != texnum1 ) {
107
GL_SelectTexture( 1 );
108
image1->frameUsed = tr.frameCount;
109
glState.currenttextures[1] = texnum1;
110
qglBindTexture( GL_TEXTURE_2D, texnum1 );
112
if ( glState.currenttextures[0] != texnum0 ) {
113
GL_SelectTexture( 0 );
114
image0->frameUsed = tr.frameCount;
115
glState.currenttextures[0] = texnum0;
116
qglBindTexture( GL_TEXTURE_2D, texnum0 );
124
void GL_Cull( int cullType ) {
125
if ( glState.faceCulling == cullType ) {
129
glState.faceCulling = cullType;
131
if ( cullType == CT_TWO_SIDED )
133
qglDisable( GL_CULL_FACE );
137
qglEnable( GL_CULL_FACE );
139
if ( cullType == CT_BACK_SIDED )
141
if ( backEnd.viewParms.isMirror )
143
qglCullFace( GL_FRONT );
147
qglCullFace( GL_BACK );
152
if ( backEnd.viewParms.isMirror )
154
qglCullFace( GL_BACK );
158
qglCullFace( GL_FRONT );
167
void GL_TexEnv( int env )
169
if ( env == glState.texEnv[glState.currenttmu] )
174
glState.texEnv[glState.currenttmu] = env;
180
qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
183
qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
186
qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
189
qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD );
192
ri.Error( ERR_DROP, "GL_TexEnv: invalid env '%d' passed\n", env );
200
** This routine is responsible for setting the most commonly changed state
203
void GL_State( unsigned long stateBits )
205
unsigned long diff = stateBits ^ glState.glStateBits;
213
// check depthFunc bits
215
if ( diff & GLS_DEPTHFUNC_EQUAL )
217
if ( stateBits & GLS_DEPTHFUNC_EQUAL )
219
qglDepthFunc( GL_EQUAL );
223
qglDepthFunc( GL_LEQUAL );
230
if ( diff & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) )
232
GLenum srcFactor, dstFactor;
234
if ( stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) )
236
switch ( stateBits & GLS_SRCBLEND_BITS )
238
case GLS_SRCBLEND_ZERO:
241
case GLS_SRCBLEND_ONE:
244
case GLS_SRCBLEND_DST_COLOR:
245
srcFactor = GL_DST_COLOR;
247
case GLS_SRCBLEND_ONE_MINUS_DST_COLOR:
248
srcFactor = GL_ONE_MINUS_DST_COLOR;
250
case GLS_SRCBLEND_SRC_ALPHA:
251
srcFactor = GL_SRC_ALPHA;
253
case GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA:
254
srcFactor = GL_ONE_MINUS_SRC_ALPHA;
256
case GLS_SRCBLEND_DST_ALPHA:
257
srcFactor = GL_DST_ALPHA;
259
case GLS_SRCBLEND_ONE_MINUS_DST_ALPHA:
260
srcFactor = GL_ONE_MINUS_DST_ALPHA;
262
case GLS_SRCBLEND_ALPHA_SATURATE:
263
srcFactor = GL_SRC_ALPHA_SATURATE;
266
srcFactor = GL_ONE; // to get warning to shut up
267
ri.Error( ERR_DROP, "GL_State: invalid src blend state bits\n" );
271
switch ( stateBits & GLS_DSTBLEND_BITS )
273
case GLS_DSTBLEND_ZERO:
276
case GLS_DSTBLEND_ONE:
279
case GLS_DSTBLEND_SRC_COLOR:
280
dstFactor = GL_SRC_COLOR;
282
case GLS_DSTBLEND_ONE_MINUS_SRC_COLOR:
283
dstFactor = GL_ONE_MINUS_SRC_COLOR;
285
case GLS_DSTBLEND_SRC_ALPHA:
286
dstFactor = GL_SRC_ALPHA;
288
case GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA:
289
dstFactor = GL_ONE_MINUS_SRC_ALPHA;
291
case GLS_DSTBLEND_DST_ALPHA:
292
dstFactor = GL_DST_ALPHA;
294
case GLS_DSTBLEND_ONE_MINUS_DST_ALPHA:
295
dstFactor = GL_ONE_MINUS_DST_ALPHA;
298
dstFactor = GL_ONE; // to get warning to shut up
299
ri.Error( ERR_DROP, "GL_State: invalid dst blend state bits\n" );
303
qglEnable( GL_BLEND );
304
qglBlendFunc( srcFactor, dstFactor );
308
qglDisable( GL_BLEND );
315
if ( diff & GLS_DEPTHMASK_TRUE )
317
if ( stateBits & GLS_DEPTHMASK_TRUE )
319
qglDepthMask( GL_TRUE );
323
qglDepthMask( GL_FALSE );
330
if ( diff & GLS_POLYMODE_LINE )
332
if ( stateBits & GLS_POLYMODE_LINE )
334
qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
338
qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
345
if ( diff & GLS_DEPTHTEST_DISABLE )
347
if ( stateBits & GLS_DEPTHTEST_DISABLE )
349
qglDisable( GL_DEPTH_TEST );
353
qglEnable( GL_DEPTH_TEST );
360
if ( diff & GLS_ATEST_BITS )
362
switch ( stateBits & GLS_ATEST_BITS )
365
qglDisable( GL_ALPHA_TEST );
368
qglEnable( GL_ALPHA_TEST );
369
qglAlphaFunc( GL_GREATER, 0.0f );
371
case GLS_ATEST_LT_80:
372
qglEnable( GL_ALPHA_TEST );
373
qglAlphaFunc( GL_LESS, 0.5f );
375
case GLS_ATEST_GE_80:
376
qglEnable( GL_ALPHA_TEST );
377
qglAlphaFunc( GL_GEQUAL, 0.5f );
385
glState.glStateBits = stateBits;
394
A player has predicted a teleport, but hasn't arrived yet
397
static void RB_Hyperspace( void ) {
400
if ( !backEnd.isHyperspace ) {
401
// do initialization shit
404
c = ( backEnd.refdef.time & 255 ) / 255.0f;
405
qglClearColor( c, c, c, 1 );
406
qglClear( GL_COLOR_BUFFER_BIT );
408
backEnd.isHyperspace = qtrue;
412
static void SetViewportAndScissor( void ) {
413
qglMatrixMode(GL_PROJECTION);
414
qglLoadMatrixf( backEnd.viewParms.projectionMatrix );
415
qglMatrixMode(GL_MODELVIEW);
417
// set the window clipping
418
qglViewport( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
419
backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight );
420
qglScissor( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
421
backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight );
428
Any mirrored or portaled views have already been drawn, so prepare
429
to actually render the visible surfaces for this view
432
void RB_BeginDrawingView (void) {
435
// sync with gl if needed
436
if ( r_finish->integer == 1 && !glState.finishCalled ) {
438
glState.finishCalled = qtrue;
440
if ( r_finish->integer == 0 ) {
441
glState.finishCalled = qtrue;
444
// we will need to change the projection matrix before drawing
446
backEnd.projection2D = qfalse;
449
// set the modelview matrix for the viewer
451
SetViewportAndScissor();
453
// ensures that depth writes are enabled for the depth clear
454
GL_State( GLS_DEFAULT );
455
// clear relevant buffers
456
clearBits = GL_DEPTH_BUFFER_BIT;
458
if ( r_measureOverdraw->integer || r_shadows->integer == 2 )
460
clearBits |= GL_STENCIL_BUFFER_BIT;
462
if ( r_fastsky->integer && !( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) )
464
clearBits |= GL_COLOR_BUFFER_BIT; // FIXME: only if sky shaders have been used
466
qglClearColor( 0.8f, 0.7f, 0.4f, 1.0f ); // FIXME: get color of sky
468
qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // FIXME: get color of sky
471
qglClear( clearBits );
473
if ( ( backEnd.refdef.rdflags & RDF_HYPERSPACE ) )
480
backEnd.isHyperspace = qfalse;
483
glState.faceCulling = -1; // force face culling to set next time
485
// we will only draw a sun if there was sky rendered in this view
486
backEnd.skyRenderedThisView = qfalse;
488
// clip to the plane of the portal
489
if ( backEnd.viewParms.isPortal ) {
493
plane[0] = backEnd.viewParms.portalPlane.normal[0];
494
plane[1] = backEnd.viewParms.portalPlane.normal[1];
495
plane[2] = backEnd.viewParms.portalPlane.normal[2];
496
plane[3] = backEnd.viewParms.portalPlane.dist;
498
plane2[0] = DotProduct (backEnd.viewParms.or.axis[0], plane);
499
plane2[1] = DotProduct (backEnd.viewParms.or.axis[1], plane);
500
plane2[2] = DotProduct (backEnd.viewParms.or.axis[2], plane);
501
plane2[3] = DotProduct (plane, backEnd.viewParms.or.origin) - plane[3];
503
qglLoadMatrixf( s_flipMatrix );
504
qglClipPlane (GL_CLIP_PLANE0, plane2);
505
qglEnable (GL_CLIP_PLANE0);
507
qglDisable (GL_CLIP_PLANE0);
512
#define MAC_EVENT_PUMP_MSEC 5
516
RB_RenderDrawSurfList
519
void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
520
shader_t *shader, *oldShader;
521
int fogNum, oldFogNum;
522
int entityNum, oldEntityNum;
523
int dlighted, oldDlighted;
524
qboolean depthRange, oldDepthRange;
526
drawSurf_t *drawSurf;
530
// save original time for entity shader offsets
531
originalTime = backEnd.refdef.floatTime;
533
// clear the z buffer, set the modelview, etc
534
RB_BeginDrawingView ();
538
backEnd.currentEntity = &tr.worldEntity;
541
oldDepthRange = qfalse;
542
oldDlighted = qfalse;
546
backEnd.pc.c_surfaces += numDrawSurfs;
548
for (i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++) {
549
if ( drawSurf->sort == oldSort ) {
550
// fast path, same as previous sort
551
rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
554
oldSort = drawSurf->sort;
555
R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted );
558
// change the tess parameters if needed
559
// a "entityMergable" shader is a shader that can have surfaces from seperate
560
// entities merged into a single batch, like smoke and blood puff sprites
561
if (shader != oldShader || fogNum != oldFogNum || dlighted != oldDlighted
562
|| ( entityNum != oldEntityNum && !shader->entityMergable ) ) {
563
if (oldShader != NULL) {
566
RB_BeginSurface( shader, fogNum );
569
oldDlighted = dlighted;
573
// change the modelview matrix if needed
575
if ( entityNum != oldEntityNum ) {
578
if ( entityNum != ENTITYNUM_WORLD ) {
579
backEnd.currentEntity = &backEnd.refdef.entities[entityNum];
580
backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime;
581
// we have to reset the shaderTime as well otherwise image animations start
582
// from the wrong frame
583
tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
585
// set up the transformation matrix
586
R_RotateForEntity( backEnd.currentEntity, &backEnd.viewParms, &backEnd.or );
588
// set up the dynamic lighting if needed
589
if ( backEnd.currentEntity->needDlights ) {
590
R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or );
593
if ( backEnd.currentEntity->e.renderfx & RF_DEPTHHACK ) {
594
// hack the depth range to prevent view model from poking into walls
598
backEnd.currentEntity = &tr.worldEntity;
599
backEnd.refdef.floatTime = originalTime;
600
backEnd.or = backEnd.viewParms.world;
601
// we have to reset the shaderTime as well otherwise image animations on
602
// the world (like water) continue with the wrong frame
603
tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
604
R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or );
607
qglLoadMatrixf( backEnd.or.modelMatrix );
610
// change depthrange if needed
612
if ( oldDepthRange != depthRange ) {
614
qglDepthRange (0, 0.3);
616
qglDepthRange (0, 1);
618
oldDepthRange = depthRange;
621
oldEntityNum = entityNum;
624
// add the triangles for this surface
625
rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
628
backEnd.refdef.floatTime = originalTime;
630
// draw the contents of the last shader batch
631
if (oldShader != NULL) {
635
// go back to the world modelview matrix
636
qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
638
qglDepthRange (0, 1);
644
// darken down any stencil shadows
647
// add light flares on lights that aren't obscured
653
============================================================================
655
RENDER BACK END THREAD FUNCTIONS
657
============================================================================
666
void RB_SetGL2D (void) {
667
backEnd.projection2D = qtrue;
669
// set 2D virtual screen size
670
qglViewport( 0, 0, glConfig.vidWidth, glConfig.vidHeight );
671
qglScissor( 0, 0, glConfig.vidWidth, glConfig.vidHeight );
672
qglMatrixMode(GL_PROJECTION);
674
qglOrtho (0, glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1);
675
qglMatrixMode(GL_MODELVIEW);
678
GL_State( GLS_DEPTHTEST_DISABLE |
679
GLS_SRCBLEND_SRC_ALPHA |
680
GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
682
qglDisable( GL_CULL_FACE );
683
qglDisable( GL_CLIP_PLANE0 );
685
// set time for 2D shaders
686
backEnd.refdef.time = ri.Milliseconds();
687
backEnd.refdef.floatTime = backEnd.refdef.time * 0.001f;
695
FIXME: not exactly backend
696
Stretches a raw 32 bit power of 2 bitmap image over the given screen rectangle.
700
void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
704
if ( !tr.registered ) {
707
R_SyncRenderThread();
709
// we definately want to sync every frame for the cinematics
713
if ( r_speeds->integer ) {
714
start = ri.Milliseconds();
717
// make sure rows and cols are powers of 2
718
for ( i = 0 ; ( 1 << i ) < cols ; i++ ) {
720
for ( j = 0 ; ( 1 << j ) < rows ; j++ ) {
722
if ( ( 1 << i ) != cols || ( 1 << j ) != rows) {
723
ri.Error (ERR_DROP, "Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows);
726
GL_Bind( tr.scratchImage[client] );
728
// if the scratchImage isn't in the format we want, specify it as a new texture
729
if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) {
730
tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
731
tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
732
qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
733
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
734
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
735
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
736
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
739
// otherwise, just subimage upload it so that drivers can tell we are going to be changing
740
// it and don't try and do a texture compression
741
qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
745
if ( r_speeds->integer ) {
746
end = ri.Milliseconds();
747
ri.Printf( PRINT_ALL, "qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start );
752
qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight );
755
qglTexCoord2f ( 0.5f / cols, 0.5f / rows );
757
qglTexCoord2f ( ( cols - 0.5f ) / cols , 0.5f / rows );
758
qglVertex2f (x+w, y);
759
qglTexCoord2f ( ( cols - 0.5f ) / cols, ( rows - 0.5f ) / rows );
760
qglVertex2f (x+w, y+h);
761
qglTexCoord2f ( 0.5f / cols, ( rows - 0.5f ) / rows );
762
qglVertex2f (x, y+h);
766
void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
768
GL_Bind( tr.scratchImage[client] );
770
// if the scratchImage isn't in the format we want, specify it as a new texture
771
if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) {
772
tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
773
tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
774
qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
775
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
776
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
777
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
778
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
781
// otherwise, just subimage upload it so that drivers can tell we are going to be changing
782
// it and don't try and do a texture compression
783
qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
795
const void *RB_SetColor( const void *data ) {
796
const setColorCommand_t *cmd;
798
cmd = (const setColorCommand_t *)data;
800
backEnd.color2D[0] = cmd->color[0] * 255;
801
backEnd.color2D[1] = cmd->color[1] * 255;
802
backEnd.color2D[2] = cmd->color[2] * 255;
803
backEnd.color2D[3] = cmd->color[3] * 255;
805
return (const void *)(cmd + 1);
813
const void *RB_StretchPic ( const void *data ) {
814
const stretchPicCommand_t *cmd;
816
int numVerts, numIndexes;
818
cmd = (const stretchPicCommand_t *)data;
820
if ( !backEnd.projection2D ) {
824
shader = cmd->shader;
825
if ( shader != tess.shader ) {
826
if ( tess.numIndexes ) {
829
backEnd.currentEntity = &backEnd.entity2D;
830
RB_BeginSurface( shader, 0 );
833
RB_CHECKOVERFLOW( 4, 6 );
834
numVerts = tess.numVertexes;
835
numIndexes = tess.numIndexes;
837
tess.numVertexes += 4;
838
tess.numIndexes += 6;
840
tess.indexes[ numIndexes ] = numVerts + 3;
841
tess.indexes[ numIndexes + 1 ] = numVerts + 0;
842
tess.indexes[ numIndexes + 2 ] = numVerts + 2;
843
tess.indexes[ numIndexes + 3 ] = numVerts + 2;
844
tess.indexes[ numIndexes + 4 ] = numVerts + 0;
845
tess.indexes[ numIndexes + 5 ] = numVerts + 1;
847
*(int *)tess.vertexColors[ numVerts ] =
848
*(int *)tess.vertexColors[ numVerts + 1 ] =
849
*(int *)tess.vertexColors[ numVerts + 2 ] =
850
*(int *)tess.vertexColors[ numVerts + 3 ] = *(int *)backEnd.color2D;
852
tess.xyz[ numVerts ][0] = cmd->x;
853
tess.xyz[ numVerts ][1] = cmd->y;
854
tess.xyz[ numVerts ][2] = 0;
856
tess.texCoords[ numVerts ][0][0] = cmd->s1;
857
tess.texCoords[ numVerts ][0][1] = cmd->t1;
859
tess.xyz[ numVerts + 1 ][0] = cmd->x + cmd->w;
860
tess.xyz[ numVerts + 1 ][1] = cmd->y;
861
tess.xyz[ numVerts + 1 ][2] = 0;
863
tess.texCoords[ numVerts + 1 ][0][0] = cmd->s2;
864
tess.texCoords[ numVerts + 1 ][0][1] = cmd->t1;
866
tess.xyz[ numVerts + 2 ][0] = cmd->x + cmd->w;
867
tess.xyz[ numVerts + 2 ][1] = cmd->y + cmd->h;
868
tess.xyz[ numVerts + 2 ][2] = 0;
870
tess.texCoords[ numVerts + 2 ][0][0] = cmd->s2;
871
tess.texCoords[ numVerts + 2 ][0][1] = cmd->t2;
873
tess.xyz[ numVerts + 3 ][0] = cmd->x;
874
tess.xyz[ numVerts + 3 ][1] = cmd->y + cmd->h;
875
tess.xyz[ numVerts + 3 ][2] = 0;
877
tess.texCoords[ numVerts + 3 ][0][0] = cmd->s1;
878
tess.texCoords[ numVerts + 3 ][0][1] = cmd->t2;
880
return (const void *)(cmd + 1);
890
const void *RB_DrawSurfs( const void *data ) {
891
const drawSurfsCommand_t *cmd;
893
// finish any 2D drawing if needed
894
if ( tess.numIndexes ) {
898
cmd = (const drawSurfsCommand_t *)data;
900
backEnd.refdef = cmd->refdef;
901
backEnd.viewParms = cmd->viewParms;
902
//TODO Maybe check for rdf_noworld stuff but q3mme has full 3d ui
903
backEnd.doneSurfaces = qtrue;
904
RB_RenderDrawSurfList( cmd->drawSurfs, cmd->numDrawSurfs );
906
return (const void *)(cmd + 1);
916
const void *RB_DrawBuffer( const void *data ) {
917
const drawBufferCommand_t *cmd;
919
cmd = (const drawBufferCommand_t *)data;
921
qglDrawBuffer( cmd->buffer );
923
// clear screen for debugging
924
if ( r_clear->integer ) {
925
qglClearColor( 1, 0, 0.5, 1 );
926
qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
929
return (const void *)(cmd + 1);
936
Draw all the images to the screen, on top of whatever
937
was there. This is used to test for texture thrashing.
939
Also called by RE_EndRegistration
942
void RB_ShowImages( void ) {
948
if ( !backEnd.projection2D ) {
952
qglClear( GL_COLOR_BUFFER_BIT );
956
start = ri.Milliseconds();
958
for ( i=0 ; i<tr.numImages ; i++ ) {
959
image = tr.images[i];
961
w = glConfig.vidWidth / 20;
962
h = glConfig.vidHeight / 15;
966
// show in proportional size in mode 2
967
if ( r_showImages->integer == 2 ) {
968
w *= image->uploadWidth / 512.0f;
969
h *= image->uploadHeight / 512.0f;
974
qglTexCoord2f( 0, 0 );
976
qglTexCoord2f( 1, 0 );
977
qglVertex2f( x + w, y );
978
qglTexCoord2f( 1, 1 );
979
qglVertex2f( x + w, y + h );
980
qglTexCoord2f( 0, 1 );
981
qglVertex2f( x, y + h );
987
end = ri.Milliseconds();
988
ri.Printf( PRINT_ALL, "%i msec to draw all images\n", end - start );
999
const void *RB_SwapBuffers( const void *data ) {
1000
const swapBuffersCommand_t *cmd;
1002
// finish any 2D drawing if needed
1003
if ( tess.numIndexes ) {
1007
// texture swapping test
1008
if ( r_showImages->integer ) {
1012
cmd = (const swapBuffersCommand_t *)data;
1014
// we measure overdraw by reading back the stencil buffer and
1015
// counting up the number of increments that have happened
1016
if ( r_measureOverdraw->integer ) {
1019
unsigned char *stencilReadback;
1021
stencilReadback = ri.Hunk_AllocateTempMemory( glConfig.vidWidth * glConfig.vidHeight );
1022
qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback );
1024
for ( i = 0; i < glConfig.vidWidth * glConfig.vidHeight; i++ ) {
1025
sum += stencilReadback[i];
1028
backEnd.pc.c_overDraw += sum;
1029
ri.Hunk_FreeTempMemory( stencilReadback );
1033
if ( !glState.finishCalled ) {
1037
GLimp_LogComment( "***************** RB_SwapBuffers *****************\n\n\n" );
1041
backEnd.projection2D = qfalse;
1042
backEnd.doneBloom = qfalse;
1043
backEnd.doneSurfaces = qfalse;
1044
return (const void *)(cmd + 1);
1048
====================
1049
RB_ExecuteRenderCommands
1051
This function will be called synchronously if running without
1052
smp extensions, or asynchronously by another thread.
1053
====================
1055
void RB_ExecuteRenderCommands( const void *data ) {
1058
t1 = ri.Milliseconds ();
1060
if ( !r_smp->integer || data == backEndData[0]->commands.cmds ) {
1061
backEnd.smpFrame = 0;
1063
backEnd.smpFrame = 1;
1067
switch ( *(const int *)data ) {
1069
data = RB_SetColor( data );
1071
case RC_STRETCH_PIC:
1072
//Check if it's time for BLOOM!
1074
data = RB_StretchPic( data );
1077
data = RB_DrawSurfs( data );
1079
case RC_DRAW_BUFFER:
1080
data = RB_DrawBuffer( data );
1082
case RC_SWAP_BUFFERS:
1083
//Check if it's time for BLOOM!
1085
data = RB_SwapBuffers( data );
1088
data = RB_TakeScreenshotCmd( data );
1091
data = RB_TakeVideoFrameCmd( data );
1094
case RC_END_OF_LIST:
1096
// stop rendering on this thread
1097
t2 = ri.Milliseconds ();
1098
backEnd.pc.msec = t2 - t1;
1111
void RB_RenderThread( void ) {
1114
// wait for either a rendering command or a quit command
1116
// sleep until we have work to do
1117
data = GLimp_RendererSleep();
1120
return; // all done, renderer is shutting down
1123
renderThreadActive = qtrue;
1125
RB_ExecuteRenderCommands( data );
1127
renderThreadActive = qfalse;