~ubuntu-branches/ubuntu/jaunty/openarena/jaunty

« back to all changes in this revision

Viewing changes to code/renderer/tr_backend.c.orig

  • Committer: Bazaar Package Importer
  • Author(s): Bruno "Fuddl" Kleinert, Bruno "Fuddl" Kleinert
  • Date: 2008-04-24 14:33:54 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20080424143354-0cuxsalv98ajw2js
Tags: 0.7.6-1
[ Bruno "Fuddl" Kleinert ]
* New upstream release
* Freshen 10_fix_build_and_binary_on_alpha.dpatch to apply to latest
  upstream sources
* Remove 10-fix_menudef.h_includes.dpatch which pulled in a missing header
  file. The header is now included in the upstream tarball.
* Remove debian/watch, because upstream places its new releases too often to
  different download locations
* Updated debian/copyright to reflect the download location
* Expand copyright years in debian/copyright

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
===========================================================================
3
 
Copyright (C) 1999-2005 Id Software, Inc.
4
 
 
5
 
This file is part of Quake III Arena source code.
6
 
 
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.
11
 
 
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.
16
 
 
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
 
===========================================================================
21
 
*/
22
 
#include "tr_local.h"
23
 
 
24
 
backEndData_t   *backEndData[SMP_FRAMES];
25
 
backEndState_t  backEnd;
26
 
 
27
 
 
28
 
static float    s_flipMatrix[16] = {
29
 
        // convert from our coordinate system (looking down X)
30
 
        // to OpenGL's coordinate system (looking down -Z)
31
 
        0, 0, -1, 0,
32
 
        -1, 0, 0, 0,
33
 
        0, 1, 0, 0,
34
 
        0, 0, 0, 1
35
 
};
36
 
 
37
 
 
38
 
/*
39
 
** GL_Bind
40
 
*/
41
 
void GL_Bind( image_t *image ) {
42
 
        int texnum;
43
 
 
44
 
        if ( !image ) {
45
 
                ri.Printf( PRINT_WARNING, "GL_Bind: NULL image\n" );
46
 
                texnum = tr.defaultImage->texnum;
47
 
        } else {
48
 
                texnum = image->texnum;
49
 
        }
50
 
 
51
 
        if ( r_nobind->integer && tr.dlightImage ) {            // performance evaluation option
52
 
                texnum = tr.dlightImage->texnum;
53
 
        }
54
 
 
55
 
        if ( glState.currenttextures[glState.currenttmu] != texnum ) {
56
 
                image->frameUsed = tr.frameCount;
57
 
                glState.currenttextures[glState.currenttmu] = texnum;
58
 
                qglBindTexture (GL_TEXTURE_2D, texnum);
59
 
        }
60
 
}
61
 
 
62
 
/*
63
 
** GL_SelectTexture
64
 
*/
65
 
void GL_SelectTexture( int unit )
66
 
{
67
 
        if ( glState.currenttmu == unit )
68
 
        {
69
 
                return;
70
 
        }
71
 
 
72
 
        if ( unit == 0 )
73
 
        {
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" );
78
 
        }
79
 
        else if ( unit == 1 )
80
 
        {
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" );
85
 
        } else {
86
 
                ri.Error( ERR_DROP, "GL_SelectTexture: unit = %i", unit );
87
 
        }
88
 
 
89
 
        glState.currenttmu = unit;
90
 
}
91
 
 
92
 
 
93
 
/*
94
 
** GL_BindMultitexture
95
 
*/
96
 
void GL_BindMultitexture( image_t *image0, GLuint env0, image_t *image1, GLuint env1 ) {
97
 
        int             texnum0, texnum1;
98
 
 
99
 
        texnum0 = image0->texnum;
100
 
        texnum1 = image1->texnum;
101
 
 
102
 
        if ( r_nobind->integer && tr.dlightImage ) {            // performance evaluation option
103
 
                texnum0 = texnum1 = tr.dlightImage->texnum;
104
 
        }
105
 
 
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 );
111
 
        }
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 );
117
 
        }
118
 
}
119
 
 
120
 
 
121
 
/*
122
 
** GL_Cull
123
 
*/
124
 
