1 /* Emacs style mode select   -*- C++ -*-
2  *-----------------------------------------------------------------------------
3  *
4  *
5  *  PrBoom: a Doom port merged with LxDoom and LSDLDoom
6  *  based on BOOM, a modified and improved DOOM engine
7  *  Copyright (C) 1999 by
8  *  id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9  *  Copyright (C) 1999-2000 by
10  *  Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11  *  Copyright 2005, 2006 by
12  *  Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13  *
14  *  This program is free software; you can redistribute it and/or
15  *  modify it under the terms of the GNU General Public License
16  *  as published by the Free Software Foundation; either version 2
17  *  of the License, or (at your option) any later version.
18  *
19  *  This program is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *  GNU General Public License for more details.
23  *
24  *  You should have received a copy of the GNU General Public License
25  *  along with this program; if not, write to the Free Software
26  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27  *  02111-1307, USA.
28  *
29  * DESCRIPTION:
30  *   Thanks Roman "Vortex" Marchenko
31  *---------------------------------------------------------------------
32  */
33 
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37 
38 #include <stdio.h>
39 
40 #include <SDL.h>
41 #include "gl_opengl.h"
42 
43 #include "doomtype.h"
44 #include "lprintf.h"
45 
46 #define isExtensionSupported(ext) strstr(extensions, ext)
47 
48 int gl_version;
49 
50 static dboolean gl_compatibility_mode;
51 
52 int GLEXT_CLAMP_TO_EDGE = GL_CLAMP;
53 int gl_max_texture_size = 0;
54 
55 // obsolete?
56 int gl_use_paletted_texture = 0;
57 int gl_use_shared_texture_palette = 0;
58 int gl_paletted_texture = 0;
59 int gl_shared_texture_palette = 0;
60 
61 dboolean gl_ext_texture_filter_anisotropic = false;
62 dboolean gl_arb_texture_non_power_of_two = false;
63 dboolean gl_arb_multitexture = false;
64 dboolean gl_arb_texture_compression = false;
65 dboolean gl_ext_framebuffer_object = false;
66 dboolean gl_ext_packed_depth_stencil = false;
67 dboolean gl_ext_blend_color = false;
68 dboolean gl_use_stencil = false;
69 dboolean gl_ext_arb_vertex_buffer_object = false;
70 dboolean gl_arb_pixel_buffer_object = false;
71 
72 // cfg values
73 int gl_ext_texture_filter_anisotropic_default;
74 int gl_arb_texture_non_power_of_two_default;
75 int gl_arb_multitexture_default;
76 int gl_arb_texture_compression_default;
77 int gl_ext_framebuffer_object_default;
78 int gl_ext_packed_depth_stencil_default;
79 int gl_ext_blend_color_default;
80 int gl_use_stencil_default;
81 int gl_ext_arb_vertex_buffer_object_default;
82 int gl_arb_pixel_buffer_object_default;
83 
84 int active_texture_enabled[32];
85 int clieant_active_texture_enabled[32];
86 
87 // obsolete?
88 PFNGLCOLORTABLEEXTPROC              GLEXT_glColorTableEXT              = NULL;
89 
90 /* EXT_framebuffer_object */
91 PFNGLBINDFRAMEBUFFEREXTPROC         GLEXT_glBindFramebufferEXT         = NULL;
92 PFNGLGENFRAMEBUFFERSEXTPROC         GLEXT_glGenFramebuffersEXT         = NULL;
93 PFNGLGENRENDERBUFFERSEXTPROC        GLEXT_glGenRenderbuffersEXT        = NULL;
94 PFNGLBINDRENDERBUFFEREXTPROC        GLEXT_glBindRenderbufferEXT        = NULL;
95 PFNGLRENDERBUFFERSTORAGEEXTPROC     GLEXT_glRenderbufferStorageEXT     = NULL;
96 PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC GLEXT_glFramebufferRenderbufferEXT = NULL;
97 PFNGLFRAMEBUFFERTEXTURE2DEXTPROC    GLEXT_glFramebufferTexture2DEXT    = NULL;
98 PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC  GLEXT_glCheckFramebufferStatusEXT  = NULL;
99 PFNGLDELETEFRAMEBUFFERSEXTPROC      GLEXT_glDeleteFramebuffersEXT      = NULL;
100 PFNGLDELETERENDERBUFFERSEXTPROC     GLEXT_glDeleteRenderbuffersEXT     = NULL;
101 
102 /* ARB_multitexture command function pointers */
103 PFNGLACTIVETEXTUREARBPROC        GLEXT_glActiveTextureARB              = NULL;
104 PFNGLCLIENTACTIVETEXTUREARBPROC  GLEXT_glClientActiveTextureARB        = NULL;
105 PFNGLMULTITEXCOORD2FARBPROC      GLEXT_glMultiTexCoord2fARB            = NULL;
106 PFNGLMULTITEXCOORD2FVARBPROC     GLEXT_glMultiTexCoord2fvARB           = NULL;
107 
108 /* ARB_texture_compression */
109 PFNGLCOMPRESSEDTEXIMAGE2DARBPROC GLEXT_glCompressedTexImage2DARB       = NULL;
110 
111 PFNGLBLENDCOLOREXTPROC              GLEXT_glBlendColorEXT              = NULL;
112 
113 /* VBO */
114 PFNGLGENBUFFERSARBPROC              GLEXT_glGenBuffersARB              = NULL;
115 PFNGLDELETEBUFFERSARBPROC           GLEXT_glDeleteBuffersARB           = NULL;
116 PFNGLBINDBUFFERARBPROC              GLEXT_glBindBufferARB              = NULL;
117 PFNGLBUFFERDATAARBPROC              GLEXT_glBufferDataARB              = NULL;
118 
119 /* PBO */
120 PFNGLBUFFERSUBDATAARBPROC           GLEXT_glBufferSubDataARB           = NULL;
121 PFNGLGETBUFFERPARAMETERIVARBPROC    GLEXT_glGetBufferParameterivARB    = NULL;
122 PFNGLMAPBUFFERARBPROC               GLEXT_glMapBufferARB               = NULL;
123 PFNGLUNMAPBUFFERARBPROC             GLEXT_glUnmapBufferARB             = NULL;
124 
125 
gld_InitOpenGLVersion(void)126 void gld_InitOpenGLVersion(void)
127 {
128   int MajorVersion, MinorVersion;
129   gl_version = OPENGL_VERSION_1_0;
130   if (sscanf((const char*)glGetString(GL_VERSION), "%d.%d", &MajorVersion, &MinorVersion) == 2)
131   {
132     if (MajorVersion > 1)
133     {
134       gl_version = OPENGL_VERSION_2_0;
135       if (MinorVersion > 0) gl_version = OPENGL_VERSION_2_1;
136     }
137     else
138     {
139       gl_version = OPENGL_VERSION_1_0;
140       if (MinorVersion > 0) gl_version = OPENGL_VERSION_1_1;
141       if (MinorVersion > 1) gl_version = OPENGL_VERSION_1_2;
142       if (MinorVersion > 2) gl_version = OPENGL_VERSION_1_3;
143       if (MinorVersion > 3) gl_version = OPENGL_VERSION_1_4;
144       if (MinorVersion > 4) gl_version = OPENGL_VERSION_1_5;
145     }
146   }
147 }
148 
gld_InitOpenGL(dboolean compatibility_mode)149 void gld_InitOpenGL(dboolean compatibility_mode)
150 {
151   GLenum texture;
152   const char *extensions = (const char*)glGetString(GL_EXTENSIONS);
153 
154   gl_compatibility_mode = compatibility_mode;
155 
156   gld_InitOpenGLVersion();
157 
158   gl_ext_texture_filter_anisotropic = gl_ext_texture_filter_anisotropic_default &&
159     isExtensionSupported("GL_EXT_texture_filter_anisotropic") != NULL;
160   if (gl_ext_texture_filter_anisotropic)
161     lprintf(LO_INFO, "using GL_EXT_texture_filter_anisotropic\n");
162 
163   // Any textures sizes are allowed
164   gl_arb_texture_non_power_of_two = gl_arb_texture_non_power_of_two_default &&
165     isExtensionSupported("GL_ARB_texture_non_power_of_two") != NULL;
166   if (gl_arb_texture_non_power_of_two)
167     lprintf(LO_INFO, "using GL_ARB_texture_non_power_of_two\n");
168 
169   // Paletted textures
170   if (isExtensionSupported("GL_EXT_paletted_texture") != NULL)
171   {
172     if (gl_use_paletted_texture)
173     {
174       gl_paletted_texture = true;
175       GLEXT_glColorTableEXT = SDL_GL_GetProcAddress("glColorTableEXT");
176       if (GLEXT_glColorTableEXT == NULL)
177         gl_paletted_texture = false;
178       else
179         lprintf(LO_INFO,"using GL_EXT_paletted_texture\n");
180     }
181   }
182   else if (isExtensionSupported("GL_EXT_shared_texture_palette") != NULL)
183   {
184     if (gl_use_shared_texture_palette)
185     {
186       gl_shared_texture_palette = true;
187       GLEXT_glColorTableEXT = SDL_GL_GetProcAddress("glColorTableEXT");
188       if (GLEXT_glColorTableEXT == NULL)
189         gl_shared_texture_palette = false;
190       else
191         lprintf(LO_INFO,"using GL_EXT_shared_texture_palette\n");
192     }
193   }
194 
195   //
196   // ARB_multitexture command function pointers
197   //
198 
199   gl_arb_multitexture = gl_arb_multitexture_default &&
200     isExtensionSupported("GL_ARB_multitexture") != NULL;
201   if (gl_arb_multitexture)
202   {
203     GLEXT_glActiveTextureARB        = SDL_GL_GetProcAddress("glActiveTextureARB");
204     GLEXT_glClientActiveTextureARB  = SDL_GL_GetProcAddress("glClientActiveTextureARB");
205     GLEXT_glMultiTexCoord2fARB      = SDL_GL_GetProcAddress("glMultiTexCoord2fARB");
206     GLEXT_glMultiTexCoord2fvARB     = SDL_GL_GetProcAddress("glMultiTexCoord2fvARB");
207 
208     if (!GLEXT_glActiveTextureARB   || !GLEXT_glClientActiveTextureARB ||
209         !GLEXT_glMultiTexCoord2fARB || !GLEXT_glMultiTexCoord2fvARB)
210       gl_arb_multitexture = false;
211   }
212   if (gl_arb_multitexture)
213     lprintf(LO_INFO,"using GL_ARB_multitexture\n");
214 
215   //
216   // ARB_texture_compression
217   //
218 
219   gl_arb_texture_compression = gl_arb_texture_compression_default &&
220     isExtensionSupported("GL_ARB_texture_compression") != NULL;
221   if (gl_arb_texture_compression)
222   {
223     GLEXT_glCompressedTexImage2DARB = SDL_GL_GetProcAddress("glCompressedTexImage2DARB");
224 
225     if (!GLEXT_glCompressedTexImage2DARB)
226       gl_arb_texture_compression = false;
227   }
228   if (gl_arb_texture_compression)
229     lprintf(LO_INFO,"using GL_ARB_texture_compression\n");
230 
231   //
232   // EXT_framebuffer_object
233   //
234   gl_ext_framebuffer_object = gl_ext_framebuffer_object_default &&
235     isExtensionSupported("GL_EXT_framebuffer_object") != NULL;
236   if (gl_ext_framebuffer_object)
237   {
238     GLEXT_glGenFramebuffersEXT         = SDL_GL_GetProcAddress("glGenFramebuffersEXT");
239     GLEXT_glBindFramebufferEXT         = SDL_GL_GetProcAddress("glBindFramebufferEXT");
240     GLEXT_glGenRenderbuffersEXT        = SDL_GL_GetProcAddress("glGenRenderbuffersEXT");
241     GLEXT_glBindRenderbufferEXT        = SDL_GL_GetProcAddress("glBindRenderbufferEXT");
242     GLEXT_glRenderbufferStorageEXT     = SDL_GL_GetProcAddress("glRenderbufferStorageEXT");
243     GLEXT_glFramebufferRenderbufferEXT = SDL_GL_GetProcAddress("glFramebufferRenderbufferEXT");
244     GLEXT_glFramebufferTexture2DEXT    = SDL_GL_GetProcAddress("glFramebufferTexture2DEXT");
245     GLEXT_glCheckFramebufferStatusEXT  = SDL_GL_GetProcAddress("glCheckFramebufferStatusEXT");
246     GLEXT_glDeleteFramebuffersEXT      = SDL_GL_GetProcAddress("glDeleteFramebuffersEXT");
247     GLEXT_glDeleteRenderbuffersEXT     = SDL_GL_GetProcAddress("glDeleteRenderbuffersEXT");
248 
249     if (!GLEXT_glGenFramebuffersEXT || !GLEXT_glBindFramebufferEXT ||
250         !GLEXT_glGenRenderbuffersEXT || !GLEXT_glBindRenderbufferEXT ||
251         !GLEXT_glRenderbufferStorageEXT || !GLEXT_glFramebufferRenderbufferEXT ||
252         !GLEXT_glFramebufferTexture2DEXT || !GLEXT_glCheckFramebufferStatusEXT ||
253         !GLEXT_glDeleteFramebuffersEXT || !GLEXT_glDeleteRenderbuffersEXT)
254       gl_ext_framebuffer_object = false;
255   }
256   if (gl_ext_framebuffer_object)
257     lprintf(LO_INFO,"using GL_EXT_framebuffer_object\n");
258 
259   gl_ext_packed_depth_stencil = gl_ext_packed_depth_stencil_default &&
260     isExtensionSupported("GL_EXT_packed_depth_stencil") != NULL;
261   if (gl_ext_packed_depth_stencil)
262     lprintf(LO_INFO,"using GL_EXT_packed_depth_stencil\n");
263 
264   //
265   // Blending
266   //
267 
268   gl_ext_blend_color = gl_ext_blend_color_default &&
269     isExtensionSupported("GL_EXT_blend_color") != NULL;
270   if (gl_ext_blend_color)
271   {
272     GLEXT_glBlendColorEXT = SDL_GL_GetProcAddress("glBlendColorEXT");
273 
274     if (!GLEXT_glBlendColorEXT)
275       gl_ext_blend_color = false;
276   }
277   if (gl_ext_blend_color)
278     lprintf(LO_INFO,"using GL_EXT_blend_color\n");
279 
280   // VBO
281 #ifdef USE_VBO
282   gl_ext_arb_vertex_buffer_object = gl_ext_arb_vertex_buffer_object_default &&
283     isExtensionSupported("GL_ARB_vertex_buffer_object") != NULL;
284   if (gl_ext_arb_vertex_buffer_object)
285   {
286     GLEXT_glGenBuffersARB = SDL_GL_GetProcAddress("glGenBuffersARB");
287     GLEXT_glDeleteBuffersARB = SDL_GL_GetProcAddress("glDeleteBuffersARB");
288     GLEXT_glBindBufferARB = SDL_GL_GetProcAddress("glBindBufferARB");
289     GLEXT_glBufferDataARB = SDL_GL_GetProcAddress("glBufferDataARB");
290 
291     if (!GLEXT_glGenBuffersARB || !GLEXT_glDeleteBuffersARB ||
292         !GLEXT_glBindBufferARB || !GLEXT_glBufferDataARB)
293       gl_ext_arb_vertex_buffer_object = false;
294   }
295   if (gl_ext_arb_vertex_buffer_object)
296     lprintf(LO_INFO,"using GL_ARB_vertex_buffer_object\n");
297 #else
298   gl_ext_arb_vertex_buffer_object = false;
299 #endif
300 
301   gl_arb_pixel_buffer_object = gl_arb_pixel_buffer_object_default &&
302     isExtensionSupported("GL_ARB_pixel_buffer_object") != NULL;
303   if (gl_arb_pixel_buffer_object)
304   {
305     GLEXT_glGenBuffersARB = SDL_GL_GetProcAddress("glGenBuffersARB");
306     GLEXT_glBindBufferARB = SDL_GL_GetProcAddress("glBindBufferARB");
307     GLEXT_glBufferDataARB = SDL_GL_GetProcAddress("glBufferDataARB");
308     GLEXT_glBufferSubDataARB = SDL_GL_GetProcAddress("glBufferSubDataARB");
309     GLEXT_glDeleteBuffersARB = SDL_GL_GetProcAddress("glDeleteBuffersARB");
310     GLEXT_glGetBufferParameterivARB = SDL_GL_GetProcAddress("glGetBufferParameterivARB");
311     GLEXT_glMapBufferARB = SDL_GL_GetProcAddress("glMapBufferARB");
312     GLEXT_glUnmapBufferARB = SDL_GL_GetProcAddress("glUnmapBufferARB");
313 
314     if (!GLEXT_glGenBuffersARB || !GLEXT_glBindBufferARB ||
315         !GLEXT_glBufferDataARB || !GLEXT_glBufferSubDataARB ||
316         !GLEXT_glDeleteBuffersARB || !GLEXT_glGetBufferParameterivARB ||
317         !GLEXT_glMapBufferARB || !GLEXT_glUnmapBufferARB)
318       gl_arb_pixel_buffer_object = false;
319   }
320   if (gl_arb_pixel_buffer_object)
321     lprintf(LO_INFO,"using GL_ARB_pixel_buffer_object\n");
322 
323   //
324   // Stencil support
325   //
326 
327   gl_use_stencil = gl_use_stencil_default;
328 
329   // GL_CLAMP_TO_EDGE
330   GLEXT_CLAMP_TO_EDGE = (gl_version >= OPENGL_VERSION_1_2 ? GL_CLAMP_TO_EDGE : GL_CLAMP);
331 
332   glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max_texture_size);
333   lprintf(LO_INFO,"GL_MAX_TEXTURE_SIZE=%i\n", gl_max_texture_size);
334 
335   // Additional checks
336   if (gl_version < OPENGL_VERSION_1_3)
337   {
338     gl_ext_framebuffer_object = false;
339     gl_ext_blend_color = false;
340   }
341 
342   if ((compatibility_mode) || (gl_version <= OPENGL_VERSION_1_1))
343   {
344     lprintf(LO_INFO, "gld_InitOpenGL: Compatibility mode is used.\n");
345     gl_arb_texture_non_power_of_two = false;
346     gl_arb_multitexture = false;
347     gl_arb_texture_compression = false;
348     gl_ext_framebuffer_object = false;
349     gl_ext_packed_depth_stencil = false;
350     gl_ext_blend_color = false;
351     gl_use_stencil = false;
352     gl_ext_arb_vertex_buffer_object = false;
353     gl_arb_pixel_buffer_object = false;
354     GLEXT_CLAMP_TO_EDGE = GL_CLAMP;
355     gl_version = OPENGL_VERSION_1_1;
356   }
357 
358   //init states manager
359   gld_EnableMultisample(true);
360   gld_EnableMultisample(false);
361 
362   for (texture = GL_TEXTURE0_ARB; texture <= GL_TEXTURE31_ARB; texture++)
363   {
364     gld_EnableTexture2D(texture, true);
365     gld_EnableTexture2D(texture, false);
366 
367     gld_EnableClientCoordArray(texture, true);
368     gld_EnableClientCoordArray(texture, false);
369   }
370 }
371 
gld_EnableTexture2D(GLenum texture,int enable)372 void gld_EnableTexture2D(GLenum texture, int enable)
373 {
374   int arb;
375 
376   if (!gl_arb_multitexture && texture != GL_TEXTURE0_ARB)
377     return;
378 
379   arb = texture - GL_TEXTURE0_ARB;
380 
381 #ifdef RANGECHECK
382   if (arb < 0 || arb > 31)
383     I_Error("gld_EnableTexture2D: wronge ARB texture unit %d", arb);
384 #endif
385 
386   if (enable)
387   {
388     if (!active_texture_enabled[arb])
389     {
390       if (arb != 0)
391       {
392         GLEXT_glActiveTextureARB(texture);
393         glEnable(GL_TEXTURE_2D);
394         GLEXT_glActiveTextureARB(GL_TEXTURE0_ARB);
395       }
396       else
397       {
398         glEnable(GL_TEXTURE_2D);
399       }
400       active_texture_enabled[arb] = enable;
401     }
402   }
403   else
404   {
405     if (active_texture_enabled[arb])
406     {
407       if (arb != 0)
408       {
409         GLEXT_glActiveTextureARB(texture);
410         glDisable(GL_TEXTURE_2D);
411         GLEXT_glActiveTextureARB(GL_TEXTURE0_ARB);
412       }
413       else
414       {
415         glDisable(GL_TEXTURE_2D);
416       }
417       active_texture_enabled[arb] = enable;
418     }
419   }
420 }
421 
gld_EnableClientCoordArray(GLenum texture,int enable)422 void gld_EnableClientCoordArray(GLenum texture, int enable)
423 {
424 #ifdef USE_VERTEX_ARRAYS
425   int arb;
426 
427   if (!gl_arb_multitexture)
428     return;
429 
430   arb = texture - GL_TEXTURE0_ARB;
431 
432 #ifdef RANGECHECK
433   if (arb < 0 || arb > 31)
434     I_Error("gld_EnableTexture2D: wronge ARB texture unit %d", arb);
435 #endif
436 
437   if (enable)
438   {
439     if (!clieant_active_texture_enabled[arb])
440     {
441       GLEXT_glClientActiveTextureARB(texture);
442       glEnableClientState(GL_TEXTURE_COORD_ARRAY);
443       GLEXT_glClientActiveTextureARB(GL_TEXTURE0_ARB);
444 
445       clieant_active_texture_enabled[arb] = enable;
446     }
447   }
448   else
449   {
450     if (clieant_active_texture_enabled[arb])
451     {
452       GLEXT_glClientActiveTextureARB(texture);
453       glDisableClientState(GL_TEXTURE_COORD_ARRAY);
454       GLEXT_glClientActiveTextureARB(GL_TEXTURE0_ARB);
455 
456       clieant_active_texture_enabled[arb] = enable;
457     }
458   }
459 #endif
460 }
461 
gld_EnableMultisample(int enable)462 void gld_EnableMultisample(int enable)
463 {
464   static int multisample_is_enabled = 0;
465   if (enable)
466   {
467     if (!multisample_is_enabled)
468     {
469       glEnable(GL_MULTISAMPLE_ARB);
470 
471       multisample_is_enabled = enable;
472     }
473   }
474   else
475   {
476     if (multisample_is_enabled)
477     {
478       glDisable(GL_MULTISAMPLE_ARB);
479 
480       multisample_is_enabled = enable;
481     }
482   }
483 }
484 
SetTextureMode(tex_mode_e type)485 void SetTextureMode(tex_mode_e type)
486 {
487   if (gl_compatibility_mode)
488   {
489     type = TM_MODULATE;
490   }
491 
492   if (type == TM_MASK)
493   {
494     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
495     glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
496     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
497     glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
498 
499     glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
500     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR);
501     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE0);
502     glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
503     glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
504   }
505   else if (type == TM_OPAQUE)
506   {
507     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
508     glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
509     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0);
510     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
511     glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
512     glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
513 
514     glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
515     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR);
516     glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
517   }
518   else if (type == TM_INVERT)
519   {
520     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
521     glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
522     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0);
523     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
524     glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR);
525     glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
526 
527     glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
528     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR);
529     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE0);
530     glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
531     glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
532   }
533   else if (type == TM_INVERTOPAQUE)
534   {
535     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
536     glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
537     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0);
538     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
539     glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR);
540     glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
541 
542     glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
543     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR);
544     glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
545   }
546   else // if (type == TM_MODULATE)
547   {
548     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
549   }
550 }
551