1 /*
2 	vid_common_gl.c
3 
4 	Common OpenGL video driver functions
5 
6 	Copyright (C) 1996-1997 Id Software, Inc.
7 	Copyright (C) 2000      Marcus Sundberg [mackan@stacken.kth.se]
8 
9 	This program is free software; you can redistribute it and/or
10 	modify it under the terms of the GNU General Public License
11 	as published by the Free Software Foundation; either version 2
12 	of the License, or (at your option) any later version.
13 
14 	This program is distributed in the hope that it will be useful,
15 	but WITHOUT ANY WARRANTY; without even the implied warranty of
16 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 	See the GNU General Public License for more details.
19 
20 	You should have received a copy of the GNU General Public License
21 	along with this program; if not, write to:
22 
23 		Free Software Foundation, Inc.
24 		59 Temple Place - Suite 330
25 		Boston, MA  02111-1307, USA
26 
27 */
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31 
32 #ifdef HAVE_MATH_H
33 # include <math.h>
34 #endif
35 #ifdef HAVE_STRING_H
36 # include <string.h>
37 #endif
38 #ifdef HAVE_STRINGS_H
39 # include <strings.h>
40 #endif
41 
42 #include "QF/cvar.h"
43 #include "QF/input.h"
44 #include "QF/qargs.h"
45 #include "QF/quakefs.h"
46 #include "QF/sys.h"
47 #include "QF/va.h"
48 #include "QF/vid.h"
49 #include "QF/GL/defines.h"
50 #include "QF/GL/extensions.h"
51 #include "QF/GL/funcs.h"
52 #include "QF/GL/qf_vid.h"
53 
54 #include "compat.h"
55 #include "d_iface.h"
56 #include "r_internal.h"
57 #include "sbar.h"
58 
59 #define WARP_WIDTH              320
60 #define WARP_HEIGHT             200
61 
62 unsigned char	gl_15to8table[65536];
63 
64 QF_glActiveTexture			qglActiveTexture = NULL;
65 QF_glMultiTexCoord2f		qglMultiTexCoord2f = NULL;
66 QF_glMultiTexCoord2fv		qglMultiTexCoord2fv = NULL;
67 
68 const char		   *gl_extensions;
69 const char		   *gl_renderer;
70 const char		   *gl_vendor;
71 const char		   *gl_version;
72 
73 int					gl_major;
74 int					gl_minor;
75 int					gl_release_number;
76 
77 static int			gl_bgra_capable;
78 int					gl_use_bgra;
79 int					gl_va_capable;
80 static  int					driver_vaelements;
81 int					vaelements;
82 int         		gl_texture_number = 1;
83 int					gl_filter_min = GL_LINEAR_MIPMAP_LINEAR;
84 int					gl_filter_max = GL_LINEAR;
85 float       		gldepthmin, gldepthmax;
86 
87 // Multitexture
88 qboolean			gl_mtex_capable = false;
89 static int			gl_mtex_tmus = 0;
90 GLenum				gl_mtex_enum;
91 int					gl_mtex_active_tmus = 0;
92 qboolean			gl_mtex_fullbright = false;
93 
94 // Combine
95 qboolean			gl_combine_capable = false;
96 int					lm_src_blend, lm_dest_blend;
97 float				gl_rgb_scale = 1.0;
98 
99 QF_glColorTableEXT	qglColorTableEXT = NULL;
100 
101 qboolean			gl_feature_mach64 = false;
102 
103 // GL_EXT_texture_filter_anisotropic
104 qboolean 			gl_Anisotropy;
105 static float		aniso_max;
106 float				gl_aniso;
107 
108 // GL_ATI_pn_triangles
109 static qboolean		TruForm;
110 static int			tess_max;
111 int			gl_tess;
112 
113 // GL_LIGHT
114 int					gl_max_lights;
115 
116 cvar_t		*gl_anisotropy;
117 cvar_t		*gl_doublebright;
118 cvar_t      *gl_fb_bmodels;
119 cvar_t      *gl_finish;
120 cvar_t      *gl_max_size;
121 cvar_t      *gl_multitexture;
122 cvar_t		*gl_tessellate;
123 cvar_t		*gl_textures_bgra;
124 cvar_t      *gl_vaelements_max;
125 cvar_t      *gl_vector_light;
126 cvar_t      *gl_screenshot_byte_swap;
127 
128 cvar_t     *gl_affinemodels;
129 cvar_t     *gl_clear;
130 cvar_t     *gl_conspin;
131 cvar_t     *gl_constretch;
132 cvar_t     *gl_dlight_polyblend;
133 cvar_t     *gl_dlight_smooth;
134 cvar_t     *gl_driver;
135 cvar_t     *gl_fb_models;
136 cvar_t     *gl_keeptjunctions;
137 cvar_t     *gl_lerp_anim;
138 cvar_t     *gl_lightmap_align;
139 cvar_t     *gl_lightmap_subimage;
140 cvar_t     *gl_nocolors;
141 cvar_t	   *gl_overbright;
142 cvar_t     *gl_particle_mip;
143 cvar_t     *gl_particle_size;
144 cvar_t     *gl_picmip;
145 cvar_t     *gl_playermip;
146 cvar_t     *gl_reporttjunctions;
147 cvar_t     *gl_sky_clip;
148 cvar_t     *gl_sky_debug;
149 cvar_t     *gl_sky_multipass;
150 cvar_t     *gl_texsort;
151 cvar_t     *gl_triplebuffer;
152 static cvar_t *vid_use8bit;
153 
154 void gl_multitexture_f (cvar_t *var);
155 
156 
157 static void
gl_max_size_f(cvar_t * var)158 gl_max_size_f (cvar_t *var)
159 {
160 	GLint		texSize;
161 
162 	if (!var)
163 		return;
164 
165 	// Check driver's max texture size
166 	qfglGetIntegerv (GL_MAX_TEXTURE_SIZE, &texSize);
167 	if (var->int_val < 1) {
168 		Cvar_SetValue (var, texSize);
169 	} else {
170 		Cvar_SetValue (var, bound (1, var->int_val, texSize));
171 	}
172 }
173 
174 static void
gl_textures_bgra_f(cvar_t * var)175 gl_textures_bgra_f (cvar_t *var)
176 {
177 	if (!var)
178 		return;
179 
180 	if (var->int_val && gl_bgra_capable) {
181 		gl_use_bgra = 1;
182 	} else {
183 		gl_use_bgra = 0;
184 	}
185 }
186 
187 static void
gl_fb_bmodels_f(cvar_t * var)188 gl_fb_bmodels_f (cvar_t *var)
189 {
190 	if (!var)
191 		return;
192 
193 	if (var->int_val && gl_mtex_tmus >= 3) {
194 		gl_mtex_fullbright = true;
195 	} else {
196 		gl_mtex_fullbright = false;
197 	}
198 }
199 
200 void
gl_multitexture_f(cvar_t * var)201 gl_multitexture_f (cvar_t *var)
202 {
203 	if (!var)
204 		return;
205 
206 	if (var->int_val && gl_mtex_capable) {
207 		gl_mtex_active_tmus = gl_mtex_tmus;
208 
209 		if (gl_fb_bmodels) {
210 			if (gl_fb_bmodels->int_val) {
211 				if (gl_mtex_tmus >= 3) {
212 					gl_mtex_fullbright = true;
213 
214 					qglActiveTexture (gl_mtex_enum + 2);
215 					qfglEnable (GL_TEXTURE_2D);
216 					qfglTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
217 								 GL_DECAL);
218 					qfglDisable (GL_TEXTURE_2D);
219 				} else {
220 					gl_mtex_fullbright = false;
221 					Sys_MaskPrintf (SYS_VID,
222 									"Not enough TMUs for BSP fullbrights.\n");
223 				}
224 			}
225 		} else {
226 			gl_mtex_fullbright = false;
227 		}
228 
229 		// Lightmaps
230 		qglActiveTexture (gl_mtex_enum + 1);
231 		qfglEnable (GL_TEXTURE_2D);
232 		if (gl_overbright) {
233 			if (gl_combine_capable && gl_overbright->int_val) {
234 				qfglTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
235 				qfglTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
236 				qfglTexEnvf (GL_TEXTURE_ENV, GL_RGB_SCALE, gl_rgb_scale);
237 			} else {
238 				qfglTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
239 			}
240 		} else {
241 			qfglTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
242 		}
243 		qfglDisable (GL_TEXTURE_2D);
244 
245 		// Base Texture
246 		qglActiveTexture (gl_mtex_enum + 0);
247 	} else {
248 		gl_mtex_active_tmus = 0;
249 		gl_mtex_fullbright = false;
250 	}
251 }
252 
253 static void
gl_screenshot_byte_swap_f(cvar_t * var)254 gl_screenshot_byte_swap_f (cvar_t *var)
255 {
256 	if (var)
257 		qfglPixelStorei (GL_PACK_SWAP_BYTES,
258 						 var->int_val ? GL_TRUE : GL_FALSE);
259 }
260 
261 static void
gl_anisotropy_f(cvar_t * var)262 gl_anisotropy_f (cvar_t * var)
263 {
264 	if (gl_Anisotropy) {
265 		if (var)
266 			gl_aniso = (bound (1.0, var->value, aniso_max));
267 		else
268 			gl_aniso = 1.0;
269 	} else {
270 		gl_aniso = 1.0;
271 		if (var)
272 			Sys_MaskPrintf (SYS_VID,
273 							"Anisotropy (GL_EXT_texture_filter_anisotropic) "
274 							"is not supported by your hardware and/or "
275 							"drivers.\n");
276 	}
277 }
278 
279 static void
gl_tessellate_f(cvar_t * var)280 gl_tessellate_f (cvar_t * var)
281 {
282 	if (TruForm) {
283 		if (var)
284 			gl_tess = (bound (0, var->int_val, tess_max));
285 		else
286 			gl_tess = 0;
287 		qfglPNTrianglesiATI (GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI, gl_tess);
288 	} else {
289 		gl_tess = 0;
290 		if (var)
291 			Sys_MaskPrintf (SYS_VID,
292 							"TruForm (GL_ATI_pn_triangles) is not supported "
293 							"by your hardware and/or drivers.\n");
294 	}
295 }
296 
297 static void
gl_vaelements_max_f(cvar_t * var)298 gl_vaelements_max_f (cvar_t *var)
299 {
300 	if (var->int_val)
301 		vaelements = min (var->int_val, driver_vaelements);
302 	else
303 		vaelements = driver_vaelements;
304 }
305 
306 static void
GL_Common_Init_Cvars(void)307 GL_Common_Init_Cvars (void)
308 {
309 	vid_use8bit = Cvar_Get ("vid_use8bit", "0", CVAR_ROM, NULL,	"Use 8-bit "
310 							"shared palettes.");
311 	gl_textures_bgra = Cvar_Get ("gl_textures_bgra", "0", CVAR_ROM,
312 								 gl_textures_bgra_f, "If set to 1, try to use "
313 								 "BGR & BGRA textures instead of RGB & RGBA.");
314 	gl_fb_bmodels = Cvar_Get ("gl_fb_bmodels", "1", CVAR_ARCHIVE,
315 							  gl_fb_bmodels_f, "Toggles fullbright color "
316 							  "support for bmodels");
317 	gl_finish = Cvar_Get ("gl_finish", "1", CVAR_ARCHIVE, NULL,
318 							"wait for rendering to finish");
319 	gl_max_size = Cvar_Get ("gl_max_size", "0", CVAR_NONE, gl_max_size_f,
320 							"Texture dimension");
321 	gl_multitexture = Cvar_Get ("gl_multitexture", "1", CVAR_ARCHIVE,
322 								gl_multitexture_f, "Use multitexture when "
323 								"available.");
324 	gl_screenshot_byte_swap =
325 		Cvar_Get ("gl_screenshot_byte_swap", "0", CVAR_NONE,
326 				  gl_screenshot_byte_swap_f, "Swap the bytes for gl "
327 				  "screenshots. Needed if you get screenshots with red and "
328 				  "blue swapped.");
329 	gl_anisotropy =
330 		Cvar_Get ("gl_anisotropy", "1.0", CVAR_NONE, gl_anisotropy_f,
331 				  nva ("Specifies degree of anisotropy, from 1.0 to %f. "
332 					   "Higher anisotropy means less distortion of textures "
333 					   "at shallow angles to the viewer.", aniso_max));
334 	gl_tessellate =
335 		Cvar_Get ("gl_tessellate", "0", CVAR_NONE, gl_tessellate_f,
336 				  nva ("Specifies tessellation level from 0 to %i. Higher "
337 					   "tessellation level means more triangles.", tess_max));
338 	gl_vaelements_max = Cvar_Get ("gl_vaelements_max", "0", CVAR_ROM,
339 								  gl_vaelements_max_f,
340 								  "Limit the vertex array size for buggy "
341 								  "drivers. 0 (default) uses driver provided "
342 								  "limit, -1 disables use of vertex arrays.");
343 	gl_vector_light = Cvar_Get ("gl_vector_light", "1", CVAR_NONE, NULL,
344 						"Enable use of GL vector lighting. 0 = flat lighting.");
345 	gl_affinemodels = Cvar_Get ("gl_affinemodels", "0", CVAR_ARCHIVE, NULL,
346 								"Makes texture rendering quality better if "
347 								"set to 1");
348 	gl_clear = Cvar_Get ("gl_clear", "0", CVAR_NONE, NULL, "Set to 1 to make "
349 						 "background black. Useful for removing HOM effect");
350 	gl_conspin = Cvar_Get ("gl_conspin", "0", CVAR_ARCHIVE, NULL,
351 						   "speed at which the console spins");
352 	gl_constretch = Cvar_Get ("gl_constretch", "0", CVAR_ARCHIVE, NULL,
353 							  "toggle console between slide and stretch");
354 	gl_dlight_polyblend = Cvar_Get ("gl_dlight_polyblend", "0", CVAR_ARCHIVE,
355 									NULL, "Set to 1 to use a dynamic light "
356 									"effect faster on GL");
357 	gl_dlight_smooth = Cvar_Get ("gl_dlight_smooth", "1", CVAR_ARCHIVE, NULL,
358 								 "Smooth dynamic vertex lighting");
359 	gl_fb_models = Cvar_Get ("gl_fb_models", "1", CVAR_ARCHIVE, NULL,
360 							 "Toggles fullbright color support for models");
361 	gl_keeptjunctions = Cvar_Get ("gl_keeptjunctions", "1", CVAR_ARCHIVE, NULL,
362 								  "Set to 0 to turn off colinear vertexes "
363 								  "upon level load.");
364 	gl_lerp_anim = Cvar_Get ("gl_lerp_anim", "1", CVAR_ARCHIVE, NULL,
365 							 "Toggles model animation interpolation");
366 
367 	gl_lightmap_align = Cvar_Get ("gl_lightmap_align", "1", CVAR_NONE, NULL,
368 								  "Workaround for nvidia slow path. Set to 4 "
369 								  "or 16 if you have an nvidia 3d "
370 								  "accelerator, set to 1 otherwise.");
371 	gl_lightmap_subimage = Cvar_Get ("gl_lightmap_subimage", "1", CVAR_NONE,
372 									 NULL, "Lightmap Update method. Default 2 "
373 									 "updates a minimum 'dirty rectangle' "
374 									 "around the area changed. 1 updates "
375 									 "every line that changed. 0 updates the "
376 									 "entire lightmap.");
377 	gl_nocolors = Cvar_Get ("gl_nocolors", "0", CVAR_NONE, NULL,
378 							"Set to 1, turns off all player colors");
379 	gl_overbright = Cvar_Get ("gl_overbright", "0", CVAR_NONE,
380 							  gl_overbright_f, "Darken lightmaps so that "
381 							  "dynamic lights can be overbright. 1 = 0.75 "
382 							  "brightness, 2 = 0.5 brightness.");
383 	gl_particle_mip = Cvar_Get ("gl_particle_mip", "0", CVAR_NONE, NULL,
384 								"Toggles particle texture mipmapping.");
385 	gl_particle_size = Cvar_Get ("gl_particle_size", "5", CVAR_NONE, NULL,
386 								 "Vertical and horizontal size of particle "
387 								 "textures as a power of 2. Default is 5 "
388 								 "(32 texel square).");
389 	gl_picmip = Cvar_Get ("gl_picmip", "0", CVAR_NONE, NULL, "Dimensions of "
390 						  "textures. 0 is normal, 1 is half, 2 is 1/4");
391 	gl_playermip = Cvar_Get ("gl_playermip", "0", CVAR_NONE, NULL,
392 							 "Detail of player skins. 0 best, 4 worst.");
393 	gl_reporttjunctions = Cvar_Get ("gl_reporttjunctions", "0", CVAR_NONE,
394 									NULL, "None");
395 	gl_sky_clip = Cvar_Get ("gl_sky_clip", "2", CVAR_ARCHIVE, NULL,
396 							"controls amount of sky overdraw");
397 	gl_sky_debug = Cvar_Get ("gl_sky_debug", "0", CVAR_NONE, NULL,
398 							 "debugging `info' for sky clipping");
399 	gl_sky_divide = Cvar_Get ("gl_sky_divide", "1", CVAR_ARCHIVE, NULL,
400 							  "subdivide sky polys");
401 	gl_sky_multipass = Cvar_Get ("gl_sky_multipass", "1", CVAR_ARCHIVE, NULL,
402 								"controls whether the skydome is single or "
403 								"double pass");
404 	gl_texsort = Cvar_Get ("gl_texsort", "1", CVAR_NONE, NULL, "None");
405 	gl_triplebuffer = Cvar_Get ("gl_triplebuffer", "1", CVAR_ARCHIVE, NULL,
406 								"Set to 1 by default. Fixes status bar "
407 								"flicker on some hardware");
408 }
409 
410 static void
CheckGLVersionString(void)411 CheckGLVersionString (void)
412 {
413 	gl_version = (char *) qfglGetString (GL_VERSION);
414 	if (sscanf (gl_version, "%d.%d", &gl_major, &gl_minor) == 2) {
415 		gl_release_number = 0;
416 		if (gl_major >= 1) {
417 			if (gl_minor >= 1) {
418 				gl_va_capable = true;
419 			} else {
420 				gl_va_capable = false;
421 			}
422 		}
423 	} else if (sscanf (gl_version, "%d.%d.%d", &gl_major, &gl_minor,
424 					   &gl_release_number) == 3) {
425 		if (gl_major >= 1) {
426 			if (gl_minor >= 1) {
427 				gl_va_capable = true;
428 			} else {
429 				gl_va_capable = false;
430 			}
431 		}
432 	} else {
433 		Sys_Error ("Malformed OpenGL version string!");
434 	}
435 	Sys_MaskPrintf (SYS_VID, "GL_VERSION: %s\n", gl_version);
436 
437 	gl_vendor = (char *) qfglGetString (GL_VENDOR);
438 	Sys_MaskPrintf (SYS_VID, "GL_VENDOR: %s\n", gl_vendor);
439 	gl_renderer = (char *) qfglGetString (GL_RENDERER);
440 	Sys_MaskPrintf (SYS_VID, "GL_RENDERER: %s\n", gl_renderer);
441 	gl_extensions = (char *) qfglGetString (GL_EXTENSIONS);
442 	Sys_MaskPrintf (SYS_VID, "GL_EXTENSIONS: %s\n", gl_extensions);
443 
444 	if (strstr (gl_renderer, "Mesa DRI Mach64"))
445 		gl_feature_mach64 = true;
446 }
447 
448 static void
CheckAnisotropyExtensions(void)449 CheckAnisotropyExtensions (void)
450 {
451 	if (QFGL_ExtensionPresent ("GL_EXT_texture_filter_anisotropic")) {
452 		gl_Anisotropy = true;
453 		qfglGetFloatv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &aniso_max);
454 	} else {
455 		gl_Anisotropy = false;
456 		aniso_max = 1.0;
457 	}
458 }
459 
460 static void
CheckBGRAExtensions(void)461 CheckBGRAExtensions (void)
462 {
463 	if (gl_major > 1 || (gl_major == 1 && gl_minor >= 3)) {
464 		gl_bgra_capable = true;
465 	} else if (QFGL_ExtensionPresent ("GL_EXT_bgra")) {
466 		gl_bgra_capable = true;
467 	} else {
468 		gl_bgra_capable = false;
469 	}
470 }
471 
472 static void
CheckCombineExtensions(void)473 CheckCombineExtensions (void)
474 {
475 	if (gl_major >= 1 && gl_minor >= 3) {
476 		gl_combine_capable = true;
477 		Sys_MaskPrintf (SYS_VID, "COMBINE active, multitextured doublebright "
478 						"enabled.\n");
479 	} else if (QFGL_ExtensionPresent ("GL_ARB_texture_env_combine")) {
480 		gl_combine_capable = true;
481 		Sys_MaskPrintf (SYS_VID, "COMBINE_ARB active, multitextured "
482 						"doublebright enabled.\n");
483 	} else {
484 		gl_combine_capable = false;
485 		Sys_MaskPrintf (SYS_VID, "GL_ARB_texture_env_combine not found. "
486 						"gl_doublebright will have no effect with "
487 						"gl_multitexture on.\n");
488 	}
489 }
490 
491 /*
492 	CheckMultiTextureExtensions
493 
494 	Check for ARB multitexture support
495 */
496 static void
CheckMultiTextureExtensions(void)497 CheckMultiTextureExtensions (void)
498 {
499 	Sys_MaskPrintf (SYS_VID, "Checking for multitexture: ");
500 	if (COM_CheckParm ("-nomtex")) {
501 		Sys_MaskPrintf (SYS_VID, "disabled.\n");
502 		return;
503 	}
504 	if (gl_major >= 1 && gl_minor >= 3) {
505 		qfglGetIntegerv (GL_MAX_TEXTURE_UNITS, &gl_mtex_tmus);
506 		if (gl_mtex_tmus >= 2) {
507 			Sys_MaskPrintf (SYS_VID, "enabled, %d TMUs.\n", gl_mtex_tmus);
508 			qglMultiTexCoord2f =
509 				QFGL_ExtensionAddress ("glMultiTexCoord2f");
510 			qglMultiTexCoord2fv =
511 				QFGL_ExtensionAddress ("glMultiTexCoord2fv");
512 			qglActiveTexture = QFGL_ExtensionAddress ("glActiveTexture");
513 			gl_mtex_enum = GL_TEXTURE0;
514 			if (qglMultiTexCoord2f && gl_mtex_enum)
515 				gl_mtex_capable = true;
516 			else
517 				Sys_MaskPrintf (SYS_VID, "Multitexture disabled, could not "
518 								"find required functions\n");
519 		} else {
520 			Sys_MaskPrintf (SYS_VID,
521 							"Multitexture disabled, not enough TMUs.\n");
522 		}
523 	} else if (QFGL_ExtensionPresent ("GL_ARB_multitexture")) {
524 		qfglGetIntegerv (GL_MAX_TEXTURE_UNITS_ARB, &gl_mtex_tmus);
525 		if (gl_mtex_tmus >= 2) {
526 			Sys_MaskPrintf (SYS_VID, "enabled, %d TMUs.\n", gl_mtex_tmus);
527 			qglMultiTexCoord2f =
528 				QFGL_ExtensionAddress ("glMultiTexCoord2fARB");
529 			qglMultiTexCoord2fv =
530 				QFGL_ExtensionAddress ("glMultiTexCoord2fvARB");
531 			qglActiveTexture = QFGL_ExtensionAddress ("glActiveTextureARB");
532 			gl_mtex_enum = GL_TEXTURE0_ARB;
533 			if (qglMultiTexCoord2f && gl_mtex_enum)
534 				gl_mtex_capable = true;
535 			else
536 				Sys_MaskPrintf (SYS_VID, "Multitexture disabled, could not "
537 								"find required functions\n");
538 		} else {
539 			Sys_MaskPrintf (SYS_VID,
540 							"Multitexture disabled, not enough TMUs.\n");
541 		}
542 	} else {
543 		Sys_MaskPrintf (SYS_VID, "not found.\n");
544 	}
545 }
546 
547 static void
CheckTruFormExtensions(void)548 CheckTruFormExtensions (void)
549 {
550 	if (QFGL_ExtensionPresent ("GL_ATI_pn_triangles")) {
551 		TruForm = true;
552 		qfglGetIntegerv (GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI,
553 						 &tess_max);
554 		qfglPNTrianglesiATI (GL_PN_TRIANGLES_NORMAL_MODE_ATI,
555 							 GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI);
556 		qfglPNTrianglesiATI (GL_PN_TRIANGLES_POINT_MODE_ATI,
557 							 GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI);
558 	} else {
559 		TruForm = false;
560 		gl_tess = 0;
561 		tess_max = 0;
562 	}
563 }
564 
565 static void
CheckVertexArraySize(void)566 CheckVertexArraySize (void)
567 {
568 	qfglGetIntegerv (GL_MAX_ELEMENTS_VERTICES, &driver_vaelements);
569 	if (driver_vaelements > 65536)
570 		driver_vaelements = 65536;
571 	vaelements = driver_vaelements;
572 //	qfglGetIntegerv (MAX_ELEMENTS_INDICES, *vaindices);
573 }
574 
575 static void
CheckLights(void)576 CheckLights (void)
577 {
578 	int		i;
579 	float	dark[4] = {0.0, 0.0, 0.0, 1.0},
580 			ambient[4] = {0.2, 0.2, 0.2, 1.0},
581 			diffuse[4] = {0.7, 0.7, 0.7, 1.0},
582 			specular[4] = {0.1, 0.1, 0.1, 1.0};
583 
584 	qfglGetIntegerv (GL_MAX_LIGHTS, &gl_max_lights);
585 	Sys_MaskPrintf (SYS_VID, "Max GL Lights %d.\n", gl_max_lights);
586 
587 	qfglEnable (GL_LIGHTING);
588 	qfglLightModelfv (GL_LIGHT_MODEL_AMBIENT, dark);
589 	qfglLightModelf (GL_LIGHT_MODEL_TWO_SIDE, 0.0);
590 
591 	for (i = 0; i < gl_max_lights; i++) {
592 		qfglEnable (GL_LIGHT0 + i);
593 		qfglLightf (GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, 0.5);
594 		qfglDisable (GL_LIGHT0 + i);
595 	}
596 
597 	// Set up material defaults
598 	qfglMaterialfv (GL_FRONT, GL_AMBIENT, ambient);
599 	qfglMaterialfv (GL_FRONT, GL_DIFFUSE, diffuse);
600 	qfglMaterialfv (GL_FRONT, GL_SPECULAR, specular);
601 	qfglMaterialf (GL_FRONT, GL_SHININESS, 1.0);
602 
603 	qfglDisable (GL_LIGHTING);
604 }
605 
606 static void
Tdfx_Init8bitPalette(void)607 Tdfx_Init8bitPalette (void)
608 {
609 	// Check for 8bit Extensions and initialize them.
610 	int         i;
611 
612 	if (vr_data.vid->is8bit)
613 		return;
614 
615 	if (QFGL_ExtensionPresent ("3DFX_set_global_palette")) {
616 		char       *oldpal;
617 		GLubyte     table[256][4];
618 		QF_gl3DfxSetPaletteEXT qgl3DfxSetPaletteEXT = NULL;
619 
620 		if (!(qgl3DfxSetPaletteEXT =
621 			  QFGL_ExtensionAddress ("gl3DfxSetPaletteEXT"))) {
622 			Sys_MaskPrintf (SYS_VID, "3DFX_set_global_palette not found.\n");
623 			return;
624 		}
625 
626 		Sys_MaskPrintf (SYS_VID, "3DFX_set_global_palette.\n");
627 
628 		oldpal = (char *) d_8to24table;	// d_8to24table3dfx;
629 		for (i = 0; i < 256; i++) {
630 			table[i][2] = *oldpal++;
631 			table[i][1] = *oldpal++;
632 			table[i][0] = *oldpal++;
633 			table[i][3] = 255;
634 			oldpal++;
635 		}
636 		qfglEnable (GL_SHARED_TEXTURE_PALETTE_EXT);
637 		qgl3DfxSetPaletteEXT ((GLuint *) table);
638 		vr_data.vid->is8bit = true;
639 	} else {
640 		Sys_MaskPrintf (SYS_VID, "\n    3DFX_set_global_palette not found.");
641 	}
642 }
643 
644 /*
645   The GL_EXT_shared_texture_palette seems like an idea which is
646   /almost/ a good idea, but seems to be severely broken with many
647   drivers, as such it is disabled.
648 
649   It should be noted, that a palette object extension as suggested by
650   the GL_EXT_shared_texture_palette spec might be a very good idea in
651   general.
652 */
653 static void
Shared_Init8bitPalette(void)654 Shared_Init8bitPalette (void)
655 {
656 	int 		i;
657 	GLubyte 	thePalette[256 * 3];
658 	GLubyte 	*oldPalette, *newPalette;
659 
660 	if (vr_data.vid->is8bit)
661 		return;
662 
663 	if (QFGL_ExtensionPresent ("GL_EXT_shared_texture_palette")) {
664 		if (!(qglColorTableEXT = QFGL_ExtensionAddress ("glColorTableEXT"))) {
665 			Sys_MaskPrintf (SYS_VID, "glColorTableEXT not found.\n");
666 			return;
667 		}
668 
669 		Sys_MaskPrintf (SYS_VID, "GL_EXT_shared_texture_palette\n");
670 
671 		qfglEnable (GL_SHARED_TEXTURE_PALETTE_EXT);
672 		oldPalette = (GLubyte *) d_8to24table;	// d_8to24table3dfx;
673 		newPalette = thePalette;
674 		for (i = 0; i < 256; i++) {
675 			*newPalette++ = *oldPalette++;
676 			*newPalette++ = *oldPalette++;
677 			*newPalette++ = *oldPalette++;
678 			oldPalette++;
679 		}
680 		qglColorTableEXT (GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB,
681 							GL_UNSIGNED_BYTE, (GLvoid *) thePalette);
682 		vr_data.vid->is8bit = true;
683 	} else {
684 		Sys_MaskPrintf (SYS_VID,
685 						"\n    GL_EXT_shared_texture_palette not found.");
686 	}
687 }
688 
689 static void
VID_Init8bitPalette(void)690 VID_Init8bitPalette (void)
691 {
692 	Sys_MaskPrintf (SYS_VID, "Checking for 8-bit extension: ");
693 	if (vid_use8bit->int_val) {
694 		Tdfx_Init8bitPalette ();
695 		Shared_Init8bitPalette ();
696 		if (!vr_data.vid->is8bit)
697 			Sys_MaskPrintf (SYS_VID, "\n  8-bit extension not found.\n");
698 	} else {
699 		Sys_MaskPrintf (SYS_VID, "disabled.\n");
700 	}
701 }
702 
703 void
GL_SetPalette(const byte * palette)704 GL_SetPalette (const byte *palette)
705 {
706 	const byte *pal;
707 	char        s[255];
708 	float       dist, bestdist;
709 	int			r1, g1, b1, k;
710 	unsigned int r, g, b, v;
711 	unsigned short i;
712 	unsigned int *table;
713 	static qboolean palflag = false;
714 	QFile      *f;
715 	static int  inited_8 = 0;
716 
717 	if (!inited_8) {
718 		inited_8 = 1;
719 		// Check for 8-bit extension and initialize if present
720 		VID_Init8bitPalette ();
721 	}
722 	// 8 8 8 encoding
723 	Sys_MaskPrintf (SYS_VID, "Converting 8to24\n");
724 
725 	pal = palette;
726 	table = d_8to24table;
727 	for (i = 0; i < 255; i++) { // used to be i<256, see d_8to24table below
728 		r = pal[0];
729 		g = pal[1];
730 		b = pal[2];
731 		pal += 3;
732 
733 #ifdef WORDS_BIGENDIAN
734 		v = (255 << 0) + (r << 24) + (g << 16) + (b << 8);
735 #else
736 		v = (255 << 24) + (r << 0) + (g << 8) + (b << 16);
737 #endif
738 		*table++ = v;
739 	}
740 	d_8to24table[255] = 0;	// 255 is transparent
741 
742 	// JACK: 3D distance calcs - k is last closest, l is the distance.
743 	if (palflag)
744 		return;
745 	palflag = true;
746 
747 	QFS_FOpenFile ("glquake/15to8.pal", &f);
748 	if (f) {
749 		Qread (f, gl_15to8table, 1 << 15);
750 		Qclose (f);
751 	} else {
752 		for (i = 0; i < (1 << 15); i++) {
753 			/* Maps
754 			   000000000000000
755 			   000000000011111 = Red  = 0x001F
756 			   000001111100000 = Blue = 0x03E0
757 			   111110000000000 = Grn  = 0x7C00
758 			*/
759 			r = ((i & 0x1F) << 3) + 4;
760 			g = ((i & 0x03E0) >> 2) + 4;
761 			b = ((i & 0x7C00) >> 7) + 4;
762 
763 			pal = (unsigned char *) d_8to24table;
764 
765 			for (v = 0, k = 0, bestdist = 10000.0; v < 256; v++, pal += 4) {
766 				r1 = (int) r - (int) pal[0];
767 				g1 = (int) g - (int) pal[1];
768 				b1 = (int) b - (int) pal[2];
769 				dist = sqrt (((r1 * r1) + (g1 * g1) + (b1 * b1)));
770 				if (dist < bestdist) {
771 					k = v;
772 					bestdist = dist;
773 				}
774 			}
775 			gl_15to8table[i] = k;
776 		}
777 		snprintf (s, sizeof (s), "%s/glquake/15to8.pal", qfs_gamedir->dir.def);
778 		if ((f = QFS_WOpen (s, 0)) != NULL) {
779 			Qwrite (f, gl_15to8table, 1 << 15);
780 			Qclose (f);
781 		}
782 	}
783 }
784 
785 void
GL_Init_Common(void)786 GL_Init_Common (void)
787 {
788 	GLF_FindFunctions ();
789 	CheckGLVersionString ();
790 
791 	CheckAnisotropyExtensions ();
792 	CheckMultiTextureExtensions ();
793 	CheckCombineExtensions ();
794 	CheckBGRAExtensions ();
795 	CheckTruFormExtensions ();
796 	CheckVertexArraySize ();
797 	CheckLights ();
798 
799 	GL_Common_Init_Cvars ();
800 
801 	qfglClearColor (0, 0, 0, 0);
802 
803 	qfglEnable (GL_TEXTURE_2D);
804 	qfglFrontFace (GL_CW);
805 	qfglCullFace (GL_BACK);
806 	qfglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
807 	qfglShadeModel (GL_FLAT);
808 
809 	qfglEnable (GL_BLEND);
810 	qfglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
811 
812 	qfglTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
813 	qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
814 	qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
815 	if (gl_Anisotropy)
816 		qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
817 						   gl_aniso);
818 	qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
819 	qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
820 }
821