void GL_Cull( int cullType ) {
125
 
        if ( glState.faceCulling == cullType ) {
126
 
                return;
127
 
        }
128
 
 
129
 
        glState.faceCulling = cullType;
130
 
 
131
 
        if ( cullType == CT_TWO_SIDED ) 
132
 
        {
133
 
                qglDisable( GL_CULL_FACE );
134
 
        } 
135
 
        else 
136
 
        {
137
 
                qglEnable( GL_CULL_FACE );
138
 
 
139
 
                if ( cullType == CT_BACK_SIDED )
140
 
                {
141
 
                        if ( backEnd.viewParms.isMirror )
142
 
                        {
143
 
                                qglCullFace( GL_FRONT );
144
 
                        }
145
 
                        else
146
 
                        {
147
 
                                qglCullFace( GL_BACK );
148
 
                        }
149
 
                }
150
 
                else
151
 
                {
152
 
                        if ( backEnd.viewParms.isMirror )
153
 
                        {
154
 
                                qglCullFace( GL_BACK );
155
 
                        }
156
 
                        else
157
 
                        {
158
 
                                qglCullFace( GL_FRONT );
159
 
                        }
160
 
                }
161
 
        }
162
 
}
163
 
 
164
 
/*
165
 
** GL_TexEnv
166
 
*/
167
 
void GL_TexEnv( int env )
168
 
{
169
 
        if ( env == glState.texEnv[glState.currenttmu] )
170
 
        {
171
 
                return;
172
 
        }
173
 
 
174
 
        glState.texEnv[glState.currenttmu] = env;
175
 
 
176
 
 
177
 
        switch ( env )
178
 
        {
179
 
        case GL_MODULATE:
180
 
                qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
181
 
                break;
182
 
        case GL_REPLACE:
183
 
                qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
184
 
                break;
185
 
        case GL_DECAL:
186
 
                qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
187
 
                break;
188
 
        case GL_ADD:
189
 
                qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD );
190
 
                break;
191
 
        default:
192
 
                ri.Error( ERR_DROP, "GL_TexEnv: invalid env '%d' passed\n", env );
193
 
                break;
194
 
        }
195
 
}
196
 
 
197
 
/*
198
 
** GL_State
199
 
**
200
 
** This routine is responsible for setting the most commonly changed state
201
 
** in Q3.
202
 
*/
203
 
void GL_State( unsigned long stateBits )
204
 
{
205
 
        unsigned long diff = stateBits ^ glState.glStateBits;
206
 
 
207
 
        if ( !diff )
208
 
        {
209
 
                return;
210
 
        }
211
 
 
212
 
        //
213
 
        // check depthFunc bits
214
 
        //
215
 
        if ( diff & GLS_DEPTHFUNC_EQUAL )
216
 
        {
217
 
                if ( stateBits & GLS_DEPTHFUNC_EQUAL )
218
 
                {
219
 
                        qglDepthFunc( GL_EQUAL );
220
 
                }
221
 
                else
222
 
                {
223
 
                        qglDepthFunc( GL_LEQUAL );
224
 
                }
225
 
        }
226
 
 
227
 
        //
228
 
        // check blend bits
229
 
        //
230
 
        if ( diff & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) )
231
 
        {
232
 
                GLenum srcFactor, dstFactor;
233
 
 
234
 
                if ( stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) )
