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