1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 */
20 // r_main.c
21 #include "gl_local.h"
22 
23 void R_Clear (void);
24 
25 viddef_t	vid;
26 
27 refimport_t	ri;
28 
29 int QGL_TEXTURE0, QGL_TEXTURE1;
30 
31 model_t		*r_worldmodel;
32 
33 float		gldepthmin, gldepthmax;
34 
35 glconfig_t gl_config;
36 glstate_t  gl_state;
37 
38 image_t		*r_notexture;		// use for bad textures
39 image_t		*r_particletexture;	// little dot for particles
40 
41 entity_t	*currententity;
42 model_t		*currentmodel;
43 
44 cplane_t	frustum[4];
45 
46 int			r_visframecount;	// bumped when going to a new PVS
47 int			r_framecount;		// used for dlight push checking
48 
49 int			c_brush_polys, c_alias_polys;
50 
51 float		v_blend[4];			// final blending color
52 
53 void GL_Strings_f( void );
54 
55 //
56 // view origin
57 //
58 vec3_t	vup;
59 vec3_t	vpn;
60 vec3_t	vright;
61 vec3_t	r_origin;
62 
63 float	r_world_matrix[16];
64 float	r_base_world_matrix[16];
65 
66 //
67 // screen size info
68 //
69 refdef_t	r_newrefdef;
70 
71 int		r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2;
72 
73 cvar_t	*r_norefresh;
74 cvar_t	*r_drawentities;
75 cvar_t	*r_drawworld;
76 cvar_t	*r_speeds;
77 cvar_t	*r_fullbright;
78 cvar_t	*r_novis;
79 cvar_t	*r_nocull;
80 cvar_t	*r_lerpmodels;
81 cvar_t	*r_lefthand;
82 
83 cvar_t	*r_lightlevel;	// FIXME: This is a HACK to get the client's light level
84 
85 cvar_t	*gl_nosubimage;
86 cvar_t	*gl_allow_software;
87 
88 cvar_t	*gl_vertex_arrays;
89 
90 cvar_t	*gl_particle_min_size;
91 cvar_t	*gl_particle_max_size;
92 cvar_t	*gl_particle_size;
93 cvar_t	*gl_particle_att_a;
94 cvar_t	*gl_particle_att_b;
95 cvar_t	*gl_particle_att_c;
96 
97 cvar_t	*gl_ext_swapinterval;
98 cvar_t	*gl_ext_palettedtexture;
99 cvar_t	*gl_ext_multitexture;
100 cvar_t	*gl_ext_pointparameters;
101 cvar_t	*gl_ext_compiled_vertex_array;
102 
103 cvar_t	*gl_log;
104 cvar_t	*gl_bitdepth;
105 cvar_t	*gl_drawbuffer;
106 cvar_t  *gl_driver;
107 cvar_t	*gl_lightmap;
108 cvar_t	*gl_shadows;
109 cvar_t * gl_stencilshadow;
110 cvar_t	*gl_mode;
111 cvar_t	*gl_dynamic;
112 cvar_t  *gl_monolightmap;
113 cvar_t	*gl_modulate;
114 cvar_t	*gl_nobind;
115 cvar_t	*gl_round_down;
116 cvar_t	*gl_picmip;
117 cvar_t	*gl_skymip;
118 cvar_t	*gl_showtris;
119 cvar_t	*gl_ztrick;
120 cvar_t	*gl_finish;
121 cvar_t	*gl_clear;
122 cvar_t	*gl_cull;
123 cvar_t	*gl_polyblend;
124 cvar_t	*gl_flashblend;
125 cvar_t	*gl_playermip;
126 cvar_t  *gl_saturatelighting;
127 cvar_t	*gl_swapinterval;
128 cvar_t	*gl_texturemode;
129 cvar_t	*gl_texturealphamode;
130 cvar_t	*gl_texturesolidmode;
131 cvar_t	*gl_lockpvs;
132 
133 cvar_t	*gl_3dlabs_broken;
134 
135 cvar_t	*vid_fullscreen;
136 cvar_t	*vid_gamma;
137 cvar_t	*vid_ref;
138 
139 /*
140 =================
141 R_CullBox
142 
143 Returns true if the box is completely outside the frustom
144 =================
145 */
R_CullBox(vec3_t mins,vec3_t maxs)146 qboolean R_CullBox (vec3_t mins, vec3_t maxs)
147 {
148 	int		i;
149 
150 	if (r_nocull->value)
151 		return false;
152 
153 	for (i=0 ; i<4 ; i++)
154 		if ( BOX_ON_PLANE_SIDE(mins, maxs, &frustum[i]) == 2)
155 			return true;
156 	return false;
157 }
158 
159 
R_RotateForEntity(entity_t * e)160 void R_RotateForEntity (entity_t *e)
161 {
162     qglTranslatef (e->origin[0],  e->origin[1],  e->origin[2]);
163 
164     qglRotatef (e->angles[1],  0, 0, 1);
165     qglRotatef (-e->angles[0],  0, 1, 0);
166     qglRotatef (-e->angles[2],  1, 0, 0);
167 }
168 
169 /*
170 =============================================================
171 
172   SPRITE MODELS
173 
174 =============================================================
175 */
176 
177 
178 /*
179 =================
180 R_DrawSpriteModel
181 
182 =================
183 */
R_DrawSpriteModel(entity_t * e)184 void R_DrawSpriteModel (entity_t *e)
185 {
186 	float alpha = 1.0F;
187 	vec3_t	point;
188 	dsprframe_t	*frame;
189 	float		*up, *right;
190 	dsprite_t		*psprite;
191 
192 	// don't even bother culling, because it's just a single
193 	// polygon without a surface cache
194 
195 	psprite = (dsprite_t *)currentmodel->extradata;
196 
197 #if 0
198 	if (e->frame < 0 || e->frame >= psprite->numframes)
199 	{
200 		ri.Con_Printf (PRINT_ALL, "no such sprite frame %i\n", e->frame);
201 		e->frame = 0;
202 	}
203 #endif
204 	e->frame %= psprite->numframes;
205 
206 	frame = &psprite->frames[e->frame];
207 
208 #if 0
209 	if (psprite->type == SPR_ORIENTED)
210 	{	// bullet marks on walls
211 	vec3_t		v_forward, v_right, v_up;
212 
213 	AngleVectors (currententity->angles, v_forward, v_right, v_up);
214 		up = v_up;
215 		right = v_right;
216 	}
217 	else
218 #endif
219 	{	// normal sprite
220 		up = vup;
221 		right = vright;
222 	}
223 
224 	if ( e->flags & RF_TRANSLUCENT )
225 		alpha = e->alpha;
226 
227 	if ( alpha != 1.0F )
228 		qglEnable( GL_BLEND );
229 
230 	qglColor4f( 1, 1, 1, alpha );
231 
232     GL_Bind(currentmodel->skins[e->frame]->texnum);
233 
234 	GL_TexEnv( GL_MODULATE );
235 
236 	if ( alpha == 1.0 )
237 		qglEnable (GL_ALPHA_TEST);
238 	else
239 		qglDisable( GL_ALPHA_TEST );
240 
241 	qglBegin (GL_QUADS);
242 
243 	qglTexCoord2f (0, 1);
244 	VectorMA (e->origin, -frame->origin_y, up, point);
245 	VectorMA (point, -frame->origin_x, right, point);
246 	qglVertex3fv (point);
247 
248 	qglTexCoord2f (0, 0);
249 	VectorMA (e->origin, frame->height - frame->origin_y, up, point);
250 	VectorMA (point, -frame->origin_x, right, point);
251 	qglVertex3fv (point);
252 
253 	qglTexCoord2f (1, 0);
254 	VectorMA (e->origin, frame->height - frame->origin_y, up, point);
255 	VectorMA (point, frame->width - frame->origin_x, right, point);
256 	qglVertex3fv (point);
257 
258 	qglTexCoord2f (1, 1);
259 	VectorMA (e->origin, -frame->origin_y, up, point);
260 	VectorMA (point, frame->width - frame->origin_x, right, point);
261 	qglVertex3fv (point);
262 
263 	qglEnd ();
264 
265 	qglDisable (GL_ALPHA_TEST);
266 	GL_TexEnv( GL_REPLACE );
267 
268 	if ( alpha != 1.0F )
269 		qglDisable( GL_BLEND );
270 
271 	qglColor4f( 1, 1, 1, 1 );
272 }
273 
274 //==================================================================================
275 
276 /*
277 =============
278 R_DrawNullModel
279 =============
280 */
R_DrawNullModel(void)281 void R_DrawNullModel (void)
282 {
283 	vec3_t	shadelight;
284 	int		i;
285 
286 	if ( currententity->flags & RF_FULLBRIGHT )
287 		shadelight[0] = shadelight[1] = shadelight[2] = 1.0F;
288 	else
289 		R_LightPoint (currententity->origin, shadelight);
290 
291     qglPushMatrix ();
292 	R_RotateForEntity (currententity);
293 
294 	qglDisable (GL_TEXTURE_2D);
295 	qglColor3fv (shadelight);
296 
297 	qglBegin (GL_TRIANGLE_FAN);
298 	qglVertex3f (0, 0, -16);
299 	for (i=0 ; i<=4 ; i++)
300 		qglVertex3f (16*cos(i*M_PI/2), 16*sin(i*M_PI/2), 0);
301 	qglEnd ();
302 
303 	qglBegin (GL_TRIANGLE_FAN);
304 	qglVertex3f (0, 0, 16);
305 	for (i=4 ; i>=0 ; i--)
306 		qglVertex3f (16*cos(i*M_PI/2), 16*sin(i*M_PI/2), 0);
307 	qglEnd ();
308 
309 	qglColor3f (1,1,1);
310 	qglPopMatrix ();
311 	qglEnable (GL_TEXTURE_2D);
312 }
313 
314 /*
315 =============
316 R_DrawEntitiesOnList
317 =============
318 */
R_DrawEntitiesOnList(void)319 void R_DrawEntitiesOnList (void)
320 {
321 	int		i;
322 
323 	if (!r_drawentities->value)
324 		return;
325 
326 	// draw non-transparent first
327 	for (i=0 ; i<r_newrefdef.num_entities ; i++)
328 	{
329 		currententity = &r_newrefdef.entities[i];
330 		if (currententity->flags & RF_TRANSLUCENT)
331 			continue;	// solid
332 
333 		if ( currententity->flags & RF_BEAM )
334 		{
335 			R_DrawBeam( currententity );
336 		}
337 		else
338 		{
339 			currentmodel = currententity->model;
340 			if (!currentmodel)
341 			{
342 				R_DrawNullModel ();
343 				continue;
344 			}
345 			switch (currentmodel->type)
346 			{
347 			case mod_alias:
348 				R_DrawAliasModel (currententity);
349 				break;
350 			case mod_brush:
351 				R_DrawBrushModel (currententity);
352 				break;
353 			case mod_sprite:
354 				R_DrawSpriteModel (currententity);
355 				break;
356 			default:
357 				ri.Sys_Error (ERR_DROP, "Bad modeltype");
358 				break;
359 			}
360 		}
361 	}
362 
363 	// draw transparent entities
364 	// we could sort these if it ever becomes a problem...
365 	qglDepthMask (0);		// no z writes
366 	for (i=0 ; i<r_newrefdef.num_entities ; i++)
367 	{
368 		currententity = &r_newrefdef.entities[i];
369 		if (!(currententity->flags & RF_TRANSLUCENT))
370 			continue;	// solid
371 
372 		if ( currententity->flags & RF_BEAM )
373 		{
374 			R_DrawBeam( currententity );
375 		}
376 		else
377 		{
378 			currentmodel = currententity->model;
379 
380 			if (!currentmodel)
381 			{
382 				R_DrawNullModel ();
383 				continue;
384 			}
385 			switch (currentmodel->type)
386 			{
387 			case mod_alias:
388 				R_DrawAliasModel (currententity);
389 				break;
390 			case mod_brush:
391 				R_DrawBrushModel (currententity);
392 				break;
393 			case mod_sprite:
394 				R_DrawSpriteModel (currententity);
395 				break;
396 			default:
397 				ri.Sys_Error (ERR_DROP, "Bad modeltype");
398 				break;
399 			}
400 		}
401 	}
402 	qglDepthMask (1);		// back to writing
403 
404 }
405 
406 /*
407 ** GL_DrawParticles
408 **
409 */
GL_DrawParticles(int num_particles,const particle_t particles[],const unsigned colortable[768])410 void GL_DrawParticles( int num_particles, const particle_t particles[], const unsigned colortable[768] )
411 {
412 	const particle_t *p;
413 	int				i;
414 	vec3_t			up, right;
415 	float			scale;
416 	byte			color[4];
417 
418     GL_Bind(r_particletexture->texnum);
419 	qglDepthMask( GL_FALSE );		// no z buffering
420 	qglEnable( GL_BLEND );
421 	GL_TexEnv( GL_MODULATE );
422 	qglBegin( GL_TRIANGLES );
423 
424 	VectorScale (vup, 1.5, up);
425 	VectorScale (vright, 1.5, right);
426 
427 	for ( p = particles, i=0 ; i < num_particles ; i++,p++)
428 	{
429 		// hack a scale up to keep particles from disapearing
430 		scale = ( p->origin[0] - r_origin[0] ) * vpn[0] +
431 			    ( p->origin[1] - r_origin[1] ) * vpn[1] +
432 			    ( p->origin[2] - r_origin[2] ) * vpn[2];
433 
434 		if (scale < 20)
435 			scale = 1;
436 		else
437 			scale = 1 + scale * 0.004;
438 
439 		*(int *)color = colortable[p->color];
440 		color[3] = p->alpha*255;
441 
442 		qglColor4ubv( color );
443 
444 		qglTexCoord2f( 0.0625, 0.0625 );
445 		qglVertex3fv( p->origin );
446 
447 		qglTexCoord2f( 1.0625, 0.0625 );
448 		qglVertex3f( p->origin[0] + up[0]*scale,
449 			         p->origin[1] + up[1]*scale,
450 					 p->origin[2] + up[2]*scale);
451 
452 		qglTexCoord2f( 0.0625, 1.0625 );
453 		qglVertex3f( p->origin[0] + right[0]*scale,
454 			         p->origin[1] + right[1]*scale,
455 					 p->origin[2] + right[2]*scale);
456 	}
457 
458 	qglEnd ();
459 	qglDisable( GL_BLEND );
460 	qglColor4f( 1,1,1,1 );
461 	qglDepthMask( 1 );		// back to normal Z buffering
462 	GL_TexEnv( GL_REPLACE );
463 }
464 
465 /*
466 ===============
467 R_DrawParticles
468 ===============
469 */
R_DrawParticles(void)470 void R_DrawParticles (void)
471 {
472 	if ( gl_ext_pointparameters->value && qglPointParameterfEXT )
473 	{
474 		int i;
475 		unsigned char color[4];
476 		const particle_t *p;
477 
478 		qglDepthMask( GL_FALSE );
479 		qglEnable( GL_BLEND );
480 		qglDisable( GL_TEXTURE_2D );
481 
482 		qglPointSize( gl_particle_size->value );
483 
484 		qglBegin( GL_POINTS );
485 		for ( i = 0, p = r_newrefdef.particles; i < r_newrefdef.num_particles; i++, p++ )
486 		{
487 			*(int *)color = d_8to24table[p->color];
488 			color[3] = p->alpha*255;
489 
490 			qglColor4ubv( color );
491 
492 			qglVertex3fv( p->origin );
493 		}
494 		qglEnd();
495 
496 		qglDisable( GL_BLEND );
497 		qglColor4f( 1.0F, 1.0F, 1.0F, 1.0F );
498 		qglDepthMask( GL_TRUE );
499 		qglEnable( GL_TEXTURE_2D );
500 
501 	}
502 	else
503 	{
504 		GL_DrawParticles( r_newrefdef.num_particles, r_newrefdef.particles, d_8to24table );
505 	}
506 }
507 
508 /*
509 ============
510 R_PolyBlend
511 ============
512 */
R_PolyBlend(void)513 void R_PolyBlend (void)
514 {
515 	if (!gl_polyblend->value)
516 		return;
517 	if (!v_blend[3])
518 		return;
519 
520 	qglDisable (GL_ALPHA_TEST);
521 	qglEnable (GL_BLEND);
522 	qglDisable (GL_DEPTH_TEST);
523 	qglDisable (GL_TEXTURE_2D);
524 
525     qglLoadIdentity ();
526 
527 	// FIXME: get rid of these
528     qglRotatef (-90,  1, 0, 0);	    // put Z going up
529     qglRotatef (90,  0, 0, 1);	    // put Z going up
530 
531 	qglColor4fv (v_blend);
532 
533 	qglBegin (GL_QUADS);
534 
535 	qglVertex3f (10, 100, 100);
536 	qglVertex3f (10, -100, 100);
537 	qglVertex3f (10, -100, -100);
538 	qglVertex3f (10, 100, -100);
539 	qglEnd ();
540 
541 	qglDisable (GL_BLEND);
542 	qglEnable (GL_TEXTURE_2D);
543 	qglEnable (GL_ALPHA_TEST);
544 
545 	qglColor4f(1,1,1,1);
546 }
547 
548 //=======================================================================
549 
SignbitsForPlane(cplane_t * out)550 int SignbitsForPlane (cplane_t *out)
551 {
552 	int	bits, j;
553 
554 	// for fast box on planeside test
555 
556 	bits = 0;
557 	for (j=0 ; j<3 ; j++)
558 	{
559 		if (out->normal[j] < 0)
560 			bits |= 1<<j;
561 	}
562 	return bits;
563 }
564 
565 
R_SetFrustum(void)566 void R_SetFrustum (void)
567 {
568 	int		i;
569 
570 #if 0
571 	/*
572 	** this code is wrong, since it presume a 90 degree FOV both in the
573 	** horizontal and vertical plane
574 	*/
575 	// front side is visible
576 	VectorAdd (vpn, vright, frustum[0].normal);
577 	VectorSubtract (vpn, vright, frustum[1].normal);
578 	VectorAdd (vpn, vup, frustum[2].normal);
579 	VectorSubtract (vpn, vup, frustum[3].normal);
580 
581 	// we theoretically don't need to normalize these vectors, but I do it
582 	// anyway so that debugging is a little easier
583 	VectorNormalize( frustum[0].normal );
584 	VectorNormalize( frustum[1].normal );
585 	VectorNormalize( frustum[2].normal );
586 	VectorNormalize( frustum[3].normal );
587 #else
588 	// rotate VPN right by FOV_X/2 degrees
589 	RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_newrefdef.fov_x / 2 ) );
590 	// rotate VPN left by FOV_X/2 degrees
591 	RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_newrefdef.fov_x / 2 );
592 	// rotate VPN up by FOV_X/2 degrees
593 	RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_newrefdef.fov_y / 2 );
594 	// rotate VPN down by FOV_X/2 degrees
595 	RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_newrefdef.fov_y / 2 ) );
596 #endif
597 
598 	for (i=0 ; i<4 ; i++)
599 	{
600 		frustum[i].type = PLANE_ANYZ;
601 		frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
602 		frustum[i].signbits = SignbitsForPlane (&frustum[i]);
603 	}
604 }
605 
606 //=======================================================================
607 
608 /*
609 ===============
610 R_SetupFrame
611 ===============
612 */
R_SetupFrame(void)613 void R_SetupFrame (void)
614 {
615 	int i;
616 	mleaf_t	*leaf;
617 
618 	r_framecount++;
619 
620 // build the transformation matrix for the given view angles
621 	VectorCopy (r_newrefdef.vieworg, r_origin);
622 
623 	AngleVectors (r_newrefdef.viewangles, vpn, vright, vup);
624 
625 // current viewcluster
626 	if ( !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
627 	{
628 		r_oldviewcluster = r_viewcluster;
629 		r_oldviewcluster2 = r_viewcluster2;
630 		leaf = Mod_PointInLeaf (r_origin, r_worldmodel);
631 		r_viewcluster = r_viewcluster2 = leaf->cluster;
632 
633 		// check above and below so crossing solid water doesn't draw wrong
634 		if (!leaf->contents)
635 		{	// look down a bit
636 			vec3_t	temp;
637 
638 			VectorCopy (r_origin, temp);
639 			temp[2] -= 16;
640 			leaf = Mod_PointInLeaf (temp, r_worldmodel);
641 			if ( !(leaf->contents & CONTENTS_SOLID) &&
642 				(leaf->cluster != r_viewcluster2) )
643 				r_viewcluster2 = leaf->cluster;
644 		}
645 		else
646 		{	// look up a bit
647 			vec3_t	temp;
648 
649 			VectorCopy (r_origin, temp);
650 			temp[2] += 16;
651 			leaf = Mod_PointInLeaf (temp, r_worldmodel);
652 			if ( !(leaf->contents & CONTENTS_SOLID) &&
653 				(leaf->cluster != r_viewcluster2) )
654 				r_viewcluster2 = leaf->cluster;
655 		}
656 	}
657 
658 	for (i=0 ; i<4 ; i++)
659 		v_blend[i] = r_newrefdef.blend[i];
660 
661 	c_brush_polys = 0;
662 	c_alias_polys = 0;
663 
664 	// clear out the portion of the screen that the NOWORLDMODEL defines
665 	if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL )
666 	{
667 		qglEnable( GL_SCISSOR_TEST );
668 		qglClearColor( 0.3, 0.3, 0.3, 1 );
669 		qglScissor( r_newrefdef.x, vid.height - r_newrefdef.height - r_newrefdef.y, r_newrefdef.width, r_newrefdef.height );
670 		qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
671 		qglClearColor( 1, 0, 0.5, 0.5 );
672 		qglDisable( GL_SCISSOR_TEST );
673 	}
674 }
675 
676 
MYgluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)677 void MYgluPerspective( GLdouble fovy, GLdouble aspect,
678 		     GLdouble zNear, GLdouble zFar )
679 {
680    GLdouble xmin, xmax, ymin, ymax;
681 
682    ymax = zNear * tan( fovy * M_PI / 360.0 );
683    ymin = -ymax;
684 
685    xmin = ymin * aspect;
686    xmax = ymax * aspect;
687 
688    xmin += -( 2 * gl_state.camera_separation ) / zNear;
689    xmax += -( 2 * gl_state.camera_separation ) / zNear;
690 
691    qglFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
692 }
693 
694 
695 /*
696 =============
697 R_SetupGL
698 =============
699 */
R_SetupGL(void)700 void R_SetupGL (void)
701 {
702 	float	screenaspect;
703 //	float	yfov;
704 	int		x, x2, y2, y, w, h;
705 
706 	//
707 	// set up viewport
708 	//
709 	x = floor(r_newrefdef.x * vid.width / vid.width);
710 	x2 = ceil((r_newrefdef.x + r_newrefdef.width) * vid.width / vid.width);
711 	y = floor(vid.height - r_newrefdef.y * vid.height / vid.height);
712 	y2 = ceil(vid.height - (r_newrefdef.y + r_newrefdef.height) * vid.height / vid.height);
713 
714 	w = x2 - x;
715 	h = y - y2;
716 
717 	qglViewport (x, y2, w, h);
718 
719 	//
720 	// set up projection matrix
721 	//
722     screenaspect = (float)r_newrefdef.width/r_newrefdef.height;
723 //	yfov = 2*atan((float)r_newrefdef.height/r_newrefdef.width)*180/M_PI;
724 	qglMatrixMode(GL_PROJECTION);
725     qglLoadIdentity ();
726     MYgluPerspective (r_newrefdef.fov_y,  screenaspect,  4,  4096);
727 
728 	qglCullFace(GL_FRONT);
729 
730 	qglMatrixMode(GL_MODELVIEW);
731     qglLoadIdentity ();
732 
733     qglRotatef (-90,  1, 0, 0);	    // put Z going up
734     qglRotatef (90,  0, 0, 1);	    // put Z going up
735     qglRotatef (-r_newrefdef.viewangles[2],  1, 0, 0);
736     qglRotatef (-r_newrefdef.viewangles[0],  0, 1, 0);
737     qglRotatef (-r_newrefdef.viewangles[1],  0, 0, 1);
738     qglTranslatef (-r_newrefdef.vieworg[0],  -r_newrefdef.vieworg[1],  -r_newrefdef.vieworg[2]);
739 
740 //	if ( gl_state.camera_separation != 0 && gl_state.stereo_enabled )
741 //		qglTranslatef ( gl_state.camera_separation, 0, 0 );
742 
743 	qglGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
744 
745 	//
746 	// set drawing parms
747 	//
748 	if (gl_cull->value)
749 		qglEnable(GL_CULL_FACE);
750 	else
751 		qglDisable(GL_CULL_FACE);
752 
753 	qglDisable(GL_BLEND);
754 	qglDisable(GL_ALPHA_TEST);
755 	qglEnable(GL_DEPTH_TEST);
756 }
757 
758 /*
759 =============
760 R_Clear
761 =============
762 */
763 extern qboolean have_stencil;
764 
R_Clear(void)765 void R_Clear (void)
766 {
767 	if (gl_ztrick->value)
768 	{
769 		static int trickframe;
770 
771 		if (gl_clear->value)
772 			qglClear (GL_COLOR_BUFFER_BIT);
773 
774 		trickframe++;
775 		if (trickframe & 1)
776 		{
777 			gldepthmin = 0;
778 			gldepthmax = 0.49999;
779 			qglDepthFunc (GL_LEQUAL);
780 		}
781 		else
782 		{
783 			gldepthmin = 1;
784 			gldepthmax = 0.5;
785 			qglDepthFunc (GL_GEQUAL);
786 		}
787 	}
788 	else
789 	{
790 		if (gl_clear->value)
791 			qglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
792 		else
793 			qglClear (GL_DEPTH_BUFFER_BIT);
794 		gldepthmin = 0;
795 		gldepthmax = 1;
796 		qglDepthFunc (GL_LEQUAL);
797 	}
798 
799 	qglDepthRange (gldepthmin, gldepthmax);
800 
801 	/* stencilbuffer shadows */
802 	if (gl_shadows->value && have_stencil && gl_stencilshadow->value) {
803 		qglClearStencil(1);
804 		qglClear(GL_STENCIL_BUFFER_BIT);
805 	}
806 }
807 
R_Flash(void)808 void R_Flash( void )
809 {
810 	R_PolyBlend ();
811 }
812 
813 /*
814 ================
815 R_RenderView
816 
817 r_newrefdef must be set before the first call
818 ================
819 */
R_RenderView(refdef_t * fd)820 void R_RenderView (refdef_t *fd)
821 {
822 	if (r_norefresh->value)
823 		return;
824 
825 	r_newrefdef = *fd;
826 
827 	if (!r_worldmodel && !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
828 		ri.Sys_Error (ERR_DROP, "R_RenderView: NULL worldmodel");
829 
830 	if (r_speeds->value)
831 	{
832 		c_brush_polys = 0;
833 		c_alias_polys = 0;
834 	}
835 
836 	R_PushDlights ();
837 
838 	if (gl_finish->value)
839 		qglFinish ();
840 
841 	R_SetupFrame ();
842 
843 	R_SetFrustum ();
844 
845 	R_SetupGL ();
846 
847 	R_MarkLeaves ();	// done here so we know if we're in water
848 
849 	R_DrawWorld ();
850 
851 	R_DrawEntitiesOnList ();
852 
853 	R_RenderDlights ();
854 
855 	R_DrawParticles ();
856 
857 	R_DrawAlphaSurfaces ();
858 
859 	R_Flash();
860 
861 	if (r_speeds->value)
862 	{
863 		ri.Con_Printf (PRINT_ALL, "%4i wpoly %4i epoly %i tex %i lmaps\n",
864 			c_brush_polys,
865 			c_alias_polys,
866 			c_visible_textures,
867 			c_visible_lightmaps);
868 	}
869 }
870 
871 
R_SetGL2D(void)872 void	R_SetGL2D (void)
873 {
874 	// set 2D virtual screen size
875 	qglViewport (0,0, vid.width, vid.height);
876 	qglMatrixMode(GL_PROJECTION);
877     qglLoadIdentity ();
878 	qglOrtho  (0, vid.width, vid.height, 0, -99999, 99999);
879 	qglMatrixMode(GL_MODELVIEW);
880     qglLoadIdentity ();
881 	qglDisable (GL_DEPTH_TEST);
882 	qglDisable (GL_CULL_FACE);
883 	qglDisable (GL_BLEND);
884 	qglEnable (GL_ALPHA_TEST);
885 	qglColor4f (1,1,1,1);
886 }
887 
888 #if 0 // Not used.
889 static void GL_DrawColoredStereoLinePair( float r, float g, float b, float y )
890 {
891 	qglColor3f( r, g, b );
892 	qglVertex2f( 0, y );
893 	qglVertex2f( vid.width, y );
894 	qglColor3f( 0, 0, 0 );
895 	qglVertex2f( 0, y + 1 );
896 	qglVertex2f( vid.width, y + 1 );
897 }
898 
899 static void GL_DrawStereoPattern( void )
900 {
901 	int i;
902 
903 	if ( !( gl_config.renderer & GL_RENDERER_INTERGRAPH ) )
904 		return;
905 
906 	if ( !gl_state.stereo_enabled )
907 		return;
908 
909 	R_SetGL2D();
910 
911 	qglDrawBuffer( GL_BACK_LEFT );
912 
913 	for ( i = 0; i < 20; i++ )
914 	{
915 		qglBegin( GL_LINES );
916 			GL_DrawColoredStereoLinePair( 1, 0, 0, 0 );
917 			GL_DrawColoredStereoLinePair( 1, 0, 0, 2 );
918 			GL_DrawColoredStereoLinePair( 1, 0, 0, 4 );
919 			GL_DrawColoredStereoLinePair( 1, 0, 0, 6 );
920 			GL_DrawColoredStereoLinePair( 0, 1, 0, 8 );
921 			GL_DrawColoredStereoLinePair( 1, 1, 0, 10);
922 			GL_DrawColoredStereoLinePair( 1, 1, 0, 12);
923 			GL_DrawColoredStereoLinePair( 0, 1, 0, 14);
924 		qglEnd();
925 
926 		GLimp_EndFrame();
927 	}
928 }
929 #endif
930 
931 /*
932 ====================
933 R_SetLightLevel
934 
935 ====================
936 */
R_SetLightLevel(void)937 void R_SetLightLevel (void)
938 {
939 	vec3_t		shadelight;
940 
941 	if (r_newrefdef.rdflags & RDF_NOWORLDMODEL)
942 		return;
943 
944 	// save off light value for server to look at (BIG HACK!)
945 
946 	R_LightPoint (r_newrefdef.vieworg, shadelight);
947 
948 	// pick the greatest component, which should be the same
949 	// as the mono value returned by software
950 	if (shadelight[0] > shadelight[1])
951 	{
952 		if (shadelight[0] > shadelight[2])
953 			r_lightlevel->value = 150*shadelight[0];
954 		else
955 			r_lightlevel->value = 150*shadelight[2];
956 	}
957 	else
958 	{
959 		if (shadelight[1] > shadelight[2])
960 			r_lightlevel->value = 150*shadelight[1];
961 		else
962 			r_lightlevel->value = 150*shadelight[2];
963 	}
964 
965 }
966 
967 /*
968 @@@@@@@@@@@@@@@@@@@@@
969 R_RenderFrame
970 
971 @@@@@@@@@@@@@@@@@@@@@
972 */
R_RenderFrame(refdef_t * fd)973 void R_RenderFrame (refdef_t *fd)
974 {
975 	R_RenderView( fd );
976 	R_SetLightLevel ();
977 	R_SetGL2D ();
978 }
979 
980 
R_Register(void)981 void R_Register( void )
982 {
983 	r_lefthand = ri.Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE );
984 	r_norefresh = ri.Cvar_Get ("r_norefresh", "0", 0);
985 	r_fullbright = ri.Cvar_Get ("r_fullbright", "0", 0);
986 	r_drawentities = ri.Cvar_Get ("r_drawentities", "1", 0);
987 	r_drawworld = ri.Cvar_Get ("r_drawworld", "1", 0);
988 	r_novis = ri.Cvar_Get ("r_novis", "0", 0);
989 	r_nocull = ri.Cvar_Get ("r_nocull", "0", 0);
990 	r_lerpmodels = ri.Cvar_Get ("r_lerpmodels", "1", 0);
991 	r_speeds = ri.Cvar_Get ("r_speeds", "0", 0);
992 
993 	r_lightlevel = ri.Cvar_Get ("r_lightlevel", "0", 0);
994 
995 	gl_nosubimage = ri.Cvar_Get( "gl_nosubimage", "0", 0 );
996 	gl_allow_software = ri.Cvar_Get( "gl_allow_software", "0", 0 );
997 
998 	gl_particle_min_size = ri.Cvar_Get( "gl_particle_min_size", "2", CVAR_ARCHIVE );
999 	gl_particle_max_size = ri.Cvar_Get( "gl_particle_max_size", "40", CVAR_ARCHIVE );
1000 	gl_particle_size = ri.Cvar_Get( "gl_particle_size", "40", CVAR_ARCHIVE );
1001 	gl_particle_att_a = ri.Cvar_Get( "gl_particle_att_a", "0.01", CVAR_ARCHIVE );
1002 	gl_particle_att_b = ri.Cvar_Get( "gl_particle_att_b", "0.0", CVAR_ARCHIVE );
1003 	gl_particle_att_c = ri.Cvar_Get( "gl_particle_att_c", "0.01", CVAR_ARCHIVE );
1004 
1005 	gl_modulate = ri.Cvar_Get ("gl_modulate", "1", CVAR_ARCHIVE );
1006 	gl_log = ri.Cvar_Get( "gl_log", "0", 0 );
1007 	gl_bitdepth = ri.Cvar_Get( "gl_bitdepth", "0", 0 );
1008 	gl_mode = ri.Cvar_Get( "gl_mode", "3", CVAR_ARCHIVE );
1009 	gl_lightmap = ri.Cvar_Get ("gl_lightmap", "0", 0);
1010 	gl_shadows = ri.Cvar_Get ("gl_shadows", "0", CVAR_ARCHIVE );
1011 	gl_stencilshadow = ri.Cvar_Get("gl_stencilshadow", "0", CVAR_ARCHIVE);
1012 	gl_dynamic = ri.Cvar_Get ("gl_dynamic", "1", 0);
1013 	gl_nobind = ri.Cvar_Get ("gl_nobind", "0", 0);
1014 	gl_round_down = ri.Cvar_Get ("gl_round_down", "1", 0);
1015 	gl_picmip = ri.Cvar_Get ("gl_picmip", "0", 0);
1016 	gl_skymip = ri.Cvar_Get ("gl_skymip", "0", 0);
1017 	gl_showtris = ri.Cvar_Get ("gl_showtris", "0", 0);
1018 	gl_ztrick = ri.Cvar_Get ("gl_ztrick", "0", 0);
1019 	gl_finish = ri.Cvar_Get ("gl_finish", "0", CVAR_ARCHIVE);
1020 	gl_clear = ri.Cvar_Get ("gl_clear", "0", 0);
1021 	gl_cull = ri.Cvar_Get ("gl_cull", "1", 0);
1022 	gl_polyblend = ri.Cvar_Get ("gl_polyblend", "1", 0);
1023 	gl_flashblend = ri.Cvar_Get ("gl_flashblend", "0", 0);
1024 	gl_playermip = ri.Cvar_Get ("gl_playermip", "0", 0);
1025 	gl_monolightmap = ri.Cvar_Get( "gl_monolightmap", "0", 0 );
1026 #ifdef _WIN32
1027 	gl_driver = ri.Cvar_Get( "gl_driver", "opengl32", CVAR_ARCHIVE );
1028 #else
1029 	gl_driver = ri.Cvar_Get( "gl_driver", "libGL.so", CVAR_ARCHIVE );
1030 #endif
1031 	gl_texturemode = ri.Cvar_Get( "gl_texturemode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE );
1032 	gl_texturealphamode = ri.Cvar_Get( "gl_texturealphamode", "default", CVAR_ARCHIVE );
1033 	gl_texturesolidmode = ri.Cvar_Get( "gl_texturesolidmode", "default", CVAR_ARCHIVE );
1034 	gl_lockpvs = ri.Cvar_Get( "gl_lockpvs", "0", 0 );
1035 
1036 	gl_vertex_arrays = ri.Cvar_Get( "gl_vertex_arrays", "0", CVAR_ARCHIVE );
1037 
1038 	gl_ext_swapinterval = ri.Cvar_Get( "gl_ext_swapinterval", "1", CVAR_ARCHIVE );
1039 	gl_ext_palettedtexture = ri.Cvar_Get( "gl_ext_palettedtexture", "1", CVAR_ARCHIVE );
1040 	gl_ext_multitexture = ri.Cvar_Get( "gl_ext_multitexture", "1", CVAR_ARCHIVE );
1041 	gl_ext_pointparameters = ri.Cvar_Get( "gl_ext_pointparameters", "1", CVAR_ARCHIVE );
1042 	gl_ext_compiled_vertex_array = ri.Cvar_Get( "gl_ext_compiled_vertex_array", "1", CVAR_ARCHIVE );
1043 
1044 	gl_drawbuffer = ri.Cvar_Get( "gl_drawbuffer", "GL_BACK", 0 );
1045 	gl_swapinterval = ri.Cvar_Get( "gl_swapinterval", "1", CVAR_ARCHIVE );
1046 
1047 	gl_saturatelighting = ri.Cvar_Get( "gl_saturatelighting", "0", 0 );
1048 
1049 	gl_3dlabs_broken = ri.Cvar_Get( "gl_3dlabs_broken", "1", CVAR_ARCHIVE );
1050 
1051 	vid_fullscreen = ri.Cvar_Get( "vid_fullscreen", "0", CVAR_ARCHIVE );
1052 	vid_gamma = ri.Cvar_Get( "vid_gamma", "1.0", CVAR_ARCHIVE );
1053 	vid_ref = ri.Cvar_Get( "vid_ref", "soft", CVAR_ARCHIVE );
1054 
1055 	ri.Cmd_AddCommand( "imagelist", GL_ImageList_f );
1056 	ri.Cmd_AddCommand( "screenshot", GL_ScreenShot_f );
1057 	ri.Cmd_AddCommand( "modellist", Mod_Modellist_f );
1058 	ri.Cmd_AddCommand( "gl_strings", GL_Strings_f );
1059 }
1060 
1061 /*
1062 ==================
1063 R_SetMode
1064 ==================
1065 */
R_SetMode(void)1066 qboolean R_SetMode (void)
1067 {
1068 	rserr_t err;
1069 	qboolean fullscreen;
1070 
1071 #ifdef _WIN32
1072 	if ( vid_fullscreen->modified && !gl_config.allow_cds )
1073 	{
1074 		ri.Con_Printf( PRINT_ALL, "R_SetMode() - CDS not allowed with this driver\n" );
1075 		ri.Cvar_SetValue( "vid_fullscreen", !vid_fullscreen->value );
1076 		vid_fullscreen->modified = false;
1077 	}
1078 #endif
1079 	fullscreen = vid_fullscreen->value;
1080 
1081 	vid_fullscreen->modified = false;
1082 	gl_mode->modified = false;
1083 
1084 	if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_mode->value, fullscreen ) ) == rserr_ok )
1085 	{
1086 		gl_state.prev_mode = gl_mode->value;
1087 	}
1088 	else
1089 	{
1090 		if ( err == rserr_invalid_fullscreen )
1091 		{
1092 			ri.Cvar_SetValue( "vid_fullscreen", 0);
1093 			vid_fullscreen->modified = false;
1094 			ri.Con_Printf( PRINT_ALL, "ref_gl::R_SetMode() - fullscreen unavailable in this mode\n" );
1095 			if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_mode->value, false ) ) == rserr_ok )
1096 				return true;
1097 		}
1098 		else if ( err == rserr_invalid_mode )
1099 		{
1100 			ri.Cvar_SetValue( "gl_mode", gl_state.prev_mode );
1101 			gl_mode->modified = false;
1102 			ri.Con_Printf( PRINT_ALL, "ref_gl::R_SetMode() - invalid mode\n" );
1103 		}
1104 
1105 		// try setting it back to something safe
1106 		if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_state.prev_mode, false ) ) != rserr_ok )
1107 		{
1108 			ri.Con_Printf( PRINT_ALL, "ref_gl::R_SetMode() - could not revert to safe mode\n" );
1109 			return false;
1110 		}
1111 	}
1112 	return true;
1113 }
1114 
1115 /*
1116 ===============
1117 R_Init
1118 ===============
1119 */
R_Init(void * hinstance,void * hWnd)1120 int R_Init( void *hinstance, void *hWnd )
1121 {
1122 	char renderer_buffer[1000];
1123 	char vendor_buffer[1000];
1124 	int		err;
1125 	int		j;
1126 	extern float r_turbsin[256];
1127 
1128 	for ( j = 0; j < 256; j++ )
1129 	{
1130 		r_turbsin[j] *= 0.5;
1131 	}
1132 
1133 	ri.Con_Printf (PRINT_ALL, "ref_gl version: "REF_VERSION"\n");
1134 
1135 	Draw_GetPalette ();
1136 
1137 	R_Register();
1138 
1139 	// initialize our QGL dynamic bindings
1140 	if ( !QGL_Init( gl_driver->string ) )
1141 	{
1142 		QGL_Shutdown();
1143 		ri.Con_Printf (PRINT_ALL, "ref_gl::R_Init() - could not load \"%s\"\n", gl_driver->string );
1144 		return -1;
1145 	}
1146 
1147 	// initialize OS-specific parts of OpenGL
1148 	if ( !GLimp_Init( hinstance, hWnd ) )
1149 	{
1150 		QGL_Shutdown();
1151 		return -1;
1152 	}
1153 
1154 	// set our "safe" modes
1155 	gl_state.prev_mode = 3;
1156 
1157 	// create the window and set up the context
1158 	if ( !R_SetMode () )
1159 	{
1160 		QGL_Shutdown();
1161 		ri.Con_Printf (PRINT_ALL, "ref_gl::R_Init() - could not R_SetMode()\n" );
1162 		return -1;
1163 	}
1164 
1165 	ri.Vid_MenuInit();
1166 
1167 	/*
1168 	** get our various GL strings
1169 	*/
1170 	gl_config.vendor_string = (char *)qglGetString (GL_VENDOR);
1171 	ri.Con_Printf (PRINT_ALL, "GL_VENDOR: %s\n", gl_config.vendor_string );
1172 	gl_config.renderer_string = (char *)qglGetString (GL_RENDERER);
1173 	ri.Con_Printf (PRINT_ALL, "GL_RENDERER: %s\n", gl_config.renderer_string );
1174 	gl_config.version_string = (char *)qglGetString (GL_VERSION);
1175 	ri.Con_Printf (PRINT_ALL, "GL_VERSION: %s\n", gl_config.version_string );
1176 	gl_config.extensions_string = (char *)qglGetString (GL_EXTENSIONS);
1177 	ri.Con_Printf (PRINT_ALL, "GL_EXTENSIONS: %s\n", gl_config.extensions_string );
1178 
1179 	strncpy( renderer_buffer, gl_config.renderer_string, sizeof(renderer_buffer) );
1180 	renderer_buffer[sizeof(renderer_buffer)-1] = 0;
1181 	strlwr( renderer_buffer );
1182 
1183 	strncpy( vendor_buffer, gl_config.vendor_string, sizeof(vendor_buffer) );
1184 	vendor_buffer[sizeof(vendor_buffer)-1] = 0;
1185 	strlwr( vendor_buffer );
1186 
1187 	if ( strstr( renderer_buffer, "voodoo" ) )
1188 	{
1189 		if ( !strstr( renderer_buffer, "rush" ) )
1190 			gl_config.renderer = GL_RENDERER_VOODOO;
1191 		else
1192 			gl_config.renderer = GL_RENDERER_VOODOO_RUSH;
1193 	}
1194 	else if ( strstr( vendor_buffer, "sgi" ) )
1195 		gl_config.renderer = GL_RENDERER_SGI;
1196 	else if ( strstr( renderer_buffer, "permedia" ) )
1197 		gl_config.renderer = GL_RENDERER_PERMEDIA2;
1198 	else if ( strstr( renderer_buffer, "glint" ) )
1199 		gl_config.renderer = GL_RENDERER_GLINT_MX;
1200 	else if ( strstr( renderer_buffer, "glzicd" ) )
1201 		gl_config.renderer = GL_RENDERER_REALIZM;
1202 	else if ( strstr( renderer_buffer, "gdi" ) )
1203 		gl_config.renderer = GL_RENDERER_MCD;
1204 	else if ( strstr( renderer_buffer, "pcx2" ) )
1205 		gl_config.renderer = GL_RENDERER_PCX2;
1206 	else if ( strstr( renderer_buffer, "verite" ) )
1207 		gl_config.renderer = GL_RENDERER_RENDITION;
1208 	else
1209 		gl_config.renderer = GL_RENDERER_OTHER;
1210 
1211 	if ( toupper( gl_monolightmap->string[1] ) != 'F' )
1212 	{
1213 		if ( gl_config.renderer == GL_RENDERER_PERMEDIA2 )
1214 		{
1215 			ri.Cvar_Set( "gl_monolightmap", "A" );
1216 			ri.Con_Printf( PRINT_ALL, "...using gl_monolightmap 'a'\n" );
1217 		}
1218 		else if ( gl_config.renderer & GL_RENDERER_POWERVR )
1219 		{
1220 			ri.Cvar_Set( "gl_monolightmap", "0" );
1221 		}
1222 		else
1223 		{
1224 			ri.Cvar_Set( "gl_monolightmap", "0" );
1225 		}
1226 	}
1227 
1228 	// power vr can't have anything stay in the framebuffer, so
1229 	// the screen needs to redraw the tiled background every frame
1230 	if ( gl_config.renderer & GL_RENDERER_POWERVR )
1231 	{
1232 		ri.Cvar_Set( "scr_drawall", "1" );
1233 	}
1234 	else
1235 	{
1236 		ri.Cvar_Set( "scr_drawall", "0" );
1237 	}
1238 
1239 #if 0 && defined(__linux__)
1240 	ri.Cvar_SetValue( "gl_finish", 1 );
1241 #endif
1242 
1243 	// MCD has buffering issues
1244 	if ( gl_config.renderer == GL_RENDERER_MCD )
1245 	{
1246 		ri.Cvar_SetValue( "gl_finish", 1 );
1247 	}
1248 
1249 	if ( gl_config.renderer & GL_RENDERER_3DLABS )
1250 	{
1251 		if ( gl_3dlabs_broken->value )
1252 			gl_config.allow_cds = false;
1253 		else
1254 			gl_config.allow_cds = true;
1255 	}
1256 	else
1257 	{
1258 		gl_config.allow_cds = true;
1259 	}
1260 
1261 #ifdef _WIN32
1262 	if ( gl_config.allow_cds )
1263 		ri.Con_Printf( PRINT_ALL, "...allowing CDS\n" );
1264 	else
1265 		ri.Con_Printf( PRINT_ALL, "...disabling CDS\n" );
1266 #endif
1267 	/*
1268 	** grab extensions
1269 	*/
1270 	if ( strstr( gl_config.extensions_string, "GL_EXT_compiled_vertex_array" ) ||
1271 		 strstr( gl_config.extensions_string, "GL_SGI_compiled_vertex_array" ) )
1272 	{
1273 		ri.Con_Printf( PRINT_ALL, "...enabling GL_EXT_compiled_vertex_array\n" );
1274 		qglLockArraysEXT = ( void * ) qwglGetProcAddress( "glLockArraysEXT" );
1275 		qglUnlockArraysEXT = ( void * ) qwglGetProcAddress( "glUnlockArraysEXT" );
1276 	}
1277 	else
1278 	{
1279 		ri.Con_Printf( PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n" );
1280 	}
1281 
1282 #ifdef _WIN32
1283 	if ( strstr( gl_config.extensions_string, "WGL_EXT_swap_control" ) )
1284 	{
1285 		qwglSwapIntervalEXT = ( BOOL (WINAPI *)(int)) qwglGetProcAddress( "wglSwapIntervalEXT" );
1286 		ri.Con_Printf( PRINT_ALL, "...enabling WGL_EXT_swap_control\n" );
1287 	}
1288 	else
1289 	{
1290 		ri.Con_Printf( PRINT_ALL, "...WGL_EXT_swap_control not found\n" );
1291 	}
1292 #endif
1293 
1294 	if ( strstr( gl_config.extensions_string, "GL_EXT_point_parameters" ) )
1295 	{
1296 		if ( gl_ext_pointparameters->value )
1297 		{
1298 			qglPointParameterfEXT = ( void (APIENTRY *)( GLenum, GLfloat ) ) qwglGetProcAddress( "glPointParameterfEXT" );
1299 			qglPointParameterfvEXT = ( void (APIENTRY *)( GLenum, const GLfloat * ) ) qwglGetProcAddress( "glPointParameterfvEXT" );
1300 			ri.Con_Printf( PRINT_ALL, "...using GL_EXT_point_parameters\n" );
1301 		}
1302 		else
1303 		{
1304 			ri.Con_Printf( PRINT_ALL, "...ignoring GL_EXT_point_parameters\n" );
1305 		}
1306 	}
1307 	else
1308 	{
1309 		ri.Con_Printf( PRINT_ALL, "...GL_EXT_point_parameters not found\n" );
1310 	}
1311 
1312 #ifdef __linux__
1313 	if ( strstr( gl_config.extensions_string, "3DFX_set_global_palette" ))
1314 	{
1315 		if ( gl_ext_palettedtexture->value )
1316 		{
1317 			ri.Con_Printf( PRINT_ALL, "...using 3DFX_set_global_palette\n" );
1318 			qgl3DfxSetPaletteEXT = ( void ( APIENTRY * ) (GLuint *) )qwglGetProcAddress( "gl3DfxSetPaletteEXT" );
1319 			qglColorTableEXT = Fake_glColorTableEXT;
1320 		}
1321 		else
1322 		{
1323 			ri.Con_Printf( PRINT_ALL, "...ignoring 3DFX_set_global_palette\n" );
1324 		}
1325 	}
1326 	else
1327 	{
1328 		ri.Con_Printf( PRINT_ALL, "...3DFX_set_global_palette not found\n" );
1329 	}
1330 #endif
1331 
1332 	if ( !qglColorTableEXT &&
1333 		strstr( gl_config.extensions_string, "GL_EXT_paletted_texture" ) &&
1334 		strstr( gl_config.extensions_string, "GL_EXT_shared_texture_palette" ) )
1335 	{
1336 		if ( gl_ext_palettedtexture->value )
1337 		{
1338 			ri.Con_Printf( PRINT_ALL, "...using GL_EXT_shared_texture_palette\n" );
1339 			qglColorTableEXT = ( void ( APIENTRY * ) ( GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid * ) ) qwglGetProcAddress( "glColorTableEXT" );
1340 		}
1341 		else
1342 		{
1343 			ri.Con_Printf( PRINT_ALL, "...ignoring GL_EXT_shared_texture_palette\n" );
1344 		}
1345 	}
1346 	else
1347 	{
1348 		ri.Con_Printf( PRINT_ALL, "...GL_EXT_shared_texture_palette not found\n" );
1349 	}
1350 
1351 	if ( strstr( gl_config.extensions_string, "GL_ARB_multitexture" ) )
1352 	{
1353 		if ( gl_ext_multitexture->value )
1354 		{
1355 			ri.Con_Printf( PRINT_ALL, "...using GL_ARB_multitexture\n" );
1356 			qglMTexCoord2fSGIS = ( void * ) qwglGetProcAddress( "glMultiTexCoord2fARB" );
1357 			qglActiveTextureARB = ( void * ) qwglGetProcAddress( "glActiveTextureARB" );
1358 			qglClientActiveTextureARB = ( void * ) qwglGetProcAddress( "glClientActiveTextureARB" );
1359 			QGL_TEXTURE0 = GL_TEXTURE0_ARB;
1360 			QGL_TEXTURE1 = GL_TEXTURE1_ARB;
1361 		}
1362 		else
1363 		{
1364 			ri.Con_Printf( PRINT_ALL, "...ignoring GL_ARB_multitexture\n" );
1365 		}
1366 	}
1367 	else
1368 	{
1369 		ri.Con_Printf( PRINT_ALL, "...GL_ARB_multitexture not found\n" );
1370 	}
1371 
1372 	if ( strstr( gl_config.extensions_string, "GL_SGIS_multitexture" ) )
1373 	{
1374 		if ( qglActiveTextureARB )
1375 		{
1376 			ri.Con_Printf( PRINT_ALL, "...GL_SGIS_multitexture deprecated in favor of ARB_multitexture\n" );
1377 		}
1378 		else if ( gl_ext_multitexture->value )
1379 		{
1380 			ri.Con_Printf( PRINT_ALL, "...using GL_SGIS_multitexture\n" );
1381 			qglMTexCoord2fSGIS = ( void * ) qwglGetProcAddress( "glMTexCoord2fSGIS" );
1382 			qglSelectTextureSGIS = ( void * ) qwglGetProcAddress( "glSelectTextureSGIS" );
1383 			QGL_TEXTURE0 = GL_TEXTURE0_SGIS;
1384 			QGL_TEXTURE1 = GL_TEXTURE1_SGIS;
1385 		}
1386 		else
1387 		{
1388 			ri.Con_Printf( PRINT_ALL, "...ignoring GL_SGIS_multitexture\n" );
1389 		}
1390 	}
1391 	else
1392 	{
1393 		ri.Con_Printf( PRINT_ALL, "...GL_SGIS_multitexture not found\n" );
1394 	}
1395 
1396 	GL_SetDefaultState();
1397 
1398 	/*
1399 	** draw our stereo patterns
1400 	*/
1401 #if 0 // commented out until H3D pays us the money they owe us
1402 	GL_DrawStereoPattern();
1403 #endif
1404 
1405 	GL_InitImages ();
1406 	Mod_Init ();
1407 	R_InitParticleTexture ();
1408 	Draw_InitLocal ();
1409 
1410 	err = qglGetError();
1411 	if ( err != GL_NO_ERROR )
1412 		ri.Con_Printf (PRINT_ALL, "glGetError() = 0x%x\n", err);
1413 
1414 	return true;
1415 }
1416 
1417 /*
1418 ===============
1419 R_Shutdown
1420 ===============
1421 */
R_Shutdown(void)1422 void R_Shutdown (void)
1423 {
1424 	ri.Cmd_RemoveCommand ("modellist");
1425 	ri.Cmd_RemoveCommand ("screenshot");
1426 	ri.Cmd_RemoveCommand ("imagelist");
1427 	ri.Cmd_RemoveCommand ("gl_strings");
1428 
1429 	Mod_FreeAll ();
1430 
1431 	GL_ShutdownImages ();
1432 
1433 	/*
1434 	** shut down OS specific OpenGL stuff like contexts, etc.
1435 	*/
1436 	GLimp_Shutdown();
1437 
1438 	/*
1439 	** shutdown our QGL subsystem
1440 	*/
1441 	QGL_Shutdown();
1442 }
1443 
1444 
1445 
1446 /*
1447 @@@@@@@@@@@@@@@@@@@@@
1448 R_BeginFrame
1449 @@@@@@@@@@@@@@@@@@@@@
1450 */
1451 extern void UpdateHardwareGamma();
1452 
R_BeginFrame(float camera_separation)1453 void R_BeginFrame( float camera_separation )
1454 {
1455 
1456 	gl_state.camera_separation = camera_separation;
1457 
1458 	/*
1459 	** change modes if necessary
1460 	*/
1461 	if ( gl_mode->modified || vid_fullscreen->modified )
1462 	{	// FIXME: only restart if CDS is required
1463 		cvar_t	*ref;
1464 
1465 		ref = ri.Cvar_Get ("vid_ref", "gl", 0);
1466 		ref->modified = true;
1467 	}
1468 
1469 	if ( gl_log->modified )
1470 	{
1471 		GLimp_EnableLogging( gl_log->value );
1472 		gl_log->modified = false;
1473 	}
1474 
1475 	if ( gl_log->value )
1476 	{
1477 		GLimp_LogNewFrame();
1478 	}
1479 
1480 	/*
1481 	** update 3Dfx gamma -- it is expected that a user will do a vid_restart
1482 	** after tweaking this value
1483 	*/
1484 	if ( vid_gamma->modified )
1485 	{
1486 		vid_gamma->modified = false;
1487 
1488 		if ( gl_state.hwgamma ) {
1489 			UpdateHardwareGamma();
1490 		} else if ( gl_config.renderer & ( GL_RENDERER_VOODOO ) )
1491 		{
1492 			char envbuffer[1024];
1493 			float g;
1494 
1495 			g = 2.00 * ( 0.8 - ( vid_gamma->value - 0.5 ) ) + 1.0F;
1496 			Com_sprintf( envbuffer, sizeof(envbuffer), "SSTV2_GAMMA=%f", g );
1497 			putenv( envbuffer );
1498 			Com_sprintf( envbuffer, sizeof(envbuffer), "SST_GAMMA=%f", g );
1499 			putenv( envbuffer );
1500 		}
1501 	}
1502 
1503 	GLimp_BeginFrame( camera_separation );
1504 
1505 	/*
1506 	** go into 2D mode
1507 	*/
1508 	qglViewport (0,0, vid.width, vid.height);
1509 	qglMatrixMode(GL_PROJECTION);
1510     qglLoadIdentity ();
1511 	qglOrtho  (0, vid.width, vid.height, 0, -99999, 99999);
1512 	qglMatrixMode(GL_MODELVIEW);
1513     qglLoadIdentity ();
1514 	qglDisable (GL_DEPTH_TEST);
1515 	qglDisable (GL_CULL_FACE);
1516 	qglDisable (GL_BLEND);
1517 	qglEnable (GL_ALPHA_TEST);
1518 	qglColor4f (1,1,1,1);
1519 
1520 	/*
1521 	** draw buffer stuff
1522 	*/
1523 	if ( gl_drawbuffer->modified )
1524 	{
1525 		gl_drawbuffer->modified = false;
1526 
1527 		if ( gl_state.camera_separation == 0 || !gl_state.stereo_enabled )
1528 		{
1529 			if ( Q_stricmp( gl_drawbuffer->string, "GL_FRONT" ) == 0 )
1530 				qglDrawBuffer( GL_FRONT );
1531 			else
1532 				qglDrawBuffer( GL_BACK );
1533 		}
1534 	}
1535 
1536 	/*
1537 	** texturemode stuff
1538 	*/
1539 	if ( gl_texturemode->modified )
1540 	{
1541 		GL_TextureMode( gl_texturemode->string );
1542 		gl_texturemode->modified = false;
1543 	}
1544 
1545 	if ( gl_texturealphamode->modified )
1546 	{
1547 		GL_TextureAlphaMode( gl_texturealphamode->string );
1548 		gl_texturealphamode->modified = false;
1549 	}
1550 
1551 	if ( gl_texturesolidmode->modified )
1552 	{
1553 		GL_TextureSolidMode( gl_texturesolidmode->string );
1554 		gl_texturesolidmode->modified = false;
1555 	}
1556 
1557 	/*
1558 	** swapinterval stuff
1559 	*/
1560 	GL_UpdateSwapInterval();
1561 
1562 	//
1563 	// clear screen if desired
1564 	//
1565 	R_Clear ();
1566 }
1567 
1568 /*
1569 =============
1570 R_SetPalette
1571 =============
1572 */
1573 unsigned r_rawpalette[256];
1574 
R_SetPalette(const unsigned char * palette)1575 void R_SetPalette ( const unsigned char *palette)
1576 {
1577 	int		i;
1578 
1579 	byte *rp = ( byte * ) r_rawpalette;
1580 
1581 	if ( palette )
1582 	{
1583 		for ( i = 0; i < 256; i++ )
1584 		{
1585 			rp[i*4+0] = palette[i*3+0];
1586 			rp[i*4+1] = palette[i*3+1];
1587 			rp[i*4+2] = palette[i*3+2];
1588 			rp[i*4+3] = 0xff;
1589 		}
1590 	}
1591 	else
1592 	{
1593 		for ( i = 0; i < 256; i++ )
1594 		{
1595 			rp[i*4+0] = LittleLong(d_8to24table[i]) & 0xff;
1596 			rp[i*4+1] = ( LittleLong(d_8to24table[i]) >> 8 ) & 0xff;
1597 			rp[i*4+2] = ( LittleLong(d_8to24table[i]) >> 16 ) & 0xff;
1598 			rp[i*4+3] = 0xff;
1599 		}
1600 	}
1601 	GL_SetTexturePalette( r_rawpalette );
1602 
1603 	qglClearColor (0,0,0,0);
1604 	qglClear (GL_COLOR_BUFFER_BIT);
1605 	qglClearColor (1,0, 0.5 , 0.5);
1606 }
1607 
1608 /*
1609 ** R_DrawBeam
1610 */
R_DrawBeam(entity_t * e)1611 void R_DrawBeam( entity_t *e )
1612 {
1613 #define NUM_BEAM_SEGS 6
1614 
1615 	int	i;
1616 	float r, g, b;
1617 
1618 	vec3_t perpvec;
1619 	vec3_t direction, normalized_direction;
1620 	vec3_t	start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS];
1621 	vec3_t oldorigin, origin;
1622 
1623 	oldorigin[0] = e->oldorigin[0];
1624 	oldorigin[1] = e->oldorigin[1];
1625 	oldorigin[2] = e->oldorigin[2];
1626 
1627 	origin[0] = e->origin[0];
1628 	origin[1] = e->origin[1];
1629 	origin[2] = e->origin[2];
1630 
1631 	normalized_direction[0] = direction[0] = oldorigin[0] - origin[0];
1632 	normalized_direction[1] = direction[1] = oldorigin[1] - origin[1];
1633 	normalized_direction[2] = direction[2] = oldorigin[2] - origin[2];
1634 
1635 	if ( VectorNormalize( normalized_direction ) == 0 )
1636 		return;
1637 
1638 	PerpendicularVector( perpvec, normalized_direction );
1639 	VectorScale( perpvec, e->frame / 2, perpvec );
1640 
1641 	for ( i = 0; i < 6; i++ )
1642 	{
1643 		RotatePointAroundVector( start_points[i], normalized_direction, perpvec, (360.0/NUM_BEAM_SEGS)*i );
1644 		VectorAdd( start_points[i], origin, start_points[i] );
1645 		VectorAdd( start_points[i], direction, end_points[i] );
1646 	}
1647 
1648 	qglDisable( GL_TEXTURE_2D );
1649 	qglEnable( GL_BLEND );
1650 	qglDepthMask( GL_FALSE );
1651 
1652 	r = ( LittleLong(d_8to24table[e->skinnum & 0xFF]) ) & 0xFF;
1653 	g = ( LittleLong(d_8to24table[e->skinnum & 0xFF]) >> 8 ) & 0xFF;
1654 	b = ( LittleLong(d_8to24table[e->skinnum & 0xFF]) >> 16 ) & 0xFF;
1655 
1656 	r *= 1/255.0F;
1657 	g *= 1/255.0F;
1658 	b *= 1/255.0F;
1659 
1660 	qglColor4f( r, g, b, e->alpha );
1661 
1662 	qglBegin( GL_TRIANGLE_STRIP );
1663 	for ( i = 0; i < NUM_BEAM_SEGS; i++ )
1664 	{
1665 		qglVertex3fv( start_points[i] );
1666 		qglVertex3fv( end_points[i] );
1667 		qglVertex3fv( start_points[(i+1)%NUM_BEAM_SEGS] );
1668 		qglVertex3fv( end_points[(i+1)%NUM_BEAM_SEGS] );
1669 	}
1670 	qglEnd();
1671 
1672 	qglEnable( GL_TEXTURE_2D );
1673 	qglDisable( GL_BLEND );
1674 	qglDepthMask( GL_TRUE );
1675 }
1676 
1677 //===================================================================
1678 
1679 
1680 void	R_BeginRegistration (char *map);
1681 struct model_s	*R_RegisterModel (char *name);
1682 struct image_s	*R_RegisterSkin (char *name);
1683 void R_SetSky (char *name, float rotate, vec3_t axis);
1684 void	R_EndRegistration (void);
1685 
1686 void	R_RenderFrame (refdef_t *fd);
1687 
1688 struct image_s	*Draw_FindPic (char *name);
1689 
1690 void	Draw_Pic (int x, int y, char *name);
1691 void	Draw_Char (int x, int y, int c);
1692 void	Draw_TileClear (int x, int y, int w, int h, char *name);
1693 void	Draw_Fill (int x, int y, int w, int h, int c);
1694 void	Draw_FadeScreen (void);
1695 
1696 /*
1697 @@@@@@@@@@@@@@@@@@@@@
1698 GetRefAPI
1699 
1700 @@@@@@@@@@@@@@@@@@@@@
1701 */
GetRefAPI(refimport_t rimp)1702 refexport_t GetRefAPI (refimport_t rimp )
1703 {
1704 	refexport_t	re;
1705 
1706 	ri = rimp;
1707 
1708 	re.api_version = API_VERSION;
1709 
1710 	re.BeginRegistration = R_BeginRegistration;
1711 	re.RegisterModel = R_RegisterModel;
1712 	re.RegisterSkin = R_RegisterSkin;
1713 	re.RegisterPic = Draw_FindPic;
1714 	re.SetSky = R_SetSky;
1715 	re.EndRegistration = R_EndRegistration;
1716 
1717 	re.RenderFrame = R_RenderFrame;
1718 
1719 	re.DrawGetPicSize = Draw_GetPicSize;
1720 	re.DrawPic = Draw_Pic;
1721 	re.DrawStretchPic = Draw_StretchPic;
1722 	re.DrawChar = Draw_Char;
1723 	re.DrawTileClear = Draw_TileClear;
1724 	re.DrawFill = Draw_Fill;
1725 	re.DrawFadeScreen= Draw_FadeScreen;
1726 
1727 	re.DrawStretchRaw = Draw_StretchRaw;
1728 
1729 	re.Init = R_Init;
1730 	re.Shutdown = R_Shutdown;
1731 
1732 	re.CinematicSetPalette = R_SetPalette;
1733 	re.BeginFrame = R_BeginFrame;
1734 	re.EndFrame = GLimp_EndFrame;
1735 
1736 	re.AppActivate = GLimp_AppActivate;
1737 
1738 	Swap_Init ();
1739 
1740 	return re;
1741 }
1742 
1743 
1744 #ifndef REF_HARD_LINKED
1745 // this is only here so the functions in q_shared.c and q_shwin.c can link
Sys_Error(char * error,...)1746 void Sys_Error (char *error, ...)
1747 {
1748 	va_list		argptr;
1749 	char		text[1024];
1750 
1751 	va_start (argptr, error);
1752 	vsprintf (text, error, argptr);
1753 	va_end (argptr);
1754 
1755 	ri.Sys_Error (ERR_FATAL, "%s", text);
1756 }
1757 
Com_Printf(char * fmt,...)1758 void Com_Printf (char *fmt, ...)
1759 {
1760 	va_list		argptr;
1761 	char		text[1024];
1762 
1763 	va_start (argptr, fmt);
1764 	vsprintf (text, fmt, argptr);
1765 	va_end (argptr);
1766 
1767 	ri.Con_Printf (PRINT_ALL, "%s", text);
1768 }
1769 
1770 #endif
1771