235
 
                {
236
 
                        switch ( stateBits & GLS_SRCBLEND_BITS )
237
 
                        {
238
 
                        case GLS_SRCBLEND_ZERO:
239
 
                                srcFactor = GL_ZERO;
240
 
                                break;
241
 
                        case GLS_SRCBLEND_ONE:
242
 
                                srcFactor = GL_ONE;
243
 
                                break;
244
 
                        case GLS_SRCBLEND_DST_COLOR:
245
 
                                srcFactor = GL_DST_COLOR;
246
 
                                break;
247
 
                        case GLS_SRCBLEND_ONE_MINUS_DST_COLOR:
248
 
                                srcFactor = GL_ONE_MINUS_DST_COLOR;
249
 
                                break;
250
 
                        case GLS_SRCBLEND_SRC_ALPHA:
251
 
                                srcFactor = GL_SRC_ALPHA;
252
 
                                break;
253
 
                        case GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA:
254
 
                                srcFactor = GL_ONE_MINUS_SRC_ALPHA;
255
 
                                break;
256
 
                        case GLS_SRCBLEND_DST_ALPHA:
257
 
                                srcFactor = GL_DST_ALPHA;
258
 
                                break;
259
 
                        case GLS_SRCBLEND_ONE_MINUS_DST_ALPHA:
260
 
                                srcFactor = GL_ONE_MINUS_DST_ALPHA;
261
 
                                break;
262
 
                        case GLS_SRCBLEND_ALPHA_SATURATE:
263
 
                                srcFactor = GL_SRC_ALPHA_SATURATE;
264
 
                                break;
265
 
                        default:
266
 
                                srcFactor = GL_ONE;             // to get warning to shut up
267
 
                                ri.Error( ERR_DROP, "GL_State: invalid src blend state bits\n" );
268
 
                                break;
269
 
                        }
270
 
 
271
 
                        switch ( stateBits & GLS_DSTBLEND_BITS )
272
 
                        {
273
 
                        case GLS_DSTBLEND_ZERO:
274
 
                                dstFactor = GL_ZERO;
275
 
                                break;
276
 
                        case GLS_DSTBLEND_ONE:
277
 
                                dstFactor = GL_ONE;
278
 
                                break;
279
 
                        case GLS_DSTBLEND_SRC_COLOR:
280
 
                                dstFactor = GL_SRC_COLOR;
281
 
                                break;
282
 
                        case GLS_DSTBLEND_ONE_MINUS_SRC_COLOR:
283
 
                                dstFactor = GL_ONE_MINUS_SRC_COLOR;
284
 
                                break;
285
 
                        case GLS_DSTBLEND_SRC_ALPHA:
286
 
                                dstFactor = GL_SRC_ALPHA;
287
 
                                break;
288
 
                        case GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA:
289
 
                                dstFactor = GL_ONE_MINUS_SRC_ALPHA;
290
 
                                break;
291
 
                        case GLS_DSTBLEND_DST_ALPHA:
292
 
                                dstFactor = GL_DST_ALPHA;
293
 
                                break;
294
 
                        case GLS_DSTBLEND_ONE_MINUS_DST_ALPHA:
295
 
                                dstFactor = GL_ONE_MINUS_DST_ALPHA;
296
 
                                break;
297
 
                        default:
298
 
                                dstFactor = GL_ONE;             // to get warning to shut up
299
 
                                ri.Error( ERR_DROP, "GL_State: invalid dst blend state bits\n" );
300
 
                                break;
301
 
                        }
302
 
 
303
 
                        qglEnable( GL_BLEND );
304
 
                        qglBlendFunc( srcFactor, dstFactor );
305
 
                }
306
 
                else
307
 
                {
308
 
                        qglDisable( GL_BLEND );
309
 
                }
310
 
        }
311
 
 
312
 
        //
313
 
        // check depthmask
314
 
        //
315
 
        if ( diff & GLS_DEPTHMASK_TRUE )
316
 
        {
317
 
                if ( stateBits & GLS_DEPTHMASK_TRUE )
318
 
                {
319
 
                        qglDepthMask( GL_TRUE );
320
 
                }
321
 
                else
322
 
                {
323
 
                        qglDepthMask( GL_FALSE );
324
 
                }
325
 
        }
326
 
 
327
 
        //
328
 
        // fill/line mode
329
 
        //
330
 
        if ( diff & GLS_POLYMODE_LINE )
331
 
        {
332
 
                if ( stateBits & GLS_POLYMODE_LINE )
333
 
                {
334
 
                        qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
335
 
                }
336
 
                else
337
 
                {
338
 
                        qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
339
 
                }
340
 
        }
341
 
 
342
 
        //
343
 
        // depthtest
344
 
        //
345
 
        if ( diff & GLS_DEPTHTEST_DISABLE )
346
 
        {
347
 
                if ( stateBits & GLS_DEPTHTEST_DISABLE )
348
 
                {
349
 
                        qglDisable( GL_DEPTH_TEST );
350
 
                }
351
 
                else
352
 
                {
353
 
                        qglEnable( GL_DEPTH_TEST );
354
 
                }
355
 
        }
356
 
 
357
 
        //
358
 
        // alpha test
359
 
        //
360
 
        if ( diff & GLS_ATEST_BITS )
361
 
        {
362
 
                switch ( stateBits & GLS_ATEST_BITS )
363
 
                {
364
 
                case 0:
365
 
                        qglDisable( GL_ALPHA_TEST );
366
 
                        break;
367
 
                case GLS_ATEST_GT_0:
368
 
                        qglEnable( GL_ALPHA_TEST );
369
 
                        qglAlphaFunc( GL_GREATER, 0.0f );
370
 
                        break;
371
 
                case GLS_ATEST_LT_80:
372
 
                        qglEnable( GL_ALPHA_TEST );
373
 
                        qglAlphaFunc( GL_LESS, 0.5f );
374
 
                        break;
375
 
                case GLS_ATEST_GE_80:
376
 
                        qglEnable( GL_ALPHA_TEST );
377
 
                        qglAlphaFunc( GL_GEQUAL, 0.5f );
378
 
                        break;
379
 
                default:
380
 
                        assert( 0 );
381
 
                        break;
382
 
                }
383
 
        }
