1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4 Copyright (C) 2006 Robert Beckebans <trebor_7@users.sourceforge.net>
5 
6 This file is part of XreaL source code.
7 
8 XreaL source code is free software; you can redistribute it
9 and/or modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the License,
11 or (at your option) any later version.
12 
13 XreaL source code is distributed in the hope that it will be
14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with XreaL source code; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21 ===========================================================================
22 */
23 // tr_backend.c
24 #include "tr_local.h"
25 
26 backEndData_t  *backEndData[SMP_FRAMES];
27 backEndState_t  backEnd;
28 
GL_Bind(image_t * image)29 void GL_Bind(image_t * image)
30 {
31 	int             texnum;
32 
33 	if(!image)
34 	{
35 		ri.Printf(PRINT_WARNING, "GL_Bind: NULL image\n");
36 		texnum = tr.defaultImage->texnum;
37 	}
38 	else
39 	{
40 		if(r_logFile->integer)
41 		{
42 			// don't just call LogComment, or we will get a call to va() every frame!
43 			GLimp_LogComment(va("--- GL_Bind( %s ) ---\n", image->name));
44 		}
45 
46 		texnum = image->texnum;
47 	}
48 
49 	if(r_nobind->integer && tr.blackImage)
50 	{
51 		// performance evaluation option
52 		texnum = tr.blackImage->texnum;
53 	}
54 
55 	if(glState.currenttextures[glState.currenttmu] != texnum)
56 	{
57 		image->frameUsed = tr.frameCount;
58 		glState.currenttextures[glState.currenttmu] = texnum;
59 		qglBindTexture(image->type, texnum);
60 	}
61 }
62 
GL_Program(GLhandleARB program)63 void GL_Program(GLhandleARB program)
64 {
65 	if(glConfig2.shadingLanguage100Available)
66 	{
67 		if(glState.currentProgram != program)
68 		{
69 			glState.currentProgram = program;
70 			qglUseProgramObjectARB(program);
71 		}
72 	}
73 }
74 
75 /*
76 ** GL_SelectTexture
77 */
GL_SelectTexture(int unit)78 void GL_SelectTexture(int unit)
79 {
80 	if(glState.currenttmu == unit)
81 	{
82 		return;
83 	}
84 
85 	if(unit >= 0 && unit <= 7)
86 	{
87 		qglActiveTextureARB(GL_TEXTURE0_ARB + unit);
88 		qglClientActiveTextureARB(GL_TEXTURE0_ARB + unit);
89 
90 		if(r_logFile->integer)
91 		{
92 			GLimp_LogComment(va("glActiveTextureARB( GL_TEXTURE%i_ARB )\n", unit));
93 			GLimp_LogComment(va("glClientActiveTextureARB( GL_TEXTURE%i_ARB )\n", unit));
94 		}
95 	}
96 	else
97 	{
98 		ri.Error(ERR_DROP, "GL_SelectTexture: unit = %i", unit);
99 	}
100 
101 	glState.currenttmu = unit;
102 }
103 
104 
105 /*
106 ** GL_BindMultitexture
107 */
GL_BindMultitexture(image_t * image0,GLuint env0,image_t * image1,GLuint env1)108 void GL_BindMultitexture(image_t * image0, GLuint env0, image_t * image1, GLuint env1)
109 {
110 	int             texnum0, texnum1;
111 
112 	texnum0 = image0->texnum;
113 	texnum1 = image1->texnum;
114 
115 	if(r_nobind->integer && tr.blackImage)
116 	{
117 		// performance evaluation option
118 		texnum0 = texnum1 = tr.blackImage->texnum;
119 	}
120 
121 	if(glState.currenttextures[1] != texnum1)
122 	{
123 		GL_SelectTexture(1);
124 		image1->frameUsed = tr.frameCount;
125 		glState.currenttextures[1] = texnum1;
126 		qglBindTexture(GL_TEXTURE_2D, texnum1);
127 	}
128 	if(glState.currenttextures[0] != texnum0)
129 	{
130 		GL_SelectTexture(0);
131 		image0->frameUsed = tr.frameCount;
132 		glState.currenttextures[0] = texnum0;
133 		qglBindTexture(GL_TEXTURE_2D, texnum0);
134 	}
135 }
136 
137 
138 /*
139 ** GL_Cull
140 */
GL_Cull(int cullType)141 void GL_Cull(int cullType)
142 {
143 	if(glState.faceCulling == cullType)
144 	{
145 		return;
146 	}
147 
148 	glState.faceCulling = cullType;
149 
150 	if(cullType == CT_TWO_SIDED)
151 	{
152 		qglDisable(GL_CULL_FACE);
153 	}
154 	else
155 	{
156 		qglEnable(GL_CULL_FACE);
157 
158 		if(cullType == CT_BACK_SIDED)
159 		{
160 			if(backEnd.viewParms.isMirror)
161 			{
162 				qglCullFace(GL_FRONT);
163 			}
164 			else
165 			{
166 				qglCullFace(GL_BACK);
167 			}
168 		}
169 		else
170 		{
171 			if(backEnd.viewParms.isMirror)
172 			{
173 				qglCullFace(GL_BACK);
174 			}
175 			else
176 			{
177 				qglCullFace(GL_FRONT);
178 			}
179 		}
180 	}
181 }
182 
183 /*
184 ** GL_TexEnv
185 */
GL_TexEnv(int env)186 void GL_TexEnv(int env)
187 {
188 	if(env == glState.texEnv[glState.currenttmu])
189 	{
190 		return;
191 	}
192 
193 	glState.texEnv[glState.currenttmu] = env;
194 
195 
196 	switch (env)
197 	{
198 		case GL_MODULATE:
199 			qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
200 			break;
201 		case GL_REPLACE:
202 			qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
203 			break;
204 		case GL_DECAL:
205 			qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
206 			break;
207 		case GL_ADD:
208 			qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
209 			break;
210 		default:
211 			ri.Error(ERR_DROP, "GL_TexEnv: invalid env '%d' passed\n", env);
212 			break;
213 	}
214 }
215 
216 /*
217 ** GL_State
218 **
219 ** This routine is responsible for setting the most commonly changed state
220 ** in Q3.
221 */
GL_State(unsigned long stateBits)222 void GL_State(unsigned long stateBits)
223 {
224 	unsigned long   diff = stateBits ^ glState.glStateBits;
225 
226 	if(!diff)
227 	{
228 		return;
229 	}
230 
231 	// check depthFunc bits
232 	if(diff & GLS_DEPTHFUNC_BITS)
233 	{
234 		switch (stateBits & GLS_DEPTHFUNC_BITS)
235 		{
236 			case 0:
237 				qglDepthFunc(GL_LEQUAL);
238 				break;
239 			case GLS_DEPTHFUNC_LESS:
240 				qglDepthFunc(GL_LESS);
241 				break;
242 			case GLS_DEPTHFUNC_EQUAL:
243 				qglDepthFunc(GL_EQUAL);
244 				break;
245 			default:
246 				assert(0);
247 				break;
248 		}
249 	}
250 
251 	// check blend bits
252 	if(diff & (GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS))
253 	{
254 		GLenum          srcFactor, dstFactor;
255 
256 		if(stateBits & (GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS))
257 		{
258 			switch (stateBits & GLS_SRCBLEND_BITS)
259 			{
260 				case GLS_SRCBLEND_ZERO:
261 					srcFactor = GL_ZERO;
262 					break;
263 				case GLS_SRCBLEND_ONE:
264 					srcFactor = GL_ONE;
265 					break;
266 				case GLS_SRCBLEND_DST_COLOR:
267 					srcFactor = GL_DST_COLOR;
268 					break;
269 				case GLS_SRCBLEND_ONE_MINUS_DST_COLOR:
270 					srcFactor = GL_ONE_MINUS_DST_COLOR;
271 					break;
272 				case GLS_SRCBLEND_SRC_ALPHA:
273 					srcFactor = GL_SRC_ALPHA;
274 					break;
275 				case GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA:
276 					srcFactor = GL_ONE_MINUS_SRC_ALPHA;
277 					break;
278 				case GLS_SRCBLEND_DST_ALPHA:
279 					srcFactor = GL_DST_ALPHA;
280 					break;
281 				case GLS_SRCBLEND_ONE_MINUS_DST_ALPHA:
282 					srcFactor = GL_ONE_MINUS_DST_ALPHA;
283 					break;
284 				case GLS_SRCBLEND_ALPHA_SATURATE:
285 					srcFactor = GL_SRC_ALPHA_SATURATE;
286 					break;
287 				default:
288 					srcFactor = GL_ONE;	// to get warning to shut up
289 					ri.Error(ERR_DROP, "GL_State: invalid src blend state bits\n");
290 					break;
291 			}
292 
293 			switch (stateBits & GLS_DSTBLEND_BITS)
294 			{
295 				case GLS_DSTBLEND_ZERO:
296 					dstFactor = GL_ZERO;
297 					break;
298 				case GLS_DSTBLEND_ONE:
299 					dstFactor = GL_ONE;
300 					break;
301 				case GLS_DSTBLEND_SRC_COLOR:
302 					dstFactor = GL_SRC_COLOR;
303 					break;
304 				case GLS_DSTBLEND_ONE_MINUS_SRC_COLOR:
305 					dstFactor = GL_ONE_MINUS_SRC_COLOR;
306 					break;
307 				case GLS_DSTBLEND_SRC_ALPHA:
308 					dstFactor = GL_SRC_ALPHA;
309 					break;
310 				case GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA:
311 					dstFactor = GL_ONE_MINUS_SRC_ALPHA;
312 					break;
313 				case GLS_DSTBLEND_DST_ALPHA:
314 					dstFactor = GL_DST_ALPHA;
315 					break;
316 				case GLS_DSTBLEND_ONE_MINUS_DST_ALPHA:
317 					dstFactor = GL_ONE_MINUS_DST_ALPHA;
318 					break;
319 				default:
320 					dstFactor = GL_ONE;	// to get warning to shut up
321 					ri.Error(ERR_DROP, "GL_State: invalid dst blend state bits\n");
322 					break;
323 			}
324 
325 			qglEnable(GL_BLEND);
326 			qglBlendFunc(srcFactor, dstFactor);
327 		}
328 		else
329 		{
330 			qglDisable(GL_BLEND);
331 		}
332 	}
333 
334 	// check colormask
335 	if(diff & GLS_COLORMASK_BITS)
336 	{
337 		if(stateBits & GLS_COLORMASK_BITS)
338 		{
339 			qglColorMask((stateBits & GLS_REDMASK_FALSE) ? GL_FALSE : GL_TRUE,
340 						 (stateBits & GLS_GREENMASK_FALSE) ? GL_FALSE : GL_TRUE,
341 						 (stateBits & GLS_BLUEMASK_FALSE) ? GL_FALSE : GL_TRUE,
342 						 (stateBits & GLS_ALPHAMASK_FALSE) ? GL_FALSE : GL_TRUE);
343 		}
344 		else
345 		{
346 			qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
347 		}
348 	}
349 
350 	// check depthmask
351 	if(diff & GLS_DEPTHMASK_TRUE)
352 	{
353 		if(stateBits & GLS_DEPTHMASK_TRUE)
354 		{
355 			qglDepthMask(GL_TRUE);
356 		}
357 		else
358 		{
359 			qglDepthMask(GL_FALSE);
360 		}
361 	}
362 
363 	// fill/line mode
364 	if(diff & GLS_POLYMODE_LINE)
365 	{
366 		if(stateBits & GLS_POLYMODE_LINE)
367 		{
368 			qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
369 		}
370 		else
371 		{
372 			qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
373 		}
374 	}
375 
376 	// depthtest
377 	if(diff & GLS_DEPTHTEST_DISABLE)
378 	{
379 		if(stateBits & GLS_DEPTHTEST_DISABLE)
380 		{
381 			qglDisable(GL_DEPTH_TEST);
382 		}
383 		else
384 		{
385 			qglEnable(GL_DEPTH_TEST);
386 		}
387 	}
388 
389 	// alpha test
390 	if(diff & GLS_ATEST_BITS)
391 	{
392 		switch (stateBits & GLS_ATEST_BITS)
393 		{
394 			case 0:
395 				qglDisable(GL_ALPHA_TEST);
396 				break;
397 			case GLS_ATEST_GT_0:
398 				qglEnable(GL_ALPHA_TEST);
399 				qglAlphaFunc(GL_GREATER, 0.0f);
400 				break;
401 			case GLS_ATEST_LT_80:
402 				qglEnable(GL_ALPHA_TEST);
403 				qglAlphaFunc(GL_LESS, 0.5f);
404 				break;
405 			case GLS_ATEST_GE_80:
406 				qglEnable(GL_ALPHA_TEST);
407 				qglAlphaFunc(GL_GEQUAL, 0.5f);
408 				break;
409 			case GLS_ATEST_GT_CUSTOM:
410 				// FIXME
411 				qglEnable(GL_ALPHA_TEST);
412 				qglAlphaFunc(GL_GREATER, 0.5f);
413 				break;
414 			default:
415 				assert(0);
416 				break;
417 		}
418 	}
419 
420 	// stenciltest
421 	if(diff & GLS_STENCILTEST_ENABLE)
422 	{
423 		if(stateBits & GLS_STENCILTEST_ENABLE)
424 		{
425 			qglEnable(GL_STENCIL_TEST);
426 		}
427 		else
428 		{
429 			qglDisable(GL_STENCIL_TEST);
430 		}
431 	}
432 
433 	glState.glStateBits = stateBits;
434 }
435 
436 
437 
438 /*
439 ================
440 RB_Hyperspace
441 
442 A player has predicted a teleport, but hasn't arrived yet
443 ================
444 */
RB_Hyperspace(void)445 static void RB_Hyperspace(void)
446 {
447 	float           c;
448 
449 	if(!backEnd.isHyperspace)
450 	{
451 		// do initialization shit
452 	}
453 
454 	c = (backEnd.refdef.time & 255) / 255.0f;
455 	qglClearColor(c, c, c, 1);
456 	qglClear(GL_COLOR_BUFFER_BIT);
457 
458 	backEnd.isHyperspace = qtrue;
459 }
460 
461 
SetViewportAndScissor(void)462 static void SetViewportAndScissor(void)
463 {
464 #if 0
465 	matrix_t        projectionMatrix;
466 
467 	// convert from our coordinate system (looking down X)
468 	// to OpenGL's coordinate system (looking down -Z)
469 	MatrixMultiply(backEnd.viewParms.projectionMatrix, quakeToOpenGLMatrix, projectionMatrix);
470 
471 	qglMatrixMode(GL_PROJECTION);
472 	qglLoadMatrixf(projectionMatrix);
473 	qglMatrixMode(GL_MODELVIEW);
474 #else
475 	qglMatrixMode(GL_PROJECTION);
476 	qglLoadMatrixf(backEnd.viewParms.projectionMatrix);
477 	qglMatrixMode(GL_MODELVIEW);
478 #endif
479 
480 	// set the window clipping
481 	qglViewport(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
482 				backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight);
483 
484 	qglScissor(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
485 			   backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight);
486 }
487 
488 
489 /*
490 ================
491 RB_SetGL2D
492 ================
493 */
RB_SetGL2D(void)494 static void RB_SetGL2D(void)
495 {
496 	GLimp_LogComment("--- RB_SetGL2D ---\n");
497 
498 	backEnd.projection2D = qtrue;
499 
500 	// set 2D virtual screen size
501 	qglViewport(0, 0, glConfig.vidWidth, glConfig.vidHeight);
502 	qglScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight);
503 	qglMatrixMode(GL_PROJECTION);
504 	qglLoadIdentity();
505 	qglOrtho(0, glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1);
506 	qglMatrixMode(GL_MODELVIEW);
507 	qglLoadIdentity();
508 
509 	GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
510 
511 	qglDisable(GL_CULL_FACE);
512 	qglDisable(GL_CLIP_PLANE0);
513 
514 	// set time for 2D shaders
515 	backEnd.refdef.time = ri.Milliseconds();
516 	backEnd.refdef.floatTime = backEnd.refdef.time * 0.001f;
517 }
518 
519 /*
520 =================
521 RB_BeginDrawingView
522 
523 Any mirrored or portaled views have already been drawn, so prepare
524 to actually render the visible surfaces for this view
525 =================
526 */
RB_BeginDrawingView(void)527 static void RB_BeginDrawingView(void)
528 {
529 	int             clearBits = 0;
530 
531 	GLimp_LogComment("--- RB_BeginDrawingView ---\n");
532 
533 	// sync with gl if needed
534 	if(r_finish->integer == 1 && !glState.finishCalled)
535 	{
536 		qglFinish();
537 		glState.finishCalled = qtrue;
538 	}
539 	if(r_finish->integer == 0)
540 	{
541 		glState.finishCalled = qtrue;
542 	}
543 
544 	// we will need to change the projection matrix before drawing
545 	// 2D images again
546 	backEnd.projection2D = qfalse;
547 
548 	// set the modelview matrix for the viewer
549 	SetViewportAndScissor();
550 
551 	// ensures that depth writes are enabled for the depth clear
552 	GL_State(GLS_DEFAULT);
553 
554 	// clear relevant buffers
555 	clearBits = GL_DEPTH_BUFFER_BIT;
556 
557 	if(r_measureOverdraw->integer || r_shadows->integer == 3)
558 	{
559 		clearBits |= GL_STENCIL_BUFFER_BIT;
560 	}
561 	if(r_fastsky->integer && !(backEnd.refdef.rdflags & RDF_NOWORLDMODEL))
562 	{
563 		clearBits |= GL_COLOR_BUFFER_BIT;	// FIXME: only if sky shaders have been used
564 #ifdef _DEBUG
565 		qglClearColor(0.0f, 0.0f, 1.0f, 1.0f);	// FIXME: get color of sky
566 #else
567 		qglClearColor(0.0f, 0.0f, 0.0f, 1.0f);	// FIXME: get color of sky
568 #endif
569 	}
570 	qglClear(clearBits);
571 
572 	if((backEnd.refdef.rdflags & RDF_HYPERSPACE))
573 	{
574 		RB_Hyperspace();
575 		return;
576 	}
577 	else
578 	{
579 		backEnd.isHyperspace = qfalse;
580 	}
581 
582 	glState.faceCulling = -1;	// force face culling to set next time
583 
584 	// we will only draw a sun if there was sky rendered in this view
585 	backEnd.skyRenderedThisView = qfalse;
586 
587 	// clip to the plane of the portal
588 	if(backEnd.viewParms.isPortal)
589 	{
590 		float           plane[4];
591 		double          plane2[4];
592 
593 		plane[0] = backEnd.viewParms.portalPlane.normal[0];
594 		plane[1] = backEnd.viewParms.portalPlane.normal[1];
595 		plane[2] = backEnd.viewParms.portalPlane.normal[2];
596 		plane[3] = backEnd.viewParms.portalPlane.dist;
597 
598 		plane2[0] = DotProduct(backEnd.viewParms.or.axis[0], plane);
599 		plane2[1] = DotProduct(backEnd.viewParms.or.axis[1], plane);
600 		plane2[2] = DotProduct(backEnd.viewParms.or.axis[2], plane);
601 		plane2[3] = DotProduct(plane, backEnd.viewParms.or.origin) - plane[3];
602 
603 //      qglLoadIdentity();
604 		qglLoadMatrixf(quakeToOpenGLMatrix);
605 		qglClipPlane(GL_CLIP_PLANE0, plane2);
606 		qglEnable(GL_CLIP_PLANE0);
607 	}
608 	else
609 	{
610 		qglDisable(GL_CLIP_PLANE0);
611 	}
612 
613 	GL_CheckErrors();
614 }
615 
RB_RenderDrawSurfaces(float originalTime,drawSurf_t * drawSurfs,int numDrawSurfs,qboolean opaque)616 static void RB_RenderDrawSurfaces(float originalTime, drawSurf_t * drawSurfs, int numDrawSurfs, qboolean opaque)
617 {
618 	trRefEntity_t  *entity, *oldEntity;
619 	int             lightmapNum, oldLightmapNum;
620 	shader_t       *shader, *oldShader;
621 	int             fogNum, oldFogNum;
622 	qboolean        depthRange, oldDepthRange;
623 	int             i;
624 	drawSurf_t     *drawSurf;
625 	int             oldSort;
626 
627 	GLimp_LogComment("--- RB_RenderDrawSurfaces ---\n");
628 
629 	// draw everything
630 	oldEntity = NULL;
631 	oldShader = NULL;
632 	oldLightmapNum = -1;
633 	oldFogNum = -1;
634 	oldDepthRange = qfalse;
635 	oldSort = -1;
636 	depthRange = qfalse;
637 
638 	for(i = 0, drawSurf = drawSurfs; i < numDrawSurfs; i++, drawSurf++)
639 	{
640 		// update locals
641 		entity = drawSurf->entity;
642 		shader = tr.sortedShaders[drawSurf->shaderNum];
643 		lightmapNum = drawSurf->lightmapNum;
644 		fogNum = drawSurf->fogNum;
645 
646 		if(opaque)
647 		{
648 			// skip all translucent surfaces that don't matter for this pass
649 			if(shader->sort > SS_OPAQUE)
650 			{
651 				break;
652 			}
653 		}
654 		else
655 		{
656 			// skip all opaque surfaces that don't matter for this pass
657 			if(shader->sort <= SS_OPAQUE)
658 			{
659 				continue;
660 			}
661 		}
662 
663 		if(entity == oldEntity && shader == oldShader && lightmapNum == oldLightmapNum && fogNum == oldFogNum)
664 		{
665 			// fast path, same as previous sort
666 			tess_surfaceTable[*drawSurf->surface] (drawSurf->surface, 0, NULL, 0, NULL);
667 			continue;
668 		}
669 
670 		// change the tess parameters if needed
671 		// a "entityMergable" shader is a shader that can have surfaces from seperate
672 		// entities merged into a single batch, like smoke and blood puff sprites
673 		if(shader != oldShader
674 		   || fogNum != oldFogNum || lightmapNum != oldLightmapNum || (entity != oldEntity && !shader->entityMergable))
675 		{
676 			if(oldShader != NULL)
677 			{
678 				Tess_End();
679 			}
680 
681 			Tess_Begin(shader, NULL, lightmapNum, fogNum, qfalse, qfalse);
682 			oldShader = shader;
683 			oldLightmapNum = lightmapNum;
684 			oldFogNum = fogNum;
685 		}
686 
687 		// change the modelview matrix if needed
688 		if(entity != oldEntity)
689 		{
690 			depthRange = qfalse;
691 
692 			if(entity != &tr.worldEntity)
693 			{
694 				backEnd.currentEntity = entity;
695 				backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime;
696 
697 				// we have to reset the shaderTime as well otherwise image animations start
698 				// from the wrong frame
699 				tess.shaderTime = backEnd.refdef.floatTime - tess.surfaceShader->timeOffset;
700 
701 				// set up the transformation matrix
702 				R_RotateForEntity(backEnd.currentEntity, &backEnd.viewParms, &backEnd.or);
703 
704 				if(backEnd.currentEntity->e.renderfx & RF_DEPTHHACK)
705 				{
706 					// hack the depth range to prevent view model from poking into walls
707 					depthRange = qtrue;
708 				}
709 			}
710 			else
711 			{
712 				backEnd.currentEntity = &tr.worldEntity;
713 				backEnd.refdef.floatTime = originalTime;
714 				backEnd.or = backEnd.viewParms.world;
715 
716 				// we have to reset the shaderTime as well otherwise image animations on
717 				// the world (like water) continue with the wrong frame
718 				tess.shaderTime = backEnd.refdef.floatTime - tess.surfaceShader->timeOffset;
719 			}
720 
721 			qglLoadMatrixf(backEnd.or.modelViewMatrix);
722 
723 			// change depthrange if needed
724 			if(oldDepthRange != depthRange)
725 			{
726 				if(depthRange)
727 				{
728 					qglDepthRange(0, 0.3);
729 				}
730 				else
731 				{
732 					qglDepthRange(0, 1);
733 				}
734 				oldDepthRange = depthRange;
735 			}
736 
737 			oldEntity = entity;
738 		}
739 
740 		// add the triangles for this surface
741 		tess_surfaceTable[*drawSurf->surface] (drawSurf->surface, 0, NULL, 0, NULL);
742 	}
743 
744 	backEnd.refdef.floatTime = originalTime;
745 
746 	// draw the contents of the last shader batch
747 	if(oldShader != NULL)
748 	{
749 		Tess_End();
750 	}
751 
752 	// go back to the world modelview matrix
753 	qglLoadMatrixf(backEnd.viewParms.world.modelViewMatrix);
754 	if(depthRange)
755 	{
756 		qglDepthRange(0, 1);
757 	}
758 
759 	GL_CheckErrors();
760 }
761 
762 /*
763 =================
764 RB_RenderInteractions
765 =================
766 */
RB_RenderInteractions(float originalTime,interaction_t * interactions,int numInteractions)767 static void RB_RenderInteractions(float originalTime, interaction_t * interactions, int numInteractions)
768 {
769 	shader_t       *shader, *oldShader;
770 	trRefEntity_t  *entity, *oldEntity;
771 	trRefDlight_t  *light, *oldLight;
772 	interaction_t  *ia;
773 	qboolean        depthRange, oldDepthRange;
774 	int             iaCount;
775 	surfaceType_t  *surface;
776 	vec3_t          tmp;
777 	matrix_t        modelToLight;
778 
779 	GLimp_LogComment("--- RB_RenderInteractions ---\n");
780 
781 	// draw everything
782 	oldLight = NULL;
783 	oldEntity = NULL;
784 	oldShader = NULL;
785 	oldDepthRange = qfalse;
786 	depthRange = qfalse;
787 
788 	tess.currentStageIteratorType = SIT_LIGHTING;
789 
790 	// render interactions
791 	for(iaCount = 0, ia = &interactions[0]; iaCount < numInteractions;)
792 	{
793 		backEnd.currentLight = light = ia->dlight;
794 		backEnd.currentEntity = entity = ia->entity;
795 		surface = ia->surface;
796 		shader = ia->surfaceShader;
797 
798 		if(glConfig2.occlusionQueryBits && !ia->occlusionQuerySamples)
799 		{
800 			// skip all interactions of this light because it failed the occlusion query
801 			goto nextInteraction;
802 		}
803 
804 		if(!shader->interactLight)
805 		{
806 			// skip this interaction because the surface shader has no ability to interact with light
807 			// this will save texcoords and matrix calculations
808 			goto nextInteraction;
809 		}
810 
811 		if(light != oldLight)
812 		{
813 			// set light scissor to reduce fillrate
814 			qglScissor(ia->scissorX, ia->scissorY, ia->scissorWidth, ia->scissorHeight);
815 
816 			#if 0
817 			if(!light->additive)
818 			{
819 				GL_State(GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL);
820 			}
821 			else
822 			#endif
823 			{
824 				GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL);
825 			}
826 		}
827 
828 		// Tr3B - this should never happen in the first iteration
829 		if(!r_nobatching->integer && light == oldLight && entity == oldEntity && shader == oldShader)
830 		{
831 			if(ia->type != IA_SHADOWONLY)
832 			{
833 				// fast path, same as previous
834 				tess_surfaceTable[*surface] (surface, ia->numLightIndexes, ia->lightIndexes, 0, NULL);
835 				goto nextInteraction;
836 			}
837 		}
838 
839 		// draw the contents of the last shader batch
840 		if(oldEntity != NULL || oldLight != NULL || oldShader != NULL)
841 		{
842 			Tess_End();
843 		}
844 
845 		// we need a new batch
846 		Tess_Begin(shader, ia->dlightShader, -1, 0, qfalse, qfalse);
847 
848 		// change the modelview matrix if needed
849 		if(entity != oldEntity)
850 		{
851 			depthRange = qfalse;
852 
853 			if(entity != &tr.worldEntity)
854 			{
855 				backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime;
856 				// we have to reset the shaderTime as well otherwise image animations start
857 				// from the wrong frame
858 				tess.shaderTime = backEnd.refdef.floatTime - tess.surfaceShader->timeOffset;
859 
860 				// set up the transformation matrix
861 				R_RotateForEntity(backEnd.currentEntity, &backEnd.viewParms, &backEnd.or);
862 
863 				if(backEnd.currentEntity->e.renderfx & RF_DEPTHHACK)
864 				{
865 					// hack the depth range to prevent view model from poking into walls
866 					depthRange = qtrue;
867 				}
868 			}
869 			else
870 			{
871 				backEnd.refdef.floatTime = originalTime;
872 				backEnd.or = backEnd.viewParms.world;
873 				// we have to reset the shaderTime as well otherwise image animations on
874 				// the world (like water) continue with the wrong frame
875 				tess.shaderTime = backEnd.refdef.floatTime - tess.surfaceShader->timeOffset;
876 			}
877 
878 			qglLoadMatrixf(backEnd.or.modelViewMatrix);
879 
880 			// change depthrange if needed
881 			if(oldDepthRange != depthRange)
882 			{
883 				if(depthRange)
884 				{
885 					qglDepthRange(0, 0.3);
886 				}
887 				else
888 				{
889 					qglDepthRange(0, 1);
890 				}
891 				oldDepthRange = depthRange;
892 			}
893 		}
894 
895 		// change the attenuation matrix if needed
896 		if(light != oldLight || entity != oldEntity)
897 		{
898 			// transform light origin into model space for u_LightOrigin parameter
899 			if(entity != &tr.worldEntity)
900 			{
901 				VectorSubtract(light->origin, backEnd.or.origin, tmp);
902 				light->transformed[0] = DotProduct(tmp, backEnd.or.axis[0]);
903 				light->transformed[1] = DotProduct(tmp, backEnd.or.axis[1]);
904 				light->transformed[2] = DotProduct(tmp, backEnd.or.axis[2]);
905 			}
906 			else
907 			{
908 				VectorCopy(light->origin, light->transformed);
909 			}
910 
911 			// build the attenuation matrix using the entity transform
912 			MatrixMultiply(light->viewMatrix, backEnd.or.transformMatrix, modelToLight);
913 
914 			MatrixSetupTranslation(light->attenuationMatrix, 0.5, 0.5, 0.5);	// bias
915 			MatrixMultiplyScale(light->attenuationMatrix, 0.5, 0.5, 0.5);	// scale
916 			MatrixMultiply2(light->attenuationMatrix, light->projectionMatrix);	// light projection (frustum)
917 			MatrixMultiply2(light->attenuationMatrix, modelToLight);
918 		}
919 
920 		if(ia->type != IA_SHADOWONLY)
921 		{
922 			// add the triangles for this surface
923 			tess_surfaceTable[*surface] (surface, ia->numLightIndexes, ia->lightIndexes, 0, NULL);
924 		}
925 
926 	  nextInteraction:
927 		if(!ia->next)
928 		{
929 			if(glConfig2.occlusionQueryBits && !ia->occlusionQuerySamples)
930 			{
931 				// do nothing
932 			}
933 			else if(!shader->interactLight)
934 			{
935 				// do nothing as well
936 			}
937 			else
938 			{
939 				// draw the contents of the current shader batch
940 				Tess_End();
941 			}
942 
943 			if(iaCount < (numInteractions - 1))
944 			{
945 				// jump to next interaction and continue
946 				ia++;
947 				iaCount++;
948 			}
949 			else
950 			{
951 				// increase last time to leave for loop
952 				iaCount++;
953 			}
954 		}
955 		else
956 		{
957 			// just continue
958 			ia = ia->next;
959 			iaCount++;
960 		}
961 
962 		// remember values
963 		oldLight = light;
964 		oldEntity = entity;
965 		oldShader = shader;
966 	}
967 
968 	backEnd.refdef.floatTime = originalTime;
969 
970 	// go back to the world modelview matrix
971 	qglLoadMatrixf(backEnd.viewParms.world.modelViewMatrix);
972 	if(depthRange)
973 	{
974 		qglDepthRange(0, 1);
975 	}
976 
977 	// reset scissor
978 	qglScissor(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
979 			   backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight);
980 
981 	// reset stage iterator
982 	tess.currentStageIteratorType = SIT_DEFAULT;
983 
984 	GL_CheckErrors();
985 }
986 
987 
988 /*
989 =================
990 RB_RenderInteractionsStencilShadowed
991 =================
992 */
RB_RenderInteractionsStencilShadowed(float originalTime,interaction_t * interactions,int numInteractions)993 static void RB_RenderInteractionsStencilShadowed(float originalTime, interaction_t * interactions, int numInteractions)
994 {
995 	shader_t       *shader, *oldShader;
996 	trRefEntity_t  *entity, *oldEntity;
997 	trRefDlight_t  *light, *oldLight;
998 	interaction_t  *ia;
999 	int             iaCount;
1000 	int             iaFirst = 0;
1001 	surfaceType_t  *surface;
1002 	qboolean        depthRange, oldDepthRange;
1003 	vec3_t          tmp;
1004 	matrix_t        modelToLight;
1005 	qboolean        drawShadows;
1006 
1007 	if(glConfig.stencilBits < 4 || !glConfig2.shadingLanguage100Available)
1008 	{
1009 		RB_RenderInteractions(originalTime, interactions, numInteractions);
1010 		return;
1011 	}
1012 
1013 	GLimp_LogComment("--- RB_RenderInteractionsStencilShadowed ---\n");
1014 
1015 	// draw everything
1016 	oldLight = NULL;
1017 	oldEntity = NULL;
1018 	oldShader = NULL;
1019 	oldDepthRange = qfalse;
1020 	depthRange = qfalse;
1021 	drawShadows = qtrue;
1022 
1023 	tess.currentStageIteratorType = SIT_LIGHTING_STENCIL;
1024 
1025 	// render interactions
1026 	for(iaCount = 0, ia = &interactions[0]; iaCount < numInteractions;)
1027 	{
1028 		backEnd.currentLight = light = ia->dlight;
1029 		backEnd.currentEntity = entity = ia->entity;
1030 		surface = ia->surface;
1031 		shader = ia->surfaceShader;
1032 
1033 		// only iaFirst == iaCount if first iteration or counters were reset
1034 		if(light != oldLight || iaFirst == iaCount)
1035 		{
1036 			iaFirst = iaCount;
1037 
1038 			if(drawShadows)
1039 			{
1040 				// set light scissor to reduce fillrate
1041 				qglScissor(ia->scissorX, ia->scissorY, ia->scissorWidth, ia->scissorHeight);
1042 
1043 				// set depth test to reduce fillrate
1044 				if(qglDepthBoundsEXT)
1045 				{
1046 					if(!ia->noDepthBoundsTest)
1047 					{
1048 						qglEnable(GL_DEPTH_BOUNDS_TEST_EXT);
1049 						qglDepthBoundsEXT(ia->depthNear, ia->depthFar);
1050 					}
1051 					else
1052 					{
1053 						qglDisable(GL_DEPTH_BOUNDS_TEST_EXT);
1054 					}
1055 				}
1056 
1057 				// set the reference stencil value
1058 				qglClearStencil(128);
1059 
1060 				// reset stencil buffer
1061 				qglClear(GL_STENCIL_BUFFER_BIT);
1062 
1063 				// use less compare as depthfunc
1064 				// don't write to the color buffer or depth buffer
1065 				// enable stencil testing for this light
1066 				GL_State(GLS_DEPTHFUNC_LESS | GLS_COLORMASK_BITS | GLS_STENCILTEST_ENABLE);
1067 
1068 				qglStencilFunc(GL_ALWAYS, 128, ~0);
1069 				qglStencilMask(~0);
1070 
1071 				qglEnable(GL_POLYGON_OFFSET_FILL);
1072 				qglPolygonOffset(r_shadowOffsetFactor->value, r_shadowOffsetUnits->value);
1073 
1074 				// enable shadow volume extrusion shader
1075 				#if 1
1076 				GL_Program(tr.shadowShader.program);
1077 				GL_ClientState(tr.shadowShader.attribs);
1078 				#else
1079 				GL_Program(0);
1080 				GL_ClientState(GLCS_VERTEX);
1081 				GL_SelectTexture(0);
1082 				GL_Bind(tr.whiteImage);
1083 				#endif
1084 
1085 				qglVertexPointer(4, GL_FLOAT, 0, tess.xyz);
1086 			}
1087 			else
1088 			{
1089 				// Tr3B - see RobustShadowVolumes.pdf by Nvidia
1090 				// Set stencil testing to render only pixels with a zero
1091 				// stencil value, i.e., visible fragments illuminated by the
1092 				// current light. Use equal depth testing to update only the
1093 				// visible fragments, and then, increment stencil to avoid
1094 				// double blending. Re-enable color buffer writes again.
1095 
1096 				#if 0
1097 				if(!light->additive)
1098 				{
1099 					GL_State(GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL | GLS_STENCILTEST_ENABLE);
1100 				}
1101 				else
1102 				#endif
1103 				{
1104 					GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL | GLS_STENCILTEST_ENABLE);
1105 				}
1106 
1107 				if(light->l.noShadows)
1108 				{
1109 					// don't consider shadow volumes
1110 					qglStencilFunc(GL_ALWAYS, 128, ~0);
1111 				}
1112 				else
1113 				{
1114 					qglStencilFunc(GL_EQUAL, 128, ~0);
1115 				}
1116 				qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);//GL_INCR);
1117 
1118 				qglDisable(GL_POLYGON_OFFSET_FILL);
1119 
1120 				// disable shadow volume extrusion shader
1121 				GL_Program(0);
1122 			}
1123 		}
1124 
1125 		if(drawShadows)
1126 		{
1127 			if(!r_nobatching->integer && light == oldLight && entity == oldEntity && shader == oldShader)
1128 			{
1129 				if(!(entity->e.renderfx & (RF_NOSHADOW | RF_DEPTHHACK)) &&
1130 				   shader->sort == SS_OPAQUE &&
1131 				   !shader->noShadows &&
1132 				   !light->l.noShadows &&
1133 				   ia->type != IA_LIGHTONLY)
1134 				{
1135 					// fast path, same as previous
1136 					tess_surfaceTable[*surface] (surface, 0, NULL, ia->numShadowIndexes, ia->shadowIndexes);
1137 					goto nextInteraction;
1138 				}
1139 			}
1140 			else
1141 			{
1142 				// draw the contents of the last shader batch
1143 				if(oldEntity != NULL || oldLight != NULL || oldShader != NULL)
1144 				{
1145 					Tess_End();
1146 				}
1147 
1148 				// we don't need tangent space calculations here
1149 				Tess_Begin(shader, ia->dlightShader, -1, 0, qtrue, qtrue);
1150 			}
1151 		}
1152 		else
1153 		{
1154 			if(!r_nobatching->integer && light == oldLight && entity == oldEntity && shader == oldShader)
1155 			{
1156 				if(shader->interactLight && ia->type != IA_SHADOWONLY)
1157 				{
1158 					// fast path, same as previous
1159 					tess_surfaceTable[*surface] (surface, ia->numLightIndexes, ia->lightIndexes, 0, NULL);
1160 					goto nextInteraction;
1161 				}
1162 			}
1163 			else
1164 			{
1165 				// draw the contents of the last shader batch
1166 				if(oldEntity != NULL || oldLight != NULL || oldShader != NULL)
1167 				{
1168 					Tess_End();
1169 				}
1170 
1171 				Tess_Begin(shader, ia->dlightShader, -1, 0, qfalse, qfalse);
1172 			}
1173 		}
1174 
1175 		// change the modelview matrix if needed
1176 		if(entity != oldEntity)
1177 		{
1178 			depthRange = qfalse;
1179 
1180 			if(entity != &tr.worldEntity)
1181 			{
1182 				backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime;
1183 				// we have to reset the shaderTime as well otherwise image animations start
1184 				// from the wrong frame
1185 				tess.shaderTime = backEnd.refdef.floatTime - tess.surfaceShader->timeOffset;
1186 
1187 				// set up the transformation matrix
1188 				R_RotateForEntity(backEnd.currentEntity, &backEnd.viewParms, &backEnd.or);
1189 
1190 				if(backEnd.currentEntity->e.renderfx & RF_DEPTHHACK)
1191 				{
1192 					// hack the depth range to prevent view model from poking into walls
1193 					depthRange = qtrue;
1194 				}
1195 			}
1196 			else
1197 			{
1198 				backEnd.refdef.floatTime = originalTime;
1199 				backEnd.or = backEnd.viewParms.world;
1200 				// we have to reset the shaderTime as well otherwise image animations on
1201 				// the world (like water) continue with the wrong frame
1202 				tess.shaderTime = backEnd.refdef.floatTime - tess.surfaceShader->timeOffset;
1203 			}
1204 
1205 			qglLoadMatrixf(backEnd.or.modelViewMatrix);
1206 
1207 			// change depthrange if needed
1208 			if(oldDepthRange != depthRange)
1209 			{
1210 				if(depthRange)
1211 				{
1212 					qglDepthRange(0, 0.3);
1213 				}
1214 				else
1215 				{
1216 					qglDepthRange(0, 1);
1217 				}
1218 				oldDepthRange = depthRange;
1219 			}
1220 		}
1221 
1222 		// change the attenuation matrix if needed
1223 		if(light != oldLight || entity != oldEntity)
1224 		{
1225 			// transform light origin into model space for u_LightOrigin parameter
1226 			if(entity != &tr.worldEntity)
1227 			{
1228 				VectorSubtract(light->origin, backEnd.or.origin, tmp);
1229 				light->transformed[0] = DotProduct(tmp, backEnd.or.axis[0]);
1230 				light->transformed[1] = DotProduct(tmp, backEnd.or.axis[1]);
1231 				light->transformed[2] = DotProduct(tmp, backEnd.or.axis[2]);
1232 			}
1233 			else
1234 			{
1235 				VectorCopy(light->origin, light->transformed);
1236 			}
1237 
1238 			if(drawShadows)
1239 			{
1240 				// set uniform parameter u_LightOrigin for GLSL shader
1241 				#if 1
1242 				qglUniform3fARB(tr.shadowShader.u_LightOrigin,
1243 								light->transformed[0], light->transformed[1], light->transformed[2]);
1244 				#endif
1245 			}
1246 
1247 			// build the attenuation matrix using the entity transform
1248 			MatrixMultiply(light->viewMatrix, backEnd.or.transformMatrix, modelToLight);
1249 
1250 			MatrixSetupTranslation(light->attenuationMatrix, 0.5, 0.5, 0.5);	// bias
1251 			MatrixMultiplyScale(light->attenuationMatrix, 0.5, 0.5, 0.5);	// scale
1252 			MatrixMultiply2(light->attenuationMatrix, light->projectionMatrix);	// light projection (frustum)
1253 			MatrixMultiply2(light->attenuationMatrix, modelToLight);
1254 		}
1255 
1256 		if(drawShadows)
1257 		{
1258 			if(!(entity->e.renderfx & (RF_NOSHADOW | RF_DEPTHHACK)) &&
1259 			   shader->sort == SS_OPAQUE &&
1260 			   !shader->noShadows &&
1261 			   !light->l.noShadows &&
1262 			   ia->type != IA_LIGHTONLY)
1263 			{
1264 				// add the triangles for this surface
1265 				tess_surfaceTable[*surface] (surface, 0, NULL, ia->numShadowIndexes, ia->shadowIndexes);
1266 			}
1267 		}
1268 		else
1269 		{
1270 			if(shader->interactLight && ia->type != IA_SHADOWONLY)
1271 			{
1272 				// add the triangles for this surface
1273 				tess_surfaceTable[*surface] (surface, ia->numLightIndexes, ia->lightIndexes, 0, NULL);
1274 			}
1275 		}
1276 
1277 	  nextInteraction:
1278 		if(!ia->next)
1279 		{
1280 			// if ia->next does not point to any other interaction then
1281 			// this is the last interaction of the current light
1282 
1283 			if(drawShadows)
1284 			{
1285 				// jump back to first interaction of this light and start lighting
1286 				ia = &interactions[iaFirst];
1287 				iaCount = iaFirst;
1288 				drawShadows = qfalse;
1289 			}
1290 			else
1291 			{
1292 				if(iaCount < (numInteractions - 1))
1293 				{
1294 					// jump to next interaction and start shadowing
1295 					ia++;
1296 					iaCount++;
1297 					drawShadows = qtrue;
1298 				}
1299 				else
1300 				{
1301 					// increase last time to leave for loop
1302 					iaCount++;
1303 				}
1304 			}
1305 
1306 			// draw the contents of the current shader batch
1307 			Tess_End();
1308 		}
1309 		else
1310 		{
1311 			// just continue
1312 			ia = ia->next;
1313 			iaCount++;
1314 		}
1315 
1316 		// remember values
1317 		oldLight = light;
1318 		oldEntity = entity;
1319 		oldShader = shader;
1320 	}
1321 
1322 	backEnd.refdef.floatTime = originalTime;
1323 
1324 	// go back to the world modelview matrix
1325 	qglLoadMatrixf(backEnd.viewParms.world.modelViewMatrix);
1326 	if(depthRange)
1327 	{
1328 		qglDepthRange(0, 1);
1329 	}
1330 
1331 	// reset scissor clamping
1332 	qglScissor(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
1333 			   backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight);
1334 
1335 	// reset depth clamping
1336 	if(qglDepthBoundsEXT)
1337 	{
1338 		qglDisable(GL_DEPTH_BOUNDS_TEST_EXT);
1339 	}
1340 
1341 	// reset stage iterator
1342 	tess.currentStageIteratorType = SIT_DEFAULT;
1343 
1344 	GL_CheckErrors();
1345 }
1346 
RB_RenderOcclusionQueries(interaction_t * interactions,int numInteractions)1347 static void RB_RenderOcclusionQueries(interaction_t * interactions, int numInteractions)
1348 {
1349 	GLimp_LogComment("--- RB_RenderOcclusionQueries ---\n");
1350 
1351 	if(glConfig2.occlusionQueryBits)
1352 	{
1353 		int				i;
1354 		interaction_t  *ia;
1355 		int             iaCount;
1356 		int             iaFirst;
1357 		trRefDlight_t  *light, *oldLight;
1358 		int             ocCount;
1359 		GLint           ocSamples = 0;
1360 		qboolean        queryObjects;
1361 		GLint			available;
1362 
1363 		qglColor4f(1.0f, 0.0f, 0.0f, 0.05f);
1364 
1365 		GL_Program(0);
1366 		GL_Cull(CT_TWO_SIDED);
1367 		GL_SelectTexture(0);
1368 		qglDisable(GL_TEXTURE_2D);
1369 
1370 		// don't write to the color buffer or depth buffer
1371 		if(r_showOcclusionQueries->integer)
1372 		{
1373 			GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
1374 		}
1375 		else
1376 		{
1377 			GL_State(GLS_COLORMASK_BITS);
1378 		}
1379 
1380 		// loop trough all light interactions and render the light OBB for each last interaction
1381 		ocCount = -1;
1382 		for(iaCount = 0, ia = &interactions[0]; iaCount < numInteractions;)
1383 		{
1384 			backEnd.currentLight = light = ia->dlight;
1385 
1386 			if(!ia->next)
1387 			{
1388 				ocCount++;
1389 
1390 				// last interaction of current light
1391 				if(ocCount < (MAX_OCCLUSION_QUERIES - 1) /*&& R_CullLightPoint(light, backEnd.viewParms.or.origin) == CULL_OUT */ )
1392 				{
1393 					R_RotateForDlight(light, &backEnd.viewParms, &backEnd.or);
1394 					qglLoadMatrixf(backEnd.or.modelViewMatrix);
1395 
1396 					// begin the occlusion query
1397 					qglBeginQueryARB(GL_SAMPLES_PASSED, tr.occlusionQueryObjects[ocCount]);
1398 
1399 					qglBegin(GL_QUADS);
1400 
1401 					qglVertex3f(light->localBounds[0][0], light->localBounds[0][1], light->localBounds[0][2]);
1402 					qglVertex3f(light->localBounds[0][0], light->localBounds[1][1], light->localBounds[0][2]);
1403 					qglVertex3f(light->localBounds[0][0], light->localBounds[1][1], light->localBounds[1][2]);
1404 					qglVertex3f(light->localBounds[0][0], light->localBounds[0][1], light->localBounds[1][2]);
1405 
1406 					qglVertex3f(light->localBounds[1][0], light->localBounds[0][1], light->localBounds[0][2]);
1407 					qglVertex3f(light->localBounds[1][0], light->localBounds[1][1], light->localBounds[0][2]);
1408 					qglVertex3f(light->localBounds[1][0], light->localBounds[1][1], light->localBounds[1][2]);
1409 					qglVertex3f(light->localBounds[1][0], light->localBounds[0][1], light->localBounds[1][2]);
1410 
1411 					qglVertex3f(light->localBounds[0][0], light->localBounds[0][1], light->localBounds[1][2]);
1412 					qglVertex3f(light->localBounds[0][0], light->localBounds[1][1], light->localBounds[1][2]);
1413 					qglVertex3f(light->localBounds[1][0], light->localBounds[1][1], light->localBounds[1][2]);
1414 					qglVertex3f(light->localBounds[1][0], light->localBounds[0][1], light->localBounds[1][2]);
1415 
1416 					qglVertex3f(light->localBounds[0][0], light->localBounds[0][1], light->localBounds[0][2]);
1417 					qglVertex3f(light->localBounds[0][0], light->localBounds[1][1], light->localBounds[0][2]);
1418 					qglVertex3f(light->localBounds[1][0], light->localBounds[1][1], light->localBounds[0][2]);
1419 					qglVertex3f(light->localBounds[1][0], light->localBounds[0][1], light->localBounds[0][2]);
1420 
1421 					qglVertex3f(light->localBounds[0][0], light->localBounds[0][1], light->localBounds[0][2]);
1422 					qglVertex3f(light->localBounds[0][0], light->localBounds[0][1], light->localBounds[1][2]);
1423 					qglVertex3f(light->localBounds[1][0], light->localBounds[0][1], light->localBounds[1][2]);
1424 					qglVertex3f(light->localBounds[1][0], light->localBounds[0][1], light->localBounds[0][2]);
1425 
1426 					qglVertex3f(light->localBounds[0][0], light->localBounds[1][1], light->localBounds[0][2]);
1427 					qglVertex3f(light->localBounds[0][0], light->localBounds[1][1], light->localBounds[1][2]);
1428 					qglVertex3f(light->localBounds[1][0], light->localBounds[1][1], light->localBounds[1][2]);
1429 					qglVertex3f(light->localBounds[1][0], light->localBounds[1][1], light->localBounds[0][2]);
1430 
1431 					qglEnd();
1432 
1433 					// end the query
1434 					// don't read back immediately so that we give the query time to be ready
1435 					qglEndQueryARB(GL_SAMPLES_PASSED);
1436 
1437 					backEnd.pc.c_occlusionQueries++;
1438 				}
1439 
1440 				if(iaCount < (numInteractions - 1))
1441 				{
1442 					// jump to next interaction and continue
1443 					ia++;
1444 					iaCount++;
1445 				}
1446 				else
1447 				{
1448 					// increase last time to leave for loop
1449 					iaCount++;
1450 				}
1451 			}
1452 			else
1453 			{
1454 				// just continue
1455 				ia = ia->next;
1456 				iaCount++;
1457 			}
1458 		}
1459 
1460 		// go back to the world modelview matrix
1461 		backEnd.or = backEnd.viewParms.world;
1462 		qglLoadMatrixf(backEnd.viewParms.world.modelViewMatrix);
1463 
1464 		if(!ocCount)
1465 		{
1466 			qglEnable(GL_TEXTURE_2D);
1467 			return;
1468 		}
1469 
1470 		qglFlush();
1471 
1472 		// do other work until "most" of the queries are back, to avoid
1473         // wasting time spinning
1474         #if 1
1475         i = (int)(ocCount * 3 / 4); // instead of N-1, to prevent the GPU from going idle
1476         do
1477         {
1478         	i++;
1479 
1480         	//if(i >= ocCount)
1481         	//	i = (int)(ocCount * 3 / 4);
1482 
1483        		qglGetQueryObjectivARB(tr.occlusionQueryObjects[i], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
1484 	    }while(!available && i < ocCount);
1485 	    #endif
1486 
1487 		// reenable writes to depth and color buffers
1488 		GL_State(GLS_DEPTHMASK_TRUE);
1489 		qglEnable(GL_TEXTURE_2D);
1490 
1491 		// loop trough all light interactions and fetch results for each last interaction
1492 		// then copy result to all other interactions that belong to the same light
1493 		ocCount = -1;
1494 		iaFirst = 0;
1495 		queryObjects = qtrue;
1496 		oldLight = NULL;
1497 		for(iaCount = 0, ia = &interactions[0]; iaCount < numInteractions;)
1498 		{
1499 			backEnd.currentLight = light = ia->dlight;
1500 
1501 			if(light != oldLight)
1502 			{
1503 				iaFirst = iaCount;
1504 			}
1505 
1506 			if(!queryObjects)
1507 			{
1508 				ia->occlusionQuerySamples = ocSamples;
1509 			}
1510 
1511 			if(!ia->next)
1512 			{
1513 				if(queryObjects)
1514 				{
1515 					ocCount++;
1516 
1517 					if(ocCount < (MAX_OCCLUSION_QUERIES - 1) /*&& R_CullLightPoint(light, backEnd.viewParms.or.origin) == CULL_OUT */ )
1518 					{
1519 						qglGetQueryObjectivARB(tr.occlusionQueryObjects[ocCount], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
1520 						if(available)
1521 						{
1522 							backEnd.pc.c_occlusionQueriesAvailable++;
1523 
1524 							// get the object and store it in the occlusion bits for the light
1525 							qglGetQueryObjectivARB(tr.occlusionQueryObjects[ocCount], GL_QUERY_RESULT, &ocSamples);
1526 
1527 							if(ocSamples <= 0)
1528 							{
1529 								backEnd.pc.c_occlusionQueriesCulled++;
1530 							}
1531 						}
1532 						else
1533 						{
1534 							ocSamples = 1;
1535 						}
1536 					}
1537 					else
1538 					{
1539 						ocSamples = 1;
1540 					}
1541 
1542 					// jump back to first interaction of this light copy query result
1543 					ia = &interactions[iaFirst];
1544 					iaCount = iaFirst;
1545 					queryObjects = qfalse;
1546 				}
1547 				else
1548 				{
1549 					if(iaCount < (numInteractions - 1))
1550 					{
1551 						// jump to next interaction and start querying
1552 						ia++;
1553 						iaCount++;
1554 						queryObjects = qtrue;
1555 					}
1556 					else
1557 					{
1558 						// increase last time to leave for loop
1559 						iaCount++;
1560 					}
1561 				}
1562 			}
1563 			else
1564 			{
1565 				// just continue
1566 				ia = ia->next;
1567 				iaCount++;
1568 			}
1569 
1570 			oldLight = light;
1571 		}
1572 	}
1573 #if 0
1574 	// Tr3B - try to cull light interactions manually with stencil overdraw test
1575 	else
1576 	{
1577 		interaction_t  *ia;
1578 		int             iaCount;
1579 		int             iaFirst = 0;
1580 		trRefDlight_t  *light, *oldLight;
1581 		int             i;
1582 		long            sum = 0;
1583 		unsigned char  *stencilReadback;
1584 		qboolean        calcSum;
1585 
1586 		qglColor4f(1.0f, 0.0f, 0.0f, 0.05f);
1587 
1588 		GL_Program(0);
1589 		GL_Cull(CT_TWO_SIDED);
1590 		GL_SelectTexture(0);
1591 		GL_Bind(tr.whiteImage);
1592 
1593 		stencilReadback = ri.Hunk_AllocateTempMemory(glConfig.vidWidth * glConfig.vidHeight);
1594 
1595 		// don't write to the color buffer or depth buffer
1596 		if(r_showOcclusionQueries->integer)
1597 		{
1598 			GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
1599 		}
1600 		else
1601 		{
1602 			GL_State(GLS_COLORMASK_BITS | GLS_STENCILTEST_ENABLE);
1603 		}
1604 
1605 		oldLight = NULL;
1606 		calcSum = qtrue;
1607 
1608 		// loop trough all light interactions and render the light OBB for each last interaction
1609 		for(iaCount = 0, ia = &interactions[0]; iaCount < numInteractions;)
1610 		{
1611 			backEnd.currentLight = light = ia->dlight;
1612 
1613 			if(light != oldLight)
1614 			{
1615 				iaFirst = iaCount;
1616 			}
1617 
1618 			if(!calcSum)
1619 			{
1620 				ia->occlusionQuerySamples = sum;
1621 			}
1622 
1623 			if(!ia->next)
1624 			{
1625 				// last interaction of current light
1626 				if(calcSum)
1627 				{
1628 					if(R_CullLightPoint(light, backEnd.viewParms.or.origin) == CULL_OUT)
1629 					{
1630 						// clear stencil buffer
1631 						qglClear(GL_STENCIL_BUFFER_BIT);
1632 
1633 						// set the reference stencil value
1634 						//qglClearStencil(0U);
1635 						qglStencilMask(~0);
1636 						qglStencilFunc(GL_ALWAYS, 0, ~0);
1637 						qglStencilOp(GL_KEEP, GL_INCR, GL_INCR);
1638 
1639 						R_RotateForDlight(light, &backEnd.viewParms, &backEnd.or);
1640 						qglLoadMatrixf(backEnd.or.modelViewMatrix);
1641 
1642 						qglBegin(GL_QUADS);
1643 
1644 						qglVertex3f(light->localBounds[0][0], light->localBounds[0][1], light->localBounds[0][2]);
1645 						qglVertex3f(light->localBounds[0][0], light->localBounds[1][1], light->localBounds[0][2]);
1646 						qglVertex3f(light->localBounds[0][0], light->localBounds[1][1], light->localBounds[1][2]);
1647 						qglVertex3f(light->localBounds[0][0], light->localBounds[0][1], light->localBounds[1][2]);
1648 
1649 						qglVertex3f(light->localBounds[1][0], light->localBounds[0][1], light->localBounds[0][2]);
1650 						qglVertex3f(light->localBounds[1][0], light->localBounds[1][1], light->localBounds[0][2]);
1651 						qglVertex3f(light->localBounds[1][0], light->localBounds[1][1], light->localBounds[1][2]);
1652 						qglVertex3f(light->localBounds[1][0], light->localBounds[0][1], light->localBounds[1][2]);
1653 
1654 						qglVertex3f(light->localBounds[0][0], light->localBounds[0][1], light->localBounds[1][2]);
1655 						qglVertex3f(light->localBounds[0][0], light->localBounds[1][1], light->localBounds[1][2]);
1656 						qglVertex3f(light->localBounds[1][0], light->localBounds[1][1], light->localBounds[1][2]);
1657 						qglVertex3f(light->localBounds[1][0], light->localBounds[0][1], light->localBounds[1][2]);
1658 
1659 						qglVertex3f(light->localBounds[0][0], light->localBounds[0][1], light->localBounds[0][2]);
1660 						qglVertex3f(light->localBounds[0][0], light->localBounds[1][1], light->localBounds[0][2]);
1661 						qglVertex3f(light->localBounds[1][0], light->localBounds[1][1], light->localBounds[0][2]);
1662 						qglVertex3f(light->localBounds[1][0], light->localBounds[0][1], light->localBounds[0][2]);
1663 
1664 						qglVertex3f(light->localBounds[0][0], light->localBounds[0][1], light->localBounds[0][2]);
1665 						qglVertex3f(light->localBounds[0][0], light->localBounds[0][1], light->localBounds[1][2]);
1666 						qglVertex3f(light->localBounds[1][0], light->localBounds[0][1], light->localBounds[1][2]);
1667 						qglVertex3f(light->localBounds[1][0], light->localBounds[0][1], light->localBounds[0][2]);
1668 
1669 						qglVertex3f(light->localBounds[0][0], light->localBounds[1][1], light->localBounds[0][2]);
1670 						qglVertex3f(light->localBounds[0][0], light->localBounds[1][1], light->localBounds[1][2]);
1671 						qglVertex3f(light->localBounds[1][0], light->localBounds[1][1], light->localBounds[1][2]);
1672 						qglVertex3f(light->localBounds[1][0], light->localBounds[1][1], light->localBounds[0][2]);
1673 
1674 						qglEnd();
1675 
1676 						backEnd.pc.c_occlusionQueries++;
1677 						backEnd.pc.c_occlusionQueriesAvailable++;
1678 
1679 						#if 1
1680 						qglReadPixels(0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback);
1681 
1682 						for(i = 0, sum = 0; i < glConfig.vidWidth * glConfig.vidHeight; i++)
1683 						{
1684 							sum += stencilReadback[i];
1685 						}
1686 						#else
1687 						// only consider the 2D light scissor of current light
1688 						qglReadPixels(ia->scissorX, ia->scissorY, ia->scissorWidth, ia->scissorHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback);
1689 
1690 						for(i = 0, sum = 0; i < ia->scissorWidth * ia->scissorHeight; i++)
1691 						{
1692 							sum += stencilReadback[i];
1693 						}
1694 						#endif
1695 
1696 						if(!sum)
1697 						{
1698 							backEnd.pc.c_occlusionQueriesCulled++;
1699 						}
1700 					}
1701 					else
1702 					{
1703 						sum = 1;
1704 					}
1705 
1706 					// jump back to first interaction of this light copy sum to all interactions
1707 					ia = &interactions[iaFirst];
1708 					iaCount = iaFirst;
1709 					calcSum = qfalse;
1710 				}
1711 				else
1712 				{
1713 					if(iaCount < (numInteractions - 1))
1714 					{
1715 						// jump to next interaction and continue
1716 						ia++;
1717 						iaCount++;
1718 						calcSum = qtrue;
1719 					}
1720 					else
1721 					{
1722 						// increase last time to leave for loop
1723 						iaCount++;
1724 					}
1725 				}
1726 			}
1727 			else
1728 			{
1729 				// just continue
1730 				ia = ia->next;
1731 				iaCount++;
1732 			}
1733 
1734 			oldLight = light;
1735 		}
1736 
1737 		// go back to the world modelview matrix
1738 		backEnd.or = backEnd.viewParms.world;
1739 		qglLoadMatrixf(backEnd.viewParms.world.modelViewMatrix);
1740 
1741 		// reenable writes to depth and color buffers
1742 		GL_State(GLS_DEPTHMASK_TRUE);
1743 
1744 		ri.Hunk_FreeTempMemory(stencilReadback);
1745 	}
1746 #endif
1747 
1748 	GL_CheckErrors();
1749 }
1750 
RB_RenderDebugUtils(interaction_t * interactions,int numInteractions)1751 static void RB_RenderDebugUtils(interaction_t * interactions, int numInteractions)
1752 {
1753 	GLimp_LogComment("--- RB_RenderDebugUtils ---\n");
1754 
1755 	if(r_showLightTransforms->integer)
1756 	{
1757 		int             i;
1758 		trRefDlight_t  *dl;
1759 		vec3_t          forward, left, up;
1760 		vec3_t          tmp;
1761 
1762 		if(r_dynamicLighting->integer)
1763 		{
1764 			GL_Program(0);
1765 			GL_State(0);
1766 			GL_SelectTexture(0);
1767 			GL_Bind(tr.whiteImage);
1768 
1769 			dl = backEnd.refdef.dlights;
1770 			for(i = 0; i < backEnd.refdef.numDlights; i++, dl++)
1771 			{
1772 				// set up the transformation matrix
1773 				R_RotateForDlight(dl, &backEnd.viewParms, &backEnd.or);
1774 				qglLoadMatrixf(backEnd.or.modelViewMatrix);
1775 
1776 				MatrixToVectorsFLU(matrixIdentity, forward, left, up);
1777 				VectorMA(vec3_origin, 16, forward, forward);
1778 				VectorMA(vec3_origin, 16, left, left);
1779 				VectorMA(vec3_origin, 16, up, up);
1780 
1781 				// draw axis
1782 				//qglLineWidth(3);
1783 				qglBegin(GL_LINES);
1784 
1785 				qglColor4fv(colorRed);
1786 				qglVertex3fv(vec3_origin);
1787 				qglVertex3fv(forward);
1788 
1789 				qglColor4fv(colorGreen);
1790 				qglVertex3fv(vec3_origin);
1791 				qglVertex3fv(left);
1792 
1793 				qglColor4fv(colorBlue);
1794 				qglVertex3fv(vec3_origin);
1795 				qglVertex3fv(up);
1796 
1797 				qglColor4fv(colorYellow);
1798 				qglVertex3fv(vec3_origin);
1799 				VectorSubtract(dl->origin, backEnd.or.origin, tmp);
1800 				dl->transformed[0] = DotProduct(tmp, backEnd.or.axis[0]);
1801 				dl->transformed[1] = DotProduct(tmp, backEnd.or.axis[1]);
1802 				dl->transformed[2] = DotProduct(tmp, backEnd.or.axis[2]);
1803 				qglVertex3fv(dl->transformed);
1804 
1805 				qglColor4fv(colorMagenta);
1806 				qglVertex3fv(vec3_origin);
1807 				qglVertex3fv(dl->l.target);
1808 
1809 				qglColor4fv(colorCyan);
1810 				qglVertex3fv(vec3_origin);
1811 				qglVertex3fv(dl->l.right);
1812 
1813 				qglColor4fv(colorWhite);
1814 				qglVertex3fv(vec3_origin);
1815 				qglVertex3fv(dl->l.up);
1816 
1817 				qglColor4fv(colorMdGrey);
1818 				qglVertex3fv(vec3_origin);
1819 				VectorAdd(dl->l.target, dl->l.up, tmp);
1820 				qglVertex3fv(tmp);
1821 
1822 				qglEnd();
1823 				//qglLineWidth(1);
1824 
1825 				R_DebugBoundingBox(vec3_origin, dl->localBounds[0], dl->localBounds[1], colorRed);
1826 
1827 				// go back to the world modelview matrix
1828 				backEnd.or = backEnd.viewParms.world;
1829 				qglLoadMatrixf(backEnd.viewParms.world.modelViewMatrix);
1830 
1831 				R_DebugBoundingBox(vec3_origin, dl->worldBounds[0], dl->worldBounds[1], colorGreen);
1832 			}
1833 		}
1834 
1835 		if(!(backEnd.refdef.rdflags & RDF_NOWORLDMODEL))
1836 		{
1837 			GL_Program(0);
1838 			GL_State(0);
1839 			GL_SelectTexture(0);
1840 			GL_Bind(tr.whiteImage);
1841 
1842 			for(i = 0; i < tr.world->numDlights; i++)
1843 			{
1844 				dl = &tr.world->dlights[i];
1845 
1846 				// set up the transformation matrix
1847 				R_RotateForDlight(dl, &backEnd.viewParms, &backEnd.or);
1848 				qglLoadMatrixf(backEnd.or.modelViewMatrix);
1849 
1850 				MatrixToVectorsFLU(matrixIdentity, forward, left, up);
1851 				VectorMA(vec3_origin, 16, forward, forward);
1852 				VectorMA(vec3_origin, 16, left, left);
1853 				VectorMA(vec3_origin, 16, up, up);
1854 
1855 				// draw axis
1856 				//qglLineWidth(3);
1857 				qglBegin(GL_LINES);
1858 
1859 				qglColor4fv(colorRed);
1860 				qglVertex3fv(vec3_origin);
1861 				qglVertex3fv(forward);
1862 
1863 				qglColor4fv(colorGreen);
1864 				qglVertex3fv(vec3_origin);
1865 				qglVertex3fv(left);
1866 
1867 				qglColor4fv(colorBlue);
1868 				qglVertex3fv(vec3_origin);
1869 				qglVertex3fv(up);
1870 
1871 				qglColor4fv(colorYellow);
1872 				qglVertex3fv(vec3_origin);
1873 				VectorSubtract(dl->origin, backEnd.or.origin, tmp);
1874 				dl->transformed[0] = DotProduct(tmp, backEnd.or.axis[0]);
1875 				dl->transformed[1] = DotProduct(tmp, backEnd.or.axis[1]);
1876 				dl->transformed[2] = DotProduct(tmp, backEnd.or.axis[2]);
1877 				qglVertex3fv(dl->transformed);
1878 
1879 				qglColor4fv(colorMagenta);
1880 				qglVertex3fv(vec3_origin);
1881 				qglVertex3fv(dl->l.target);
1882 
1883 				qglColor4fv(colorCyan);
1884 				qglVertex3fv(vec3_origin);
1885 				qglVertex3fv(dl->l.right);
1886 
1887 				qglColor4fv(colorWhite);
1888 				qglVertex3fv(vec3_origin);
1889 				qglVertex3fv(dl->l.up);
1890 
1891 				qglColor4fv(colorMdGrey);
1892 				qglVertex3fv(vec3_origin);
1893 				VectorAdd(dl->l.target, dl->l.up, tmp);
1894 				qglVertex3fv(tmp);
1895 
1896 				qglEnd();
1897 				//qglLineWidth(1);
1898 
1899 				R_DebugBoundingBox(vec3_origin, dl->localBounds[0], dl->localBounds[1], colorBlue);
1900 
1901 				// go back to the world modelview matrix
1902 				backEnd.or = backEnd.viewParms.world;
1903 				qglLoadMatrixf(backEnd.viewParms.world.modelViewMatrix);
1904 
1905 				R_DebugBoundingBox(vec3_origin, dl->worldBounds[0], dl->worldBounds[1], colorYellow);
1906 			}
1907 		}
1908 	}
1909 
1910 	if(r_showLightInteractions->integer)
1911 	{
1912 		interaction_t  *ia;
1913 		int             iaCount;
1914 		trRefEntity_t  *entity;
1915 		surfaceType_t  *surface;
1916 
1917 		GL_Program(0);
1918 		GL_State(0);
1919 		GL_SelectTexture(0);
1920 		GL_Bind(tr.whiteImage);
1921 
1922 		for(iaCount = 0, ia = &interactions[0]; iaCount < numInteractions;)
1923 		{
1924 			backEnd.currentEntity = entity = ia->entity;
1925 			surface = ia->surface;
1926 
1927 			R_RotateForEntity(entity, &backEnd.viewParms, &backEnd.or);
1928 			qglLoadMatrixf(backEnd.or.modelViewMatrix);
1929 
1930 			if(*surface == SF_FACE)
1931 			{
1932 				srfSurfaceFace_t *face;
1933 
1934 				face = (srfSurfaceFace_t *) surface;
1935 				R_DebugBoundingBox(vec3_origin, face->bounds[0], face->bounds[1], colorYellow);
1936 			}
1937 			else if(*surface == SF_GRID)
1938 			{
1939 				srfGridMesh_t  *grid;
1940 
1941 				grid = (srfGridMesh_t *) surface;
1942 				R_DebugBoundingBox(vec3_origin, grid->meshBounds[0], grid->meshBounds[1], colorMagenta);
1943 			}
1944 			else if(*surface == SF_TRIANGLES)
1945 			{
1946 				srfTriangles_t *tri;
1947 
1948 				tri = (srfTriangles_t *) surface;
1949 				R_DebugBoundingBox(vec3_origin, tri->bounds[0], tri->bounds[1], colorCyan);
1950 			}
1951 			else if(*surface == SF_MDX)
1952 			{
1953 				R_DebugBoundingBox(vec3_origin, entity->localBounds[0], entity->localBounds[1], colorMdGrey);
1954 			}
1955 
1956 			if(!ia->next)
1957 			{
1958 				if(iaCount < (numInteractions - 1))
1959 				{
1960 					// jump to next interaction and continue
1961 					ia++;
1962 					iaCount++;
1963 				}
1964 				else
1965 				{
1966 					// increase last time to leave for loop
1967 					iaCount++;
1968 				}
1969 			}
1970 			else
1971 			{
1972 				// just continue
1973 				ia = ia->next;
1974 				iaCount++;
1975 			}
1976 		}
1977 
1978 		// go back to the world modelview matrix
1979 		backEnd.or = backEnd.viewParms.world;
1980 		qglLoadMatrixf(backEnd.viewParms.world.modelViewMatrix);
1981 	}
1982 
1983 	if(r_showEntityTransforms->integer)
1984 	{
1985 		trRefEntity_t  *ent;
1986 		int             i;
1987 
1988 		GL_Program(0);
1989 		GL_State(0);
1990 		GL_SelectTexture(0);
1991 		GL_Bind(tr.whiteImage);
1992 
1993 		ent = backEnd.refdef.entities;
1994 		for(i = 0; i < backEnd.refdef.numEntities; i++, ent++)
1995 		{
1996 			if((ent->e.renderfx & RF_THIRD_PERSON) && !backEnd.viewParms.isPortal)
1997 				continue;
1998 
1999 			// set up the transformation matrix
2000 			R_RotateForEntity(ent, &backEnd.viewParms, &backEnd.or);
2001 			qglLoadMatrixf(backEnd.or.modelViewMatrix);
2002 
2003 			R_DebugAxis(vec3_origin, matrixIdentity);
2004 			R_DebugBoundingBox(vec3_origin, ent->localBounds[0], ent->localBounds[1], colorMagenta);
2005 
2006 			// go back to the world modelview matrix
2007 			backEnd.or = backEnd.viewParms.world;
2008 			qglLoadMatrixf(backEnd.viewParms.world.modelViewMatrix);
2009 
2010 			R_DebugBoundingBox(vec3_origin, ent->worldBounds[0], ent->worldBounds[1], colorCyan);
2011 		}
2012 	}
2013 
2014 	if(r_showLightScissors->integer)
2015 	{
2016 		interaction_t  *ia;
2017 		int             iaCount;
2018 
2019 		GL_Program(0);
2020 		GL_SelectTexture(0);
2021 		GL_Bind(tr.whiteImage);
2022 		GL_State(GLS_POLYMODE_LINE | GLS_DEPTHTEST_DISABLE);
2023 		GL_Cull(CT_TWO_SIDED);
2024 
2025 		// set 2D virtual screen size
2026 		qglPushMatrix();
2027 		qglLoadIdentity();
2028 		qglMatrixMode(GL_PROJECTION);
2029 		qglPushMatrix();
2030 		qglLoadIdentity();
2031 		qglOrtho(backEnd.viewParms.viewportX,
2032 				 backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
2033 				 backEnd.viewParms.viewportY,
2034 				 backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight, -99999, 99999);
2035 
2036 		for(iaCount = 0, ia = &interactions[0]; iaCount < numInteractions;)
2037 		{
2038 			if(qglDepthBoundsEXT)
2039 			{
2040 				if(ia->noDepthBoundsTest)
2041 				{
2042 					qglColor4fv(colorRed);
2043 				}
2044 				else
2045 				{
2046 					qglColor4fv(colorGreen);
2047 				}
2048 
2049 				qglBegin(GL_QUADS);
2050 				qglVertex2f(ia->scissorX, ia->scissorY);
2051 				qglVertex2f(ia->scissorX + ia->scissorWidth - 1, ia->scissorY);
2052 				qglVertex2f(ia->scissorX + ia->scissorWidth - 1, ia->scissorY + ia->scissorHeight - 1);
2053 				qglVertex2f(ia->scissorX, ia->scissorY + ia->scissorHeight - 1);
2054 				qglEnd();
2055 			}
2056 			else
2057 			{
2058 				qglBegin(GL_QUADS);
2059 				qglColor4fv(colorRed);
2060 				qglVertex2f(ia->scissorX, ia->scissorY);
2061 				qglColor4fv(colorGreen);
2062 				qglVertex2f(ia->scissorX + ia->scissorWidth - 1, ia->scissorY);
2063 				qglColor4fv(colorBlue);
2064 				qglVertex2f(ia->scissorX + ia->scissorWidth - 1, ia->scissorY + ia->scissorHeight - 1);
2065 				qglColor4fv(colorWhite);
2066 				qglVertex2f(ia->scissorX, ia->scissorY + ia->scissorHeight - 1);
2067 				qglEnd();
2068 			}
2069 
2070 			if(!ia->next)
2071 			{
2072 				if(iaCount < (numInteractions - 1))
2073 				{
2074 					// jump to next interaction and continue
2075 					ia++;
2076 					iaCount++;
2077 				}
2078 				else
2079 				{
2080 					// increase last time to leave for loop
2081 					iaCount++;
2082 				}
2083 			}
2084 			else
2085 			{
2086 				// just continue
2087 				ia = ia->next;
2088 				iaCount++;
2089 			}
2090 		}
2091 
2092 		qglPopMatrix();
2093 		qglMatrixMode(GL_MODELVIEW);
2094 		qglPopMatrix();
2095 	}
2096 
2097 	GL_CheckErrors();
2098 }
2099 
RB_RenderBloom(void)2100 static void RB_RenderBloom(void)
2101 {
2102 	GLimp_LogComment("--- RB_RenderBloom ---\n");
2103 
2104 	if((backEnd.refdef.rdflags & RDF_NOWORLDMODEL) || !r_drawBloom->integer)
2105 		return;
2106 
2107 	// set 2D virtual screen size
2108 	qglPushMatrix();
2109 	qglLoadIdentity();
2110 	qglMatrixMode(GL_PROJECTION);
2111 	qglPushMatrix();
2112 	qglLoadIdentity();
2113 	qglOrtho(backEnd.viewParms.viewportX,
2114 		backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
2115 		backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight, -99999, 99999);
2116 
2117 	if(r_drawBloom->integer == 1)
2118 	{
2119 		GL_State(GLS_DEPTHTEST_DISABLE);
2120 		GL_Cull(CT_TWO_SIDED);
2121 
2122 		// render contrast
2123 		GL_Program(tr.contrastShader.program);
2124 		GL_ClientState(tr.contrastShader.attribs);
2125 		GL_SetVertexAttribs();
2126 
2127 		GL_SelectTexture(0);
2128 		GL_Bind(tr.currentRenderImage);
2129 		qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, tr.currentRenderImage->uploadWidth, tr.currentRenderImage->uploadHeight);
2130 
2131 		// draw viewport
2132 		qglBegin(GL_QUADS);
2133 		qglVertex2f(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY);
2134 		qglVertex2f(backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportY);
2135 		qglVertex2f(backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
2136 			backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight);
2137 		qglVertex2f(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight);
2138 		qglEnd();
2139 
2140 		// render bloom
2141 		GL_Program(tr.bloomShader.program);
2142 		GL_ClientState(tr.bloomShader.attribs);
2143 		GL_SetVertexAttribs();
2144 
2145 		qglUniform1fARB(tr.bloomShader.u_BlurMagnitude, r_bloomBlur->value);
2146 
2147 		GL_SelectTexture(1);
2148 		GL_Bind(tr.currentRenderNearestImage);
2149 		qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, tr.currentRenderNearestImage->uploadWidth, tr.currentRenderNearestImage->uploadHeight);
2150 
2151 		// draw viewport
2152 		qglBegin(GL_QUADS);
2153 		qglVertex2f(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY);
2154 		qglVertex2f(backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportY);
2155 		qglVertex2f(backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
2156 			backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight);
2157 		qglVertex2f(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight);
2158 		qglEnd();
2159 	}
2160 	else if(r_drawBloom->integer == 2)
2161 	{
2162 		GL_State(GLS_DEPTHTEST_DISABLE);
2163 		GL_Cull(CT_TWO_SIDED);
2164 
2165 		// render contrast
2166 		GL_Program(tr.contrastShader.program);
2167 		GL_ClientState(tr.contrastShader.attribs);
2168 		GL_SetVertexAttribs();
2169 
2170 		GL_SelectTexture(0);
2171 		GL_Bind(tr.currentRenderImage);
2172 		qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, tr.currentRenderImage->uploadWidth, tr.currentRenderImage->uploadHeight);
2173 
2174 		// draw viewport
2175 		qglBegin(GL_QUADS);
2176 		qglVertex2f(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY);
2177 		qglVertex2f(backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportY);
2178 		qglVertex2f(backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
2179 			backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight);
2180 		qglVertex2f(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight);
2181 		qglEnd();
2182 
2183 		// render blurX
2184 		GL_Program(tr.blurXShader.program);
2185 		GL_ClientState(tr.blurXShader.attribs);
2186 		GL_SetVertexAttribs();
2187 
2188 		qglUniform1fARB(tr.blurXShader.u_BlurMagnitude, r_bloomBlur->value);
2189 
2190 		GL_Bind(tr.currentRenderNearestImage);
2191 		qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, tr.currentRenderNearestImage->uploadWidth, tr.currentRenderNearestImage->uploadHeight);
2192 
2193 		// draw viewport
2194 		qglBegin(GL_QUADS);
2195 		qglVertex2f(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY);
2196 		qglVertex2f(backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportY);
2197 		qglVertex2f(backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
2198 			backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight);
2199 		qglVertex2f(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight);
2200 		qglEnd();
2201 
2202 		// render blurY
2203 		GL_Program(tr.blurYShader.program);
2204 		GL_ClientState(tr.blurYShader.attribs);
2205 		GL_SetVertexAttribs();
2206 
2207 		qglUniform1fARB(tr.blurYShader.u_BlurMagnitude, r_bloomBlur->value);
2208 
2209 		GL_Bind(tr.currentRenderNearestImage);
2210 		qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, tr.currentRenderNearestImage->uploadWidth, tr.currentRenderNearestImage->uploadHeight);
2211 
2212 		// draw viewport
2213 		qglBegin(GL_QUADS);
2214 		qglVertex2f(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY);
2215 		qglVertex2f(backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportY);
2216 		qglVertex2f(backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
2217 			backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight);
2218 		qglVertex2f(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight);
2219 		qglEnd();
2220 
2221 		// render bloom
2222 		GL_Program(tr.bloomShader.program);
2223 		GL_ClientState(tr.bloomShader.attribs);
2224 		GL_SetVertexAttribs();
2225 
2226 		qglUniform1fARB(tr.bloomShader.u_BlurMagnitude, r_bloomBlur->value);
2227 
2228 		GL_SelectTexture(0);
2229 		GL_Bind(tr.currentRenderImage);
2230 
2231 		GL_SelectTexture(1);
2232 		GL_Bind(tr.currentRenderNearestImage);
2233 
2234 		// draw viewport
2235 		qglBegin(GL_QUADS);
2236 		qglVertex2f(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY);
2237 		qglVertex2f(backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportY);
2238 		qglVertex2f(backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
2239 			backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight);
2240 		qglVertex2f(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight);
2241 		qglEnd();
2242 	}
2243 
2244 	// go back to 3D
2245 	qglMatrixMode(GL_PROJECTION);
2246 	qglPopMatrix();
2247 	qglMatrixMode(GL_MODELVIEW);
2248 	qglPopMatrix();
2249 }
2250 
2251 /*
2252 ==================
2253 RB_RenderDrawSurfList
2254 ==================
2255 */
RB_RenderDrawSurfList(drawSurf_t * drawSurfs,int numDrawSurfs,interaction_t * interactions,int numInteractions)2256 static void RB_RenderDrawSurfList(drawSurf_t * drawSurfs, int numDrawSurfs, interaction_t * interactions, int numInteractions)
2257 {
2258 	float           originalTime;
2259 
2260 	if(r_logFile->integer)
2261 	{
2262 		// don't just call LogComment, or we will get a call to va() every frame!
2263 		GLimp_LogComment(va("--- RB_RenderDrawSurfList( %i surfaces, %i interactions ) ---\n", numDrawSurfs, numInteractions));
2264 	}
2265 
2266 	GL_CheckErrors();
2267 
2268 	// save original time for entity shader offsets
2269 	originalTime = backEnd.refdef.floatTime;
2270 
2271 	// clear the z buffer, set the modelview, etc
2272 	RB_BeginDrawingView();
2273 
2274 	backEnd.pc.c_surfaces += numDrawSurfs;
2275 
2276 	// draw everything that is opaque
2277 	RB_RenderDrawSurfaces(originalTime, drawSurfs, numDrawSurfs, qtrue);
2278 
2279 	// try to cull lights using occlusion queries
2280 	RB_RenderOcclusionQueries(interactions, numInteractions);
2281 
2282 	if(r_shadows->integer == 3)
2283 	{
2284 		// render dynamic shadowing and lighting using stencil shadow volumes
2285 		RB_RenderInteractionsStencilShadowed(originalTime, interactions, numInteractions);
2286 	}
2287 	else
2288 	{
2289 		// render dynamic lighting
2290 		RB_RenderInteractions(originalTime, interactions, numInteractions);
2291 	}
2292 
2293 	// draw everything that is translucent
2294 	RB_RenderDrawSurfaces(originalTime, drawSurfs, numDrawSurfs, qfalse);
2295 
2296 	// add the sun flare
2297 	RB_DrawSun();
2298 
2299 	// add light flares on lights that aren't obscured
2300 	RB_RenderFlares();
2301 
2302 	// render bloom post process effect
2303 	RB_RenderBloom();
2304 
2305 	// render debug information
2306 	RB_RenderDebugUtils(interactions, numInteractions);
2307 }
2308 
2309 
2310 /*
2311 ============================================================================
2312 
2313 RENDER BACK END THREAD FUNCTIONS
2314 
2315 ============================================================================
2316 */
2317 
2318 
2319 /*
2320 =============
2321 RE_StretchRaw
2322 
2323 FIXME: not exactly backend
2324 Stretches a raw 32 bit power of 2 bitmap image over the given screen rectangle.
2325 Used for cinematics.
2326 =============
2327 */
RE_StretchRaw(int x,int y,int w,int h,int cols,int rows,const byte * data,int client,qboolean dirty)2328 void RE_StretchRaw(int x, int y, int w, int h, int cols, int rows, const byte * data, int client, qboolean dirty)
2329 {
2330 	int             i, j;
2331 	int             start, end;
2332 
2333 	if(!tr.registered)
2334 	{
2335 		return;
2336 	}
2337 	R_SyncRenderThread();
2338 
2339 	// we definately want to sync every frame for the cinematics
2340 	qglFinish();
2341 
2342 	start = end = 0;
2343 	if(r_speeds->integer)
2344 	{
2345 		start = ri.Milliseconds();
2346 	}
2347 
2348 	// make sure rows and cols are powers of 2
2349 	for(i = 0; (1 << i) < cols; i++)
2350 	{
2351 	}
2352 	for(j = 0; (1 << j) < rows; j++)
2353 	{
2354 	}
2355 	if((1 << i) != cols || (1 << j) != rows)
2356 	{
2357 		ri.Error(ERR_DROP, "Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows);
2358 	}
2359 
2360 	GL_SelectTexture(0);
2361 	GL_Bind(tr.scratchImage[client]);
2362 
2363 	// if the scratchImage isn't in the format we want, specify it as a new texture
2364 	if(cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height)
2365 	{
2366 		tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
2367 		tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
2368 		qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
2369 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2370 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2371 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
2372 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
2373 	}
2374 	else
2375 	{
2376 		if(dirty)
2377 		{
2378 			// otherwise, just subimage upload it so that drivers can tell we are going to be changing
2379 			// it and don't try and do a texture compression
2380 			qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data);
2381 		}
2382 	}
2383 
2384 	if(r_speeds->integer)
2385 	{
2386 		end = ri.Milliseconds();
2387 		ri.Printf(PRINT_ALL, "qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start);
2388 	}
2389 
2390 	RB_SetGL2D();
2391 
2392 	qglColor3f(tr.identityLight, tr.identityLight, tr.identityLight);
2393 
2394 	qglBegin(GL_QUADS);
2395 	qglTexCoord2f(0.5f / cols, 0.5f / rows);
2396 	qglVertex2f(x, y);
2397 	qglTexCoord2f((cols - 0.5f) / cols, 0.5f / rows);
2398 	qglVertex2f(x + w, y);
2399 	qglTexCoord2f((cols - 0.5f) / cols, (rows - 0.5f) / rows);
2400 	qglVertex2f(x + w, y + h);
2401 	qglTexCoord2f(0.5f / cols, (rows - 0.5f) / rows);
2402 	qglVertex2f(x, y + h);
2403 	qglEnd();
2404 }
2405 
RE_UploadCinematic(int w,int h,int cols,int rows,const byte * data,int client,qboolean dirty)2406 void RE_UploadCinematic(int w, int h, int cols, int rows, const byte * data, int client, qboolean dirty)
2407 {
2408 	GL_Bind(tr.scratchImage[client]);
2409 
2410 	// if the scratchImage isn't in the format we want, specify it as a new texture
2411 	if(cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height)
2412 	{
2413 		tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
2414 		tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
2415 		qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
2416 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2417 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2418 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
2419 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
2420 	}
2421 	else
2422 	{
2423 		if(dirty)
2424 		{
2425 			// otherwise, just subimage upload it so that drivers can tell we are going to be changing
2426 			// it and don't try and do a texture compression
2427 			qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data);
2428 		}
2429 	}
2430 }
2431 
2432 
2433 /*
2434 =============
2435 RB_SetColor
2436 =============
2437 */
RB_SetColor(const void * data)2438 const void     *RB_SetColor(const void *data)
2439 {
2440 	const setColorCommand_t *cmd;
2441 
2442 	GLimp_LogComment("--- RB_SetColor ---\n");
2443 
2444 	cmd = (const setColorCommand_t *)data;
2445 
2446 	backEnd.color2D[0] = cmd->color[0] * 255;
2447 	backEnd.color2D[1] = cmd->color[1] * 255;
2448 	backEnd.color2D[2] = cmd->color[2] * 255;
2449 	backEnd.color2D[3] = cmd->color[3] * 255;
2450 
2451 	return (const void *)(cmd + 1);
2452 }
2453 
2454 /*
2455 =============
2456 RB_StretchPic
2457 =============
2458 */
RB_StretchPic(const void * data)2459 const void     *RB_StretchPic(const void *data)
2460 {
2461 	const stretchPicCommand_t *cmd;
2462 	shader_t       *shader;
2463 	int             numVerts, numIndexes;
2464 
2465 	GLimp_LogComment("--- RB_StretchPic ---\n");
2466 
2467 	cmd = (const stretchPicCommand_t *)data;
2468 
2469 	if(!backEnd.projection2D)
2470 	{
2471 		RB_SetGL2D();
2472 	}
2473 
2474 	shader = cmd->shader;
2475 	if(shader != tess.surfaceShader)
2476 	{
2477 		if(tess.numIndexes)
2478 		{
2479 			Tess_End();
2480 		}
2481 		backEnd.currentEntity = &backEnd.entity2D;
2482 		Tess_Begin(shader, NULL, -1, 0, qfalse, qfalse);
2483 	}
2484 
2485 	Tess_CheckOverflow(4, 6);
2486 	numVerts = tess.numVertexes;
2487 	numIndexes = tess.numIndexes;
2488 
2489 	tess.numVertexes += 4;
2490 	tess.numIndexes += 6;
2491 
2492 	tess.indexes[numIndexes] = numVerts + 3;
2493 	tess.indexes[numIndexes + 1] = numVerts + 0;
2494 	tess.indexes[numIndexes + 2] = numVerts + 2;
2495 	tess.indexes[numIndexes + 3] = numVerts + 2;
2496 	tess.indexes[numIndexes + 4] = numVerts + 0;
2497 	tess.indexes[numIndexes + 5] = numVerts + 1;
2498 
2499 	*(int *)tess.colors[numVerts] =
2500 		*(int *)tess.colors[numVerts + 1] =
2501 		*(int *)tess.colors[numVerts + 2] = *(int *)tess.colors[numVerts + 3] = *(int *)backEnd.color2D;
2502 
2503 	tess.xyz[numVerts][0] = cmd->x;
2504 	tess.xyz[numVerts][1] = cmd->y;
2505 	tess.xyz[numVerts][2] = 0;
2506 	tess.xyz[numVerts][3] = 1;
2507 
2508 	tess.texCoords[numVerts][0][0] = cmd->s1;
2509 	tess.texCoords[numVerts][0][1] = cmd->t1;
2510 
2511 	tess.xyz[numVerts + 1][0] = cmd->x + cmd->w;
2512 	tess.xyz[numVerts + 1][1] = cmd->y;
2513 	tess.xyz[numVerts + 1][2] = 0;
2514 	tess.xyz[numVerts + 1][3] = 1;
2515 
2516 	tess.texCoords[numVerts + 1][0][0] = cmd->s2;
2517 	tess.texCoords[numVerts + 1][0][1] = cmd->t1;
2518 
2519 	tess.xyz[numVerts + 2][0] = cmd->x + cmd->w;
2520 	tess.xyz[numVerts + 2][1] = cmd->y + cmd->h;
2521 	tess.xyz[numVerts + 2][2] = 0;
2522 	tess.xyz[numVerts + 2][3] = 1;
2523 
2524 	tess.texCoords[numVerts + 2][0][0] = cmd->s2;
2525 	tess.texCoords[numVerts + 2][0][1] = cmd->t2;
2526 
2527 	tess.xyz[numVerts + 3][0] = cmd->x;
2528 	tess.xyz[numVerts + 3][1] = cmd->y + cmd->h;
2529 	tess.xyz[numVerts + 3][2] = 0;
2530 	tess.xyz[numVerts + 3][3] = 1;
2531 
2532 	tess.texCoords[numVerts + 3][0][0] = cmd->s1;
2533 	tess.texCoords[numVerts + 3][0][1] = cmd->t2;
2534 
2535 	return (const void *)(cmd + 1);
2536 }
2537 
2538 
2539 /*
2540 =============
2541 RB_DrawSurfs
2542 =============
2543 */
RB_DrawSurfs(const void * data)2544 const void     *RB_DrawSurfs(const void *data)
2545 {
2546 	const drawSurfsCommand_t *cmd;
2547 
2548 	GLimp_LogComment("--- RB_DrawSurfs ---\n");
2549 
2550 	// finish any 2D drawing if needed
2551 	if(tess.numIndexes)
2552 	{
2553 		Tess_End();
2554 	}
2555 
2556 	cmd = (const drawSurfsCommand_t *)data;
2557 
2558 	backEnd.refdef = cmd->refdef;
2559 	backEnd.viewParms = cmd->viewParms;
2560 
2561 	RB_RenderDrawSurfList(cmd->drawSurfs, cmd->numDrawSurfs, cmd->interactions, cmd->numInteractions);
2562 
2563 	return (const void *)(cmd + 1);
2564 }
2565 
2566 
2567 /*
2568 =============
2569 RB_DrawBuffer
2570 =============
2571 */
RB_DrawBuffer(const void * data)2572 const void     *RB_DrawBuffer(const void *data)
2573 {
2574 	const drawBufferCommand_t *cmd;
2575 
2576 	GLimp_LogComment("--- RB_DrawBuffer ---\n");
2577 
2578 	cmd = (const drawBufferCommand_t *)data;
2579 
2580 	qglDrawBuffer(cmd->buffer);
2581 
2582 	// clear screen for debugging
2583 	if(r_clear->integer)
2584 	{
2585 //      qglClearColor(1, 0, 0.5, 1);
2586 		qglClearColor(0, 0, 0, 1);
2587 		qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2588 	}
2589 
2590 	return (const void *)(cmd + 1);
2591 }
2592 
2593 /*
2594 ===============
2595 RB_ShowImages
2596 
2597 Draw all the images to the screen, on top of whatever
2598 was there.  This is used to test for texture thrashing.
2599 
2600 Also called by RE_EndRegistration
2601 ===============
2602 */
RB_ShowImages(void)2603 void RB_ShowImages(void)
2604 {
2605 	int             i;
2606 	image_t        *image;
2607 	float           x, y, w, h;
2608 	int             start, end;
2609 
2610 	GLimp_LogComment("--- RB_ShowImages ---\n");
2611 
2612 	if(!backEnd.projection2D)
2613 	{
2614 		RB_SetGL2D();
2615 	}
2616 
2617 	qglClear(GL_COLOR_BUFFER_BIT);
2618 
2619 	qglFinish();
2620 
2621 	GL_SelectTexture(0);
2622 
2623 	start = ri.Milliseconds();
2624 
2625 	for(i = 0; i < tr.numImages; i++)
2626 	{
2627 		image = tr.images[i];
2628 
2629 		w = glConfig.vidWidth / 20;
2630 		h = glConfig.vidHeight / 15;
2631 		x = i % 20 * w;
2632 		y = i / 20 * h;
2633 
2634 		// show in proportional size in mode 2
2635 		if(r_showImages->integer == 2)
2636 		{
2637 			w *= image->uploadWidth / 512.0f;
2638 			h *= image->uploadHeight / 512.0f;
2639 		}
2640 
2641 		GL_Bind(image);
2642 		qglBegin(GL_QUADS);
2643 		qglTexCoord2f(0, 0);
2644 		qglVertex2f(x, y);
2645 		qglTexCoord2f(1, 0);
2646 		qglVertex2f(x + w, y);
2647 		qglTexCoord2f(1, 1);
2648 		qglVertex2f(x + w, y + h);
2649 		qglTexCoord2f(0, 1);
2650 		qglVertex2f(x, y + h);
2651 		qglEnd();
2652 	}
2653 
2654 	qglFinish();
2655 
2656 	end = ri.Milliseconds();
2657 	ri.Printf(PRINT_ALL, "%i msec to draw all images\n", end - start);
2658 }
2659 
2660 
2661 /*
2662 =============
2663 RB_SwapBuffers
2664 =============
2665 */
RB_SwapBuffers(const void * data)2666 const void     *RB_SwapBuffers(const void *data)
2667 {
2668 	const swapBuffersCommand_t *cmd;
2669 
2670 	// finish any 2D drawing if needed
2671 	if(tess.numIndexes)
2672 	{
2673 		Tess_End();
2674 	}
2675 
2676 	// texture swapping test
2677 	if(r_showImages->integer)
2678 	{
2679 		RB_ShowImages();
2680 	}
2681 
2682 	cmd = (const swapBuffersCommand_t *)data;
2683 
2684 	// we measure overdraw by reading back the stencil buffer and
2685 	// counting up the number of increments that have happened
2686 	if(r_measureOverdraw->integer)
2687 	{
2688 		int             i;
2689 		long            sum = 0;
2690 		unsigned char  *stencilReadback;
2691 
2692 		stencilReadback = ri.Hunk_AllocateTempMemory(glConfig.vidWidth * glConfig.vidHeight);
2693 		qglReadPixels(0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback);
2694 
2695 		for(i = 0; i < glConfig.vidWidth * glConfig.vidHeight; i++)
2696 		{
2697 			sum += stencilReadback[i];
2698 		}
2699 
2700 		backEnd.pc.c_overDraw += sum;
2701 		ri.Hunk_FreeTempMemory(stencilReadback);
2702 	}
2703 
2704 
2705 	if(!glState.finishCalled)
2706 	{
2707 		qglFinish();
2708 	}
2709 
2710 	GLimp_LogComment("***************** RB_SwapBuffers *****************\n\n\n");
2711 
2712 	GLimp_EndFrame();
2713 
2714 	backEnd.projection2D = qfalse;
2715 
2716 	return (const void *)(cmd + 1);
2717 }
2718 
2719 /*
2720 ====================
2721 RB_ExecuteRenderCommands
2722 
2723 This function will be called synchronously if running without
2724 smp extensions, or asynchronously by another thread.
2725 ====================
2726 */
RB_ExecuteRenderCommands(const void * data)2727 void RB_ExecuteRenderCommands(const void *data)
2728 {
2729 	int             t1, t2;
2730 
2731 	GLimp_LogComment("--- RB_ExecuteRenderCommands ---\n");
2732 
2733 	t1 = ri.Milliseconds();
2734 
2735 	if(!r_smp->integer || data == backEndData[0]->commands.cmds)
2736 	{
2737 		backEnd.smpFrame = 0;
2738 	}
2739 	else
2740 	{
2741 		backEnd.smpFrame = 1;
2742 	}
2743 
2744 	while(1)
2745 	{
2746 		switch (*(const int *)data)
2747 		{
2748 			case RC_SET_COLOR:
2749 				data = RB_SetColor(data);
2750 				break;
2751 			case RC_STRETCH_PIC:
2752 				data = RB_StretchPic(data);
2753 				break;
2754 			case RC_DRAW_SURFS:
2755 				data = RB_DrawSurfs(data);
2756 				break;
2757 			case RC_DRAW_BUFFER:
2758 				data = RB_DrawBuffer(data);
2759 				break;
2760 			case RC_SWAP_BUFFERS:
2761 				data = RB_SwapBuffers(data);
2762 				break;
2763 			case RC_SCREENSHOT:
2764 				data = RB_TakeScreenshotCmd(data);
2765 				break;
2766 
2767 			case RC_END_OF_LIST:
2768 			default:
2769 				// stop rendering on this thread
2770 				t2 = ri.Milliseconds();
2771 				backEnd.pc.msec = t2 - t1;
2772 				return;
2773 		}
2774 	}
2775 }
2776 
2777 
2778 /*
2779 ================
2780 RB_RenderThread
2781 ================
2782 */
RB_RenderThread(void)2783 void RB_RenderThread(void)
2784 {
2785 	const void     *data;
2786 
2787 	// wait for either a rendering command or a quit command
2788 	while(1)
2789 	{
2790 		// sleep until we have work to do
2791 		data = GLimp_RendererSleep();
2792 
2793 		if(!data)
2794 		{
2795 			return;				// all done, renderer is shutting down
2796 		}
2797 
2798 		renderThreadActive = qtrue;
2799 
2800 		RB_ExecuteRenderCommands(data);
2801 
2802 		renderThreadActive = qfalse;
2803 	}
2804 }
2805