384
 
 
385
 
        glState.glStateBits = stateBits;
386
 
}
387
 
 
388
 
 
389
 
 
390
 
/*
391
 
================
392
 
RB_Hyperspace
393
 
 
394
 
A player has predicted a teleport, but hasn't arrived yet
395
 
================
396
 
*/
397
 
static void RB_Hyperspace( void ) {
398
 
        float           c;
399
 
 
400
 
        if ( !backEnd.isHyperspace ) {
401
 
                // do initialization shit
402
 
        }
403
 
 
404
 
        c = ( backEnd.refdef.time & 255 ) / 255.0f;
405
 
        qglClearColor( c, c, c, 1 );
406
 
        qglClear( GL_COLOR_BUFFER_BIT );
407
 
 
408
 
        backEnd.isHyperspace = qtrue;
409
 
}
410
 
 
411
 
 
412
 
static void SetViewportAndScissor( void ) {
413
 
        qglMatrixMode(GL_PROJECTION);
414
 
        qglLoadMatrixf( backEnd.viewParms.projectionMatrix );
415
 
        qglMatrixMode(GL_MODELVIEW);
416
 
 
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 );
422
 
}
423
 
 
424
 
/*
425
 
=================
426
 
RB_BeginDrawingView
427
 
 
428
 
Any mirrored or portaled views have already been drawn, so prepare
429
 
to actually render the visible surfaces for this view
430
 
=================
431
 
*/
432
 
void RB_BeginDrawingView (void) {
433
 
        int clearBits = 0;
434
 
 
435
 
        // sync with gl if needed
436
 
        if ( r_finish->integer == 1 && !glState.finishCalled ) {
437
 
                qglFinish ();
438
 
                glState.finishCalled = qtrue;
439
 
        }
440
 
        if ( r_finish->integer == 0 ) {
441
 
                glState.finishCalled = qtrue;
442
 
        }
443
 
 
444
 
        // we will need to change the projection matrix before drawing
445
 
        // 2D images again
446
 
        backEnd.projection2D = qfalse;
447
 
 
448
 
        //
449
 
        // set the modelview matrix for the viewer
450
 
        //
451
 
        SetViewportAndScissor();
452
 
 
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;
457
 
 
458
 
        if ( r_measureOverdraw->integer || r_shadows->integer == 2 )
459
 
        {
460
 
                clearBits |= GL_STENCIL_BUFFER_BIT;
461
 
        }
462
 
        if ( r_fastsky->integer && !( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) )
463
 
        {
464
 
                clearBits |= GL_COLOR_BUFFER_BIT;       // FIXME: only if sky shaders have been used
465
 
#ifdef _DEBUG
466
 
                qglClearColor( 0.8f, 0.7f, 0.4f, 1.0f );        // FIXME: get color of sky
467
 
#else
468
 
                qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f );        // FIXME: get color of sky
469
 
#endif
470
 
        }
471
 
        qglClear( clearBits );
472
 
 
473
 
        if ( ( backEnd.refdef.rdflags & RDF_HYPERSPACE ) )
474
 
        {
475
 
                RB_Hyperspace();
476
 
                return;
477
 
        }
478
 
        else
479
 
        {
480
 
                backEnd.isHyperspace = qfalse;
481
 
        }
482
 
 
483
 
        glState.faceCulling = -1;               // force face culling to set next time
484
 
 
485
 
        // we will only draw a sun if there was sky rendered in this view
486
 
        backEnd.skyRenderedThisView = qfalse;
487
 
 
488
 
        // clip to the plane of the portal
489
 
        if ( backEnd.viewParms.isPortal ) {
490
 
                float   plane[4];
491
 
                double  plane2[4];
492
 
 
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;
497
 
 
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];
502
 
 
503
 
                qglLoadMatrixf( s_flipMatrix );
504
 
                qglClipPlane (GL_CLIP_PLANE0, plane2);
505
 
                qglEnable (GL_CLIP_PLANE0);
506
 
        } else {
507
 
                qglDisable (GL_CLIP_PLANE0);
508
 
        }
509
 
}
510
 
 
511
 
 
512
 
#define MAC_EVENT_PUMP_MSEC             5
513
 
 
514
 
/*
515
 
==================
516
 
RB_RenderDrawSurfList
517
 
==================
518
 
*/
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;
525
 
        int                             i;
526
 
        drawSurf_t              *drawSurf;
527
 
        int                             oldSort;
528
 
        float                   originalTime;
529
 
 
530
 
        // save original time for entity shader offsets
531
 
        originalTime = backEnd.refdef.floatTime;
532
 
 
533
 
        // clear the z buffer, set the modelview, etc
534
 
        RB_BeginDrawingView ();
535
 
 
536
 
        // draw everything
537
 
        oldEntityNum = -1;
538
 
        backEnd.currentEntity = &tr.worldEntity;
539
 
        oldShader = NULL;
540
 
        oldFogNum = -1;
541
 
        oldDepthRange = qfalse;
542
 
        oldDlighted = qfalse;
543
 
        oldSort = -1;
544
 
        depthRange = qfalse;
545
 
 
546
 
        backEnd.pc.c_surfaces += numDrawSurfs;
547
 
 
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 );
552
 
                        continue;
553
 
                }
554
 
                oldSort = drawSurf->sort;
555
 
                R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted );
556
 
 
557
 
                //
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) {
564
 
                                RB_EndSurface();
565
 
                        }
566
 
                        RB_BeginSurface( shader, fogNum );
567
 
                        oldShader = shader;
568
 
                        oldFogNum = fogNum;
569
 
                        oldDlighted = dlighted;
570
 
                }
571
 
 
572
 
                //
573
 
                // change the modelview matrix if needed
574
 
                //
575
 
                if ( entityNum != oldEntityNum ) {
576
 
                        depthRange = qfalse;
577
 
 
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;
584
 
 
585
 
                                // set up the transformation matrix
586
 
                                R_RotateForEntity( backEnd.currentEntity, &backEnd.viewParms, &backEnd.or );
587
 
 
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 );
591
 
                                }
592
 
 
593
 
                                if ( backEnd.currentEntity->e.renderfx & RF_DEPTHHACK ) {
594
 
                                        // hack the depth range to prevent view model from poking into walls
595
 
                                        depthRange = qtrue;
596
 
                                }
597
 
                        } else {
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 );
605
 
                        }
606
 
 
607
 
                        qglLoadMatrixf( backEnd.or.modelMatrix );
608
 
 
609
 
                        //
610
 
                        // change depthrange if needed
611
 
                        //
612
 
                        if ( oldDepthRange != depthRange ) {
613
 
                                if ( depthRange ) {
614
 
                                        qglDepthRange (0, 0.3);
615
 
                                } else {
616
 
                                        qglDepthRange (0, 1);
617
 
                                }
618
 
                                oldDepthRange = depthRange;
619
 
                        }
620
 
 
621
 
                        oldEntityNum = entityNum;
622
 
                }
623
 
 
624
 
                // add the triangles for this surface
625
 
                rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
626
 
        }
627
 
 
628
 
        backEnd.refdef.floatTime = originalTime;
629
 
 
630
 
        // draw the contents of the last shader batch
631
 
        if (oldShader != NULL) {
632
 
                RB_EndSurface();
633
 
        }
634
 
 
635
 
        // go back to the world modelview matrix
636
 
        qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
637
 
        if ( depthRange ) {
638
 
                qglDepthRange (0, 1);
639
 
        }
640
 
 
641
 
#if 0
642
 
        RB_DrawSun();
643
 
#endif
644
 
        // darken down any stencil shadows
645
 
        RB_ShadowFinish();              
646
 
 
647
 
        // add light flares on lights that aren't obscured
648
 
        RB_RenderFlares();
649
 
}
650
 
 
651
 
 
652
 
/*
653
 
============================================================================
654
 
 
655
 
RENDER BACK END THREAD FUNCTIONS
656
 
 
657
 
============================================================================
658
 
*/
659
 
 
660
 
/*
661
 
================
662
 
RB_SetGL2D
663
 
 
664
 
================
665
 
*/
666
 
void    RB_SetGL2D (void) {
667
 
        backEnd.projection2D = qtrue;
668
 
 
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);
673
 
    qglLoadIdentity ();
674
 
        qglOrtho (0, glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1);
675
 
        qglMatrixMode(GL_MODELVIEW);
676
 
    qglLoadIdentity ();
677
 
 
678
 
        GL_State( GLS_DEPTHTEST_DISABLE |
679
 
                          GLS_SRCBLEND_SRC_ALPHA |
680
 
                          GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
681
 
 
682
 
        qglDisable( GL_CULL_FACE );
683
 
        qglDisable( GL_CLIP_PLANE0 );
684
 
 
685
 
        // set time for 2D shaders
686
 
        backEnd.refdef.time = ri.Milliseconds();
687
 
        backEnd.refdef.floatTime = backEnd.refdef.time * 0.001f;
688
 
}
689
 
 
690
 
 
691
 
/*
692
 
=============
693
 
RE_StretchRaw
694
 
 
695
 
FIXME: not exactly backend
696
 
Stretches a raw 32 bit power of 2 bitmap image over the given screen rectangle.
697
 
Used for cinematics.
698
 
=============
699
 
*/
700
 
void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
701
 
        int                     i, j;
702
 
        int                     start, end;
703
 
 
704
 
        if ( !tr.registered ) {
705
 
                return;
706
 
        }
707
 
        R_SyncRenderThread();
708
 
 
709
 
        // we definately want to sync every frame for the cinematics
710
 
        qglFinish();
711
 
 
712
 
        start = end = 0;
713
 
        if ( r_speeds->integer ) {
714
 
                start = ri.Milliseconds();
715
 
        }
716
 
 
717
 
        // make sure rows and cols are powers of 2
718
 
        for ( i = 0 ; ( 1 << i ) < cols ; i++ ) {
719
 
        }
720
 
        for ( j = 0 ; ( 1 << j ) < rows ; j++ ) {
721
 
        }
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);
724
 
        }
725
 
 
726
 
        GL_Bind( tr.scratchImage[client] );
727
 
 
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 ); 
737
 
        } else {
738
 
                if (dirty) {
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 );
742
 
                }
743
 
        }
744
 
 
745
 
        if ( r_speeds->integer ) {
746
 
                end = ri.Milliseconds();
747
 
                ri.Printf( PRINT_ALL, "qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start );
748
 
        }
749
 
 
750
 
        RB_SetGL2D();
751
 
 
752
 
        qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight );
753
 
 
754
 
        qglBegin (GL_QUADS);
755
 
        qglTexCoord2f ( 0.5f / cols,  0.5f / rows );
756
 
        qglVertex2f (x, y);
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);
763
 
        qglEnd ();
764
 
}
765
 
 
766
 
void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
767
 
 
768
 
        GL_Bind( tr.scratchImage[client] );
769
 
 
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 ); 
779
 
        } else {
780
 
                if (dirty) {
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 );
784
 
                }
785
 
        }
786
 
}
787
 
 
788
 
 
789
 
/*
790
 
=============
791
 
RB_SetColor
792
 
 
793
 
=============
794
 
*/
795
 
const void      *RB_SetColor( const void *data ) {
796
 
        const setColorCommand_t *cmd;
797
 
 
798
 
        cmd = (const setColorCommand_t *)data;
799
 
 
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;
804
 
 
805
 
        return (const void *)(cmd + 1);
806
 
}
807
 
 
808
 
/*
809
 
=============
810
 
RB_StretchPic
811
 
=============
812
 
*/
813
 
const void *RB_StretchPic ( const void *data ) {
814
 
        const stretchPicCommand_t       *cmd;
815
 
        shader_t *shader;
816
 
        int             numVerts, numIndexes;
817
 
 
818
 
        cmd = (const stretchPicCommand_t *)data;
819
 
 
820
 
        if ( !backEnd.projection2D ) {
821
 
                RB_SetGL2D();
822
 
        }
823
 
 
824
 
        shader = cmd->shader;
825
 
        if ( shader != tess.shader ) {
826
 
                if ( tess.numIndexes ) {
827
 
                        RB_EndSurface();
828
 
                }
829
 
                backEnd.currentEntity = &backEnd.entity2D;
830
 
                RB_BeginSurface( shader, 0 );
831
 
        }
832
 
 
833
 
        RB_CHECKOVERFLOW( 4, 6 );
834
 
        numVerts = tess.numVertexes;
835
 
        numIndexes = tess.numIndexes;
836
 
 
837
 
        tess.numVertexes += 4;
838
 
        tess.numIndexes += 6;
839
 
 
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;
846
 
 
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;
851
 
 
852
 
        tess.xyz[ numVerts ][0] = cmd->x;
853
 
        tess.xyz[ numVerts ][1] = cmd->y;
854
 
        tess.xyz[ numVerts ][2] = 0;
855
 
 
856
 
        tess.texCoords[ numVerts ][0][0] = cmd->s1;
857
 
        tess.texCoords[ numVerts ][0][1] = cmd->t1;
858
 
 
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;
862
 
 
863
 
        tess.texCoords[ numVerts + 1 ][0][0] = cmd->s2;
864
 
        tess.texCoords[ numVerts + 1 ][0][1] = cmd->t1;
865
 
 
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;
869
 
 
870
 
        tess.texCoords[ numVerts + 2 ][0][0] = cmd->s2;
871
 
        tess.texCoords[ numVerts + 2 ][0][1] = cmd->t2;
872
 
 
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;
876
 
 
877
 
        tess.texCoords[ numVerts + 3 ][0][0] = cmd->s1;
878
 
        tess.texCoords[ numVerts + 3 ][0][1] = cmd->t2;
879
 
 
880
 
        return (const void *)(cmd + 1);
881
 
}
882
 
 
883
 
 
884
 
/*
885
 
=============
886
 
RB_DrawSurfs
887
 
 
888
 
=============
889
 
*/
890
 
const void      *RB_DrawSurfs( const void *data ) {
891
 
        const drawSurfsCommand_t        *cmd;
892
 
 
893
 
        // finish any 2D drawing if needed
894
 
        if ( tess.numIndexes ) {
895
 
                RB_EndSurface();
896
 
        }
897
 
 
898
 
        cmd = (const drawSurfsCommand_t *)data;
899
 
 
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 );
905
 
 
906
 
        return (const void *)(cmd + 1);
907
 
}
908
 
 
909
 
 
910
 
/*
911
 
=============
912
 
RB_DrawBuffer
913
 
 
914
 
=============
915
 
*/
916
 
const void      *RB_DrawBuffer( const void *data ) {
917
 
        const drawBufferCommand_t       *cmd;
918
 
 
919
 
        cmd = (const drawBufferCommand_t *)data;
920
 
 
921
 
        qglDrawBuffer( cmd->buffer );
922
 
 
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 );
927
 
        }
928
 
 
929
 
        return (const void *)(cmd + 1);
930
 
}
931
 
 
932
 
/*
933
 
===============
934
 
RB_ShowImages
935
 
 
936
 
Draw all the images to the screen, on top of whatever
937
 
was there.  This is used to test for texture thrashing.
938
 
 
939
 
Also called by RE_EndRegistration
940
 
===============
941
 
*/
942
 
void RB_ShowImages( void ) {
943
 
        int             i;
944
 
        image_t *image;
945
 
        float   x, y, w, h;
946
 
        int             start, end;
947
 
 
948
 
        if ( !backEnd.projection2D ) {
949
 
                RB_SetGL2D();
950
 
        }
951
 
 
952
 
        qglClear( GL_COLOR_BUFFER_BIT );
953
 
 
954
 
        qglFinish();
955
 
 
956
 
        start = ri.Milliseconds();
957
 
 
958
 
        for ( i=0 ; i<tr.numImages ; i++ ) {
959
 
                image = tr.images[i];
960
 
 
961
 
                w = glConfig.vidWidth / 20;
962
 
                h = glConfig.vidHeight / 15;
963
 
                x = i % 20 * w;
964
 
                y = i / 20 * h;
965
 
 
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;
970
 
                }
971
 
 
972
 
                GL_Bind( image );
973
 
                qglBegin (GL_QUADS);
974
 
                qglTexCoord2f( 0, 0 );
975
 
                qglVertex2f( x, y );
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 );
982
 
                qglEnd();
983
 
        }
984
 
 
985
 
        qglFinish();
986
 
 
987
 
        end = ri.Milliseconds();
988
 
        ri.Printf( PRINT_ALL, "%i msec to draw all images\n", end - start );
989
 
 
990
 
}
991
 
 
992
 
 
993
 
/*
994
 
=============
995
 
RB_SwapBuffers
996
 
 
997
 
=============
998
 
*/
999
 
const void      *RB_SwapBuffers( const void *data ) {
1000
 
        const swapBuffersCommand_t      *cmd;
1001
 
 
1002
 
        // finish any 2D drawing if needed
1003
 
        if ( tess.numIndexes ) {
1004
 
                RB_EndSurface();
1005
 
        }
1006
 
 
1007
 
        // texture swapping test
1008
 
        if ( r_showImages->integer ) {
1009
 
                RB_ShowImages();
1010
 
        }
1011
 
 
1012
 
        cmd = (const swapBuffersCommand_t *)data;
1013
 
 
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 ) {
1017
 
                int i;
1018
 
                long sum = 0;
1019
 
                unsigned char *stencilReadback;
1020
 
 
1021
 
                stencilReadback = ri.Hunk_AllocateTempMemory( glConfig.vidWidth * glConfig.vidHeight );
1022
 
                qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback );
1023
 
 
1024
 
                for ( i = 0; i < glConfig.vidWidth * glConfig.vidHeight; i++ ) {
1025
 
                        sum += stencilReadback[i];
1026
 
                }
1027
 
 
1028
 
                backEnd.pc.c_overDraw += sum;
1029
 
                ri.Hunk_FreeTempMemory( stencilReadback );
1030
 
        }
1031
 
 
1032
 
 
1033
 
        if ( !glState.finishCalled ) {
1034
 
                qglFinish();
1035
 
        }
1036
 
 
1037
 
        GLimp_LogComment( "***************** RB_SwapBuffers *****************\n\n\n" );
1038
 
 
1039
 
        GLimp_EndFrame();
1040
 
 
1041
 
        backEnd.projection2D = qfalse;
1042
 
        backEnd.doneBloom = qfalse;
1043
 
        backEnd.doneSurfaces = qfalse;
1044
 
        return (const void *)(cmd + 1);
1045
 
}
1046
 
 
1047
 
/*
1048
 
====================
1049
 
RB_ExecuteRenderCommands
1050
 
 
1051
 
This function will be called synchronously if running without
1052
 
smp extensions, or asynchronously by another thread.
1053
 
====================
1054
 
*/
1055
 
void RB_ExecuteRenderCommands( const void *data ) {
1056
 
        int             t1, t2;
1057
 
 
1058
 
        t1 = ri.Milliseconds ();
1059
 
 
1060
 
        if ( !r_smp->integer || data == backEndData[0]->commands.cmds ) {
1061
 
                backEnd.smpFrame = 0;
1062
 
        } else {
1063
 
                backEnd.smpFrame = 1;
1064
 
        }
1065
 
 
1066
 
        while ( 1 ) {
1067
 
                switch ( *(const int *)data ) {
1068
 
                case RC_SET_COLOR:
1069
 
                        data = RB_SetColor( data );
1070
 
                        break;
1071
 
                case RC_STRETCH_PIC:
1072
 
                        //Check if it's time for BLOOM!
1073
 
                        R_BloomScreen();
1074
 
                        data = RB_StretchPic( data );
1075
 
                        break;
1076
 
                case RC_DRAW_SURFS:
1077
 
                        data = RB_DrawSurfs( data );
1078
 
                        break;
1079
 
                case RC_DRAW_BUFFER:
1080
 
                        data = RB_DrawBuffer( data );
1081
 
                        break;
1082
 
                case RC_SWAP_BUFFERS:
1083
 
                        //Check if it's time for BLOOM!
1084
 
                        R_BloomScreen();
1085
 
                        data = RB_SwapBuffers( data );
1086
 
                        break;
1087
 
                case RC_SCREENSHOT:
1088
 
                        data = RB_TakeScreenshotCmd( data );
1089
 
                        break;
1090
 
                case RC_VIDEOFRAME:
1091
 
                        data = RB_TakeVideoFrameCmd( data );
1092
 
                        break;
1093
 
 
1094
 
                case RC_END_OF_LIST:
1095
 
                default:
1096
 
                        // stop rendering on this thread
1097
 
                        t2 = ri.Milliseconds ();
1098
 
                        backEnd.pc.msec = t2 - t1;
1099
 
                        return;
1100
 
                }
1101
 
        }
1102
 
 
1103
 
}
1104
 
 
1105
 
 
1106
 
/*
1107
 
================
1108
 
RB_RenderThread
1109
 
================
1110
 
*/
1111
 
void RB_RenderThread( void ) {
1112
 
        const void      *data;
1113
 
 
1114
 
        // wait for either a rendering command or a quit command
1115
 
        while ( 1 ) {
1116
 
                // sleep until we have work to do
1117
 
                data = GLimp_RendererSleep();
1118
 
 
1119
 
                if ( !data ) {
1120
 
                        return; // all done, renderer is shutting down
1121
 
                }
1122
 
 
1123
 
                renderThreadActive = qtrue;
1124
 
 
1125
 
                RB_ExecuteRenderCommands( data );
1126
 
 
1127
 
                renderThreadActive = qfalse;
1128
 
        }
1129
 
}
1130