1 /**************************************************************************\
2  * Copyright (c) Kongsberg Oil & Gas Technologies AS
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32 
33 /*!
34   How to use OpenGL / GLX|WGL|AGL|CGL inside Coin
35   ===============================================
36 
37   Creating portable OpenGL applications can be a complicated matter
38   since you have to have both compile-time and run-time tests for
39   OpenGL version, and what extensions are available. In addition, you
40   might not have an entry point to the (extension) function in
41   question on your build system.  The cc_glglue abstraction is here
42   to relieve the application programmer for that burden.
43 
44   To use the cc_glglue interface, include Inventor/C/glue/gl.h.
45 
46   The cc_glglue interface is part of the public API of Coin, but is
47   not documented on the public documentation pages at
48   https://coin3d.bitbucket.io/Coin/ yet. The status for client application
49   usage is "unofficial, use at own risk, interface may change without
50   warning for major version number upgrade releases".
51 
52   Coin programmer's responsibilities
53   ----------------------------------
54 
55   o OpenGL calls that are part of OpenGL 1.0 can safely be used
56     without any kind of checking.
57 
58   o Do _not_ use cc_glglue unless you are sure that you have a valid
59     OpenGL context. cc_glglue implicitly assumes that this is the case
60     for most of its functions. In short, only use OpenGL functions
61     inside an SoGLRenderAction.
62 
63   o To get hold of a cc_glglue instance:
64       const cc_glglue * cc_glglue_instance(int contextid);
65     or
66       const cc_glglue * cc_glglue_instance_from_context_ptr(void * ctx);
67 
68     See header file for more information about these.
69 
70   o Always check that the capability you want to use is supported.
71     Queries for this is supported through the cc_glglue_has_*()
72     functions.
73 
74   o cc_glglue has some functions for querying OpenGL/GLX version and
75     extension availability. Usually you shouldn't need to use these
76     unless you want to bypass cc_glglue or your function isn't
77     supported by cc_glglue (in which case you should add it).
78 
79   o SoGLCacheContextElement also has some functions for querying
80     OpenGL version and extension availability. These are public, so
81     you can use them even in external code. However, use cc_glglue
82     internally for consistency.
83 
84   What cc_glglue supplies
85   -----------------------
86 
87   o cc_glglue supplies function pointer to OpenGL and GLX functions
88     used in Coin that are _not_ part of OpenGL 1.0 and GLX 1.1.  Note
89     that cc_glglue supplies OpenGL extension functions as if they were
90     standard functions (i.e. without the EXT suffix).
91 
92   o In addition, the Inventor/system/gl.h file supplies OpenGL enums
93     that might not otherwise be present in your system's GL headers.
94 
95   The following example accesses OpenGL 3D texturing. It works both on
96   OpenGL >= 1.2 and on OpenGL drivers with the GL_EXT_texture3D
97   extension.
98 
99   ------ 8< --------- [snip] --------------------- 8< --------- [snip] -----
100 
101   const cc_glglue * glw = cc_glglue_instance(SoGLCacheContextElement::get(state));
102   if (cc_glglue_has_3d_textures(glw)) {
103     cc_glglue_glTexImage3D(glw, GL_PROXY_TEXTURE_3D, 0, GL_RGBA,
104                            64, 64, 64, 0,
105                            GL_RGBA, GL_UNSIGNED_BYTE,
106                            NULL);
107   }
108   else {
109     // Implement a proper fallback or error handling.
110   }
111 
112   ------ 8< --------- [snip] --------------------- 8< --------- [snip] -----
113 */
114 
115 /*!
116   For the library/API doc, here's the environment variables
117   influencing the OpenGL binding:
118 
119   - COIN_DEBUG_GLGLUE: set equal to "1" to make the wrapper
120     initialization spit out lots of info about the underlying OpenGL
121     implementation.
122 
123   - COIN_PREFER_GLPOLYGONOFFSET_EXT: when set to "1" and both
124     glPolygonOffset() and glPolygonOffsetEXT() is available, the
125     latter will be used. This can be useful to work around a
126     problematic glPolygonOffset() implementation for certain SGI
127     platforms.
128 
129   - COIN_FULL_INDIRECT_RENDERING: set to "1" to let Coin take
130     advantage of OpenGL1.1+ and extensions even when doing
131     remote/indirect rendering.
132 
133     We don't allow this by default now, for mainly two reasons: 1)
134     we've seen NVidia GLX bugs when attempting this. 2) We generally
135     prefer a "better safe than sorry" strategy.
136 
137     We might consider changing this strategy to allow it by default,
138     and provide an envvar to turn it off instead -- if we can get
139     confirmation that the assumed NVidia driver bug is indeed NVidia's
140     problem.
141 
142   - COIN_FORCE_GL1_0_ONLY: set to "1" to disallow use of OpenGL1.1+
143     and extensions under all circumstances.
144 
145   - COIN_FORCE_AGL: set to "1" to prefer using the old AGL bindings over CGL.
146     Note that AGL is not available on 64-bit systems. The AGL code is not
147     compiled into Coin by default, but must be enabled at configure-time using
148     --enable-agl in addition to using the environment variable.
149 */
150 
151 
152 /*
153   Useful resources:
154 
155    - About OpenGL 1.2, 1.3, 1.4:
156      <URL:http://www.opengl.org/developers/documentation/OpenGL12.html>
157      <URL:http://www.opengl.org/developers/documentation/OpenGL13.html>
158      <URL:http://www.opengl.org/developers/documentation/OpenGL14.html>
159      (explains all new features in depth)
160 
161    - The OpenGL Extension Registry:
162      <URL:http://oss.sgi.com/projects/ogl-sample/registry/>
163 
164    - A great overview of what OpenGL driver capabilities are available
165      for different cards, check out "3D Hardware Info" on
166      <URL:http://www.delphi3d.net/>.
167 
168    - Brian Paul presentation "Using OpenGL Extensions" from SIGGRAPH '97:
169      <URL:http://www.mesa3d.org/brianp/sig97/exten.htm>
170 
171    - Sun's man pages:
172      <URL:http://wwws.sun.com/software/graphics/OpenGL/manpages>
173 
174    - IBM AIX GL man pages (try to find a "more official looking" link):
175      <URL:http://molt.zdv.uni-mainz.de/doc_link/en_US/a_doc_lib/libs/openglrf/OpenGLXEnv.htm>
176 
177    - HP GL man pages:
178      <URL:http://www.hp.com/workstations/support/documentation/manuals/user_guides/graphics/opengl/RefTOC.html>
179 
180    - An Apple Technical Q&A on how to do dynamic binding to OpenGL symbols:
181      <URL:http://developer.apple.com/qa/qa2001/qa1188.html>
182 
183      Full documentation on all "Object File Image" functions, see:
184      <URL:http://developer.apple.com/techpubs/macosx/DeveloperTools/MachORuntime/5rt_api_reference/_Object_Fil_e_Functions.html>
185 */
186 
187 #ifdef HAVE_CONFIG_H
188 #include "config.h"
189 #endif /* HAVE_CONFIG_H */
190 
191 // *************************************************************************
192 
193 /* The configure script should protect against more than one of
194    HAVE_WGL, HAVE_GLX, HAVE_AGL|HAVE_CGL being defined at the same time, but
195    we set up this little trip-wire in addition, just in case someone
196    is either fiddling manually with config.h, or in case a change is
197    made which breaks this protection in the configure script. */
198 
199 #if defined(HAVE_WGL) && (defined(HAVE_GLX) || defined(HAVE_AGL) || defined(HAVE_CGL))
200 #error More than one of HAVE_WGL, HAVE_GLX and HAVE_AGL|HAVE_CGL set simultaneously!
201 #endif
202 
203 #if defined(HAVE_GLX) && (defined(HAVE_AGL) || defined(HAVE_CGL))
204 #error More than one of HAVE_WGL, HAVE_GLX and HAVE_AGL|HAVE_CGL set simultaneously!
205 #endif
206 
207 // Define HAVE_NOGL if no platform GL binding exists
208 #if !defined(HAVE_WGL) && !defined(HAVE_GLX) && !(defined(HAVE_AGL) || defined(HAVE_CGL))
209 #define HAVE_NOGL 1
210 #endif
211 
212 // *************************************************************************
213 
214 #include <cassert>
215 #include <cstdlib>
216 #include <cstring>
217 #include <climits> /* SHRT_MAX */
218 
219 #ifdef HAVE_AGL
220 #include <AGL/agl.h>
221 #endif /* HAVE_AGL */
222 
223 #ifdef HAVE_OPENGL_CGLCURRENT_H
224 #include <OpenGL/CGLCurrent.h>
225 #endif
226 
227 #ifdef HAVE_CGL
228 #include <OpenGL/OpenGL.h>
229 #endif
230 
231 #ifdef HAVE_GLX
232 #include <GL/glx.h>
233 #endif /* HAVE_GLX */
234 
235 #include <Inventor/C/glue/gl.h>
236 
237 #include <Inventor/C/errors/debugerror.h>
238 #include <Inventor/C/glue/dl.h>
239 #include <Inventor/C/tidbits.h>
240 #include <Inventor/C/base/list.h>
241 
242 #include "coindefs.h"
243 #include "tidbitsp.h"
244 #include "base/dict.h"
245 #include "base/namemap.h"
246 #include "glue/glp.h"
247 #include "glue/dlp.h"
248 #include "glue/gl_agl.h"
249 #include "glue/gl_cgl.h"
250 #include "glue/gl_glx.h"
251 #include "glue/gl_wgl.h"
252 #include "threads/threadsutilp.h"
253 
254 /* ********************************************************************** */
255 
256 #ifdef __cplusplus
257 extern "C" {
258 #endif /* __cplusplus */
259 
260 #if 0 /* emacs indentation fix */
261 }
262 #endif
263 
264 static cc_list * gl_instance_created_cblist = NULL;
265 static int COIN_MAXIMUM_TEXTURE2_SIZE = -1;
266 static int COIN_MAXIMUM_TEXTURE3_SIZE = -1;
267 static cc_glglue_offscreen_cb_functions* offscreen_cb = NULL;
268 static int COIN_USE_AGL = -1;
269 
270 /* ********************************************************************** */
271 
272 /* Sanity checks for enum extension value assumed to be equal to the
273  * final / "proper" / standard OpenGL enum values. (If not, we could
274  * end up with hard-to-find bugs because of mismatches with the
275  * compiled values versus the run-time values.)
276  *
277  * This doesn't really _fix_ anything, it is just meant as an aid to
278  * smoke out platforms where we're getting unexpected enum values.
279  */
280 
281 #ifdef GL_CLAMP_TO_EDGE_EXT
282 #if GL_CLAMP_TO_EDGE != GL_CLAMP_TO_EDGE_EXT
283 #error dangerous enum mismatch
284 #endif /* cmp */
285 #endif /* GL_CLAMP_TO_EDGE_EXT */
286 
287 #ifdef GL_CLAMP_TO_EDGE_SGIS
288 #if GL_CLAMP_TO_EDGE != GL_CLAMP_TO_EDGE_SGIS
289 #error dangerous enum mismatch
290 #endif /* cmp */
291 #endif /* GL_CLAMP_TO_EDGE_SGIS */
292 
293 #ifdef GL_MAX_3D_TEXTURE_SIZE_EXT
294 #if GL_MAX_3D_TEXTURE_SIZE != GL_MAX_3D_TEXTURE_SIZE_EXT
295 #error dangerous enum mismatch
296 #endif /* cmp */
297 #endif /* GL_MAX_3D_TEXTURE_SIZE_EXT */
298 
299 #ifdef GL_PACK_IMAGE_HEIGHT_EXT
300 #if GL_PACK_IMAGE_HEIGHT != GL_PACK_IMAGE_HEIGHT_EXT
301 #error dangerous enum mismatch
302 #endif /* cmp */
303 #endif /* GL_PACK_IMAGE_HEIGHT_EXT */
304 
305 #ifdef GL_PACK_SKIP_IMAGES_EXT
306 #if GL_PACK_SKIP_IMAGES != GL_PACK_SKIP_IMAGES_EXT
307 #error dangerous enum mismatch
308 #endif /* cmp */
309 #endif /* GL_PACK_SKIP_IMAGES_EXT */
310 
311 #ifdef GL_PROXY_TEXTURE_2D_EXT
312 #if GL_PROXY_TEXTURE_2D != GL_PROXY_TEXTURE_2D_EXT
313 #error dangerous enum mismatch
314 #endif /* cmp */
315 #endif /* GL_PROXY_TEXTURE_2D_EXT */
316 
317 #ifdef GL_PROXY_TEXTURE_3D_EXT
318 #if GL_PROXY_TEXTURE_3D != GL_PROXY_TEXTURE_3D_EXT
319 #error dangerous enum mismatch
320 #endif /* cmp */
321 #endif /* GL_PROXY_TEXTURE_3D_EXT */
322 
323 #ifdef GL_TEXTURE_3D_EXT
324 #if GL_TEXTURE_3D != GL_TEXTURE_3D_EXT
325 #error dangerous enum mismatch
326 #endif /* cmp */
327 #endif /* GL_TEXTURE_3D_EXT */
328 
329 #ifdef GL_TEXTURE_DEPTH_EXT
330 #if GL_TEXTURE_DEPTH != GL_TEXTURE_DEPTH_EXT
331 #error dangerous enum mismatch
332 #endif /* cmp */
333 #endif /* GL_TEXTURE_DEPTH_EXT */
334 
335 #ifdef GL_TEXTURE_WRAP_R_EXT
336 #if GL_TEXTURE_WRAP_R != GL_TEXTURE_WRAP_R_EXT
337 #error dangerous enum mismatch
338 #endif /* cmp */
339 #endif /* GL_TEXTURE_WRAP_R_EXT */
340 
341 #ifdef GL_UNPACK_IMAGE_HEIGHT_EXT
342 #if GL_UNPACK_IMAGE_HEIGHT != GL_UNPACK_IMAGE_HEIGHT_EXT
343 #error dangerous enum mismatch
344 #endif /* cmp */
345 #endif /* GL_UNPACK_IMAGE_HEIGHT_EXT */
346 
347 #ifdef GL_UNPACK_SKIP_IMAGES_EXT
348 #if GL_UNPACK_SKIP_IMAGES != GL_UNPACK_SKIP_IMAGES_EXT
349 #error dangerous enum mismatch
350 #endif /* cmp */
351 #endif /* GL_UNPACK_SKIP_IMAGES_EXT */
352 
353 #ifdef GL_FUNC_ADD_EXT
354 #if GL_FUNC_ADD != GL_FUNC_ADD_EXT
355 #error dangerous enum mismatch
356 #endif /* cmp */
357 #endif /* GL_FUNC_ADD_EXT */
358 
359 #ifdef GL_MIN_EXT
360 #if GL_MIN != GL_MIN_EXT
361 #error dangerous enum mismatch
362 #endif /* cmp */
363 #endif /* GL_MIN_EXT */
364 
365 #ifdef GL_MAX_EXT
366 #if GL_MAX != GL_MAX_EXT
367 #error dangerous enum mismatch
368 #endif /* cmp */
369 #endif /* GL_MAX_EXT */
370 
371 #ifdef GL_COLOR_TABLE_WIDTH_EXT
372 #if GL_COLOR_TABLE_WIDTH != GL_COLOR_TABLE_WIDTH_EXT
373 #error dangerous enum mismatch
374 #endif /* cmp */
375 #endif /* GL_COLOR_TABLE_WIDTH_EXT */
376 
377 /* ********************************************************************** */
378 
379 /* Resolve and return the integer value of an environment variable. */
380 static int
glglue_resolve_envvar(const char * txt)381 glglue_resolve_envvar(const char * txt)
382 {
383   const char * val = coin_getenv(txt);
384   return val ? atoi(val) : 0;
385 }
386 
387 /* Returns a flag which indicates whether or not to allow the use of
388    OpenGL 1.1+ features and extensions.
389 
390    We default to *not* allowing this if rendering is indirect, as
391    we've seen major problems with at least NVidia GLX when using
392    OpenGL 1.1+ features. It can be forced on by an environment
393    variable, though.
394 
395    (A better strategy *might* be to default to allow it, but to smoke
396    out and warn if we detect NVidia GLX, and in addition to provide an
397    environment variable that disables it.)
398 */
399 static SbBool
glglue_allow_newer_opengl(const cc_glglue * w)400 glglue_allow_newer_opengl(const cc_glglue * w)
401 {
402   static SbBool fullindirect = -1;
403   static SbBool force1_0 = -1;
404   static const char * COIN_FULL_INDIRECT_RENDERING = "COIN_FULL_INDIRECT_RENDERING";
405   static const char * COIN_DONT_INFORM_INDIRECT_RENDERING = "COIN_DONT_INFORM_INDIRECT_RENDERING";
406 
407   if (fullindirect == -1) {
408     fullindirect = (glglue_resolve_envvar(COIN_FULL_INDIRECT_RENDERING) > 0);
409   }
410 
411   if (force1_0 == -1) {
412     force1_0 = (glglue_resolve_envvar("COIN_FORCE_GL1_0_ONLY") > 0);
413   }
414 
415   if (force1_0) return FALSE;
416 
417   if (!w->glx.isdirect && !fullindirect) {
418     /* We give out a warning, once, when the full OpenGL feature set is not
419        used, in case the end user uses an application with a remote display,
420        and that was not expected by the application programmer. */
421     static int inform = -1;
422     if (inform == -1) { inform = glglue_resolve_envvar(COIN_DONT_INFORM_INDIRECT_RENDERING); }
423     if (inform == 0) {
424       cc_debugerror_postinfo("glglue_allow_newer_opengl",
425                              "\n\nFeatures of OpenGL version > 1.0 has been\n"
426                              "disabled, due to the use of a remote display.\n\n"
427                              "This is so because many common OpenGL drivers\n"
428                              "have problems in this regard.\n\n"
429                              "To force full OpenGL use, set the environment\n"
430                              "variable %s=1 and re-run the application.\n\n"
431                              "If you don't want this message displayed again,\n"
432                              "set the environment variable %s=1.\n",
433                              COIN_FULL_INDIRECT_RENDERING,
434                              COIN_DONT_INFORM_INDIRECT_RENDERING);
435       inform = 1;
436     }
437     return FALSE;
438   }
439 
440   return TRUE;
441 }
442 
443 
444 /* Returns whether or not COIN_GLGLUE_SILENCE_DRIVER_WARNINGS is set
445    to a value > 0. If so, all known driver bugs will just be silently
446    accepted and attempted worked around. */
447 static int
coin_glglue_silence_all_driver_warnings(void)448 coin_glglue_silence_all_driver_warnings(void)
449 {
450   static int d = -1;
451   if (d == -1) { d = glglue_resolve_envvar("COIN_GLGLUE_SILENCE_DRIVER_WARNINGS"); }
452   /* Note the inversion of the envvar value versus the return value. */
453   return (d > 0) ? 0 : 1;
454 }
455 
456 /* Return value of COIN_GLGLUE_NO_RADEON_WARNING environment variable. */
457 static int
coin_glglue_radeon_warning(void)458 coin_glglue_radeon_warning(void)
459 {
460   static int d = -1;
461 
462   if (coin_glglue_silence_all_driver_warnings()) { return 0; }
463 
464   if (d == -1) { d = glglue_resolve_envvar("COIN_GLGLUE_NO_RADEON_WARNING"); }
465   /* Note the inversion of the envvar value versus the return value. */
466   return (d > 0) ? 0 : 1;
467 }
468 
469 /* Return value of COIN_GLGLUE_NO_G400_WARNING environment variable. */
470 static int
coin_glglue_old_matrox_warning(void)471 coin_glglue_old_matrox_warning(void)
472 {
473   static int d = -1;
474 
475   if (coin_glglue_silence_all_driver_warnings()) { return 0; }
476 
477   if (d == -1) { d = glglue_resolve_envvar("COIN_GLGLUE_NO_G400_WARNING"); }
478   /* Note the inversion of the envvar value versus the return value. */
479   return (d > 0) ? 0 : 1;
480 }
481 
482 /* Return value of COIN_GLGLUE_NO_ELSA_WARNING environment variable. */
483 static int
coin_glglue_old_elsa_warning(void)484 coin_glglue_old_elsa_warning(void)
485 {
486   static int d = -1;
487 
488   if (coin_glglue_silence_all_driver_warnings()) { return 0; }
489 
490   if (d == -1) { d = glglue_resolve_envvar("COIN_GLGLUE_NO_ELSA_WARNING"); }
491   /* Note the inversion of the envvar value versus the return value. */
492   return (d > 0) ? 0 : 1;
493 }
494 
495 /* Return value of COIN_GLGLUE_NO_SUN_EXPERT3D_WARNING environment variable. */
496 static int
coin_glglue_sun_expert3d_warning(void)497 coin_glglue_sun_expert3d_warning(void)
498 {
499   static int d = -1;
500 
501   if (coin_glglue_silence_all_driver_warnings()) { return 0; }
502 
503   if (d == -1) { d = glglue_resolve_envvar("COIN_GLGLUE_NO_SUN_EXPERT3D_WARNING"); }
504   /* Note the inversion of the envvar value versus the return value. */
505   return (d > 0) ? 0 : 1;
506 }
507 
508 /* Return value of COIN_GLGLUE_NO_TRIDENT_WARNING environment variable. */
509 static int
coin_glglue_trident_warning(void)510 coin_glglue_trident_warning(void)
511 {
512   static int d = -1;
513 
514   if (coin_glglue_silence_all_driver_warnings()) { return 0; }
515 
516   if (d == -1) { d = glglue_resolve_envvar("COIN_GLGLUE_NO_TRIDENT_WARNING"); }
517   /* Note the inversion of the envvar value versus the return value. */
518   return (d > 0) ? 0 : 1;
519 }
520 
521 /* Return value of COIN_DEBUG_GLGLUE environment variable. */
522 int
coin_glglue_debug(void)523 coin_glglue_debug(void)
524 {
525   static int d = -1;
526   if (d == -1) { d = glglue_resolve_envvar("COIN_DEBUG_GLGLUE"); }
527   return (d > 0) ? 1 : 0;
528 }
529 
530 /* Return value of COIN_PREFER_GLPOLYGONOFFSET_EXT environment variable. */
531 static int
glglue_prefer_glPolygonOffsetEXT(void)532 glglue_prefer_glPolygonOffsetEXT(void)
533 {
534   static int d = -1;
535   if (d == -1) { d = glglue_resolve_envvar("COIN_PREFER_GLPOLYGONOFFSET_EXT"); }
536   return (d > 0) ? 1 : 0;
537 }
538 
539 /* FIXME: the following is a hack to get around a problem which really
540    demands more effort to be solved properly.
541 
542    The problem is that there is no way in the API of the
543    SoOffscreenRenderer class to specify what particular attributes to
544    request. This most often manifests itself as a problem for app
545    programmers in that they have made some kind of extension node
546    which uses the OpenGL stencil buffer. If no stencil buffer happens
547    to be part of the GL context format for the offscreen renderer,
548    these will not work properly. At the same time, we don't want to
549    default to requesting a stencil buffer, as that takes a non-trivial
550    amount of extra memory resources on the gfx card.
551 
552    So until we have implemented the proper solution for making it
553    possible to pass in a detailed specification of which attributes to
554    request from offscreen GL contexts, we provide this temporary
555    work-around: the app programmer can set an envvar with a value
556    specifying the number of stencil buffer bits he/she wants.
557 
558    20060223 mortene.
559 */
560 int
coin_glglue_stencil_bits_hack(void)561 coin_glglue_stencil_bits_hack(void)
562 {
563   const char * env = coin_getenv("COIN_OFFSCREEN_STENCIL_BITS");
564   if (!env) { return -1; }
565   return atoi(env);
566 }
567 
568 cc_libhandle
coin_glglue_dl_handle(const cc_glglue * glue)569 coin_glglue_dl_handle(const cc_glglue * glue)
570 {
571   if (!glue->dl_handle) {
572     const_cast <cc_glglue *> (glue)->dl_handle = cc_dl_handle_with_gl_symbols();
573   }
574   return glue->dl_handle;
575 }
576 
577 /* doc in header file */
578 void *
cc_glglue_getprocaddress(const cc_glglue * glue,const char * symname)579 cc_glglue_getprocaddress(const cc_glglue * glue, const char * symname)
580 {
581   void * ptr = NULL;
582 
583   // FIXME: also supply 'glue' to coin_[x]gl_getprocaddress()
584   ptr = coin_wgl_getprocaddress(glue, symname);
585   if (ptr) goto returnpoint;
586 
587   ptr = glxglue_getprocaddress(glue, symname);
588   if (ptr) goto returnpoint;
589 
590   ptr = cc_dl_sym(coin_glglue_dl_handle(glue), symname);
591   if (ptr) goto returnpoint;
592 
593 returnpoint:
594   if (coin_glglue_debug()) {
595     cc_debugerror_postinfo("cc_glglue_getprocaddress", "%s==%p", symname, ptr);
596   }
597   return ptr;
598 }
599 
600 /* Global dictionary which stores the mappings from the context IDs to
601    actual cc_glglue instances. */
602 static cc_dict * gldict = NULL;
603 
604 static void
free_glglue_instance(uintptr_t COIN_UNUSED_ARG (key),void * value,void * COIN_UNUSED_ARG (closure))605 free_glglue_instance(uintptr_t COIN_UNUSED_ARG(key), void * value, void * COIN_UNUSED_ARG(closure))
606 {
607   cc_glglue * glue = (cc_glglue*) value;
608   cc_dict_destruct(glue->glextdict);
609   free(value);
610 }
611 
612 /* Cleans up at exit. */
613 static void
glglue_cleanup(void)614 glglue_cleanup(void)
615 {
616   if (gldict) {
617     cc_dict_apply(gldict, free_glglue_instance, NULL);
618     cc_dict_destruct(gldict);
619     gldict = NULL;
620   }
621   offscreen_cb = NULL;
622 
623 #ifdef HAVE_GLX
624   glxglue_cleanup();
625 #elif defined(HAVE_WGL)
626   wglglue_cleanup();
627 #else
628 #if defined(HAVE_AGL)
629   if (COIN_USE_AGL > 0) aglglue_cleanup(); else
630 #endif
631 #if defined(HAVE_CGL)
632   cglglue_cleanup();
633 #else
634   ;
635 #endif
636 #endif
637 }
638 
639 static SbBool
glglue_has_nvidia_framebuffer_object_bug(int major,int minor,int release)640 glglue_has_nvidia_framebuffer_object_bug(int major, int minor, int release)
641 {
642   return (major == 2) && (minor == 0) && (release == 0);
643 }
644 
645 /*
646   Set the OpenGL version variables in the given cc_glglue struct
647   instance.
648 
649   Note: this code has been copied from GLUWrapper.c, so if any changes
650   are made, make sure they are propagated over if necessary.
651 */
652 static void
glglue_set_glVersion(cc_glglue * w)653 glglue_set_glVersion(cc_glglue * w)
654 {
655   char buffer[256];
656   char * dotptr;
657 
658   /* NB: if you are getting a crash here, it's because an attempt at
659    * setting up a cc_glglue instance was made when there is no current
660    * OpenGL context. */
661   if (coin_glglue_debug()) {
662     cc_debugerror_postinfo("glglue_set_glVersion",
663                            "glGetString(GL_VERSION)=='%s'", w->versionstr);
664   }
665 
666   w->version.major = 0;
667   w->version.minor = 0;
668   w->version.release = 0;
669 
670   (void)strncpy(buffer, (const char *)w->versionstr, 255);
671   buffer[255] = '\0'; /* strncpy() will not null-terminate if strlen > 255 */
672   dotptr = strchr(buffer, '.');
673   if (dotptr) {
674     char * spaceptr;
675     char * start = buffer;
676     *dotptr = '\0';
677     w->version.major = atoi(start);
678     start = ++dotptr;
679 
680     dotptr = strchr(start, '.');
681     spaceptr = strchr(start, ' ');
682     if (!dotptr && spaceptr) dotptr = spaceptr;
683     if (dotptr && spaceptr && spaceptr < dotptr) dotptr = spaceptr;
684     if (dotptr) {
685       int terminate = *dotptr == ' ';
686       *dotptr = '\0';
687       w->version.minor = atoi(start);
688       if (!terminate) {
689         start = ++dotptr;
690         dotptr = strchr(start, ' ');
691         if (dotptr) *dotptr = '\0';
692         w->version.release = atoi(start);
693       }
694     }
695     else {
696       w->version.minor = atoi(start);
697     }
698   }
699 
700   if (coin_glglue_debug()) {
701     cc_debugerror_postinfo("glglue_set_glVersion",
702                            "parsed to major=='%d', minor=='%d', micro=='%d'",
703                            w->version.major,
704                            w->version.minor,
705                            w->version.release);
706   }
707 }
708 
709 void
cc_glglue_glversion(const cc_glglue * w,unsigned int * major,unsigned int * minor,unsigned int * release)710 cc_glglue_glversion(const cc_glglue * w,
711                     unsigned int * major,
712                     unsigned int * minor,
713                     unsigned int * release)
714 {
715   if (!glglue_allow_newer_opengl(w)) {
716     *major = 1;
717     *minor = 0;
718     *release = 0;
719   }
720   else {
721     *major = w->version.major;
722     *minor = w->version.minor;
723     *release = w->version.release;
724   }
725 }
726 
727 
728 SbBool
cc_glglue_glversion_matches_at_least(const cc_glglue * w,unsigned int major,unsigned int minor,unsigned int revision)729 cc_glglue_glversion_matches_at_least(const cc_glglue * w,
730                                      unsigned int major,
731                                      unsigned int minor,
732                                      unsigned int revision)
733 {
734   unsigned int glmajor, glminor, glrev;
735   cc_glglue_glversion(w, &glmajor, &glminor, &glrev);
736 
737   if (glmajor < major) return FALSE;
738   else if (glmajor > major) return TRUE;
739   if (glminor < minor) return FALSE;
740   else if (glminor > minor) return TRUE;
741   if (glminor < revision) return FALSE;
742   return TRUE;
743 }
744 
745 SbBool
cc_glglue_glxversion_matches_at_least(const cc_glglue * w,int major,int minor)746 cc_glglue_glxversion_matches_at_least(const cc_glglue * w,
747                                       int major,
748                                       int minor)
749 {
750   if (w->glx.version.major < major) return FALSE;
751   else if (w->glx.version.major > major) return TRUE;
752   if (w->glx.version.minor < minor) return FALSE;
753   return TRUE;
754 }
755 
756 int
coin_glglue_extension_available(const char * extensions,const char * ext)757 coin_glglue_extension_available(const char * extensions, const char * ext)
758 {
759   const char * start;
760   size_t extlen;
761   SbBool found = FALSE;
762 
763   assert(ext && "NULL string");
764   assert((ext[0] != '\0') && "empty string");
765   assert((strchr(ext, ' ') == NULL) && "extension name can't have spaces");
766 
767   start = extensions;
768   extlen = strlen(ext);
769 
770   while (start) {
771     const char * where = strstr(start, ext);
772     if (!where) goto done;
773 
774     if (where == start || *(where - 1) == ' ') {
775       const char * terminator = where + extlen;
776       if (*terminator == ' ' || *terminator == '\0') {
777         found = TRUE;
778         goto done;
779       }
780     }
781 
782     start = where + extlen;
783   }
784 
785 done:
786   if (coin_glglue_debug()) {
787     cc_debugerror_postinfo("coin_glglue_extension_available",
788                            "extension '%s' is%s present",
789                            ext, found ? "" : " NOT");
790   }
791 
792   return found ? 1 : 0;
793 }
794 
795 int
cc_glglue_glext_supported(const cc_glglue * wrapper,const char * extension)796 cc_glglue_glext_supported(const cc_glglue * wrapper, const char * extension)
797 {
798   const uintptr_t key = (uintptr_t)cc_namemap_get_address(extension);
799 
800   void * result = NULL;
801   if (cc_dict_get(wrapper->glextdict, key, &result)) {
802     return result != NULL;
803   }
804   result = coin_glglue_extension_available(wrapper->extensionsstr, extension) ?
805     (void*) 1 : NULL;
806   cc_dict_put(wrapper->glextdict, key, result);
807 
808   return result != NULL;
809 }
810 
811 #ifdef HAVE_DYNAMIC_LINKING
812 
813 #define PROC(_glue_, _func_) cc_glglue_getprocaddress(_glue_, SO__QUOTE(_func_))
814 
815 /* The OpenGL library which we dynamically pick up symbols from
816    /could/ have all these defined. For the code below which tries to
817    dynamically resolve the methods, we will assume that they are all
818    defined. By doing this little "trick", can we use the same code
819    below for resolving stuff dynamically as we need anyway to resolve
820    in a static manner. */
821 #define GL_VERSION_1_1 1
822 #define GL_VERSION_1_2 1
823 #define GL_VERSION_1_3 1
824 #define GL_VERSION_1_4 1
825 #define GL_VERSION_1_5 1
826 #define GL_EXT_polygon_offset 1
827 #define GL_EXT_texture_object 1
828 #define GL_EXT_subtexture 1
829 #define GL_EXT_texture3D 1
830 #define GL_ARB_multitexture 1
831 #define GL_ARB_texture_compression 1
832 #define GL_EXT_paletted_texture 1
833 #define GL_ARB_imaging 1
834 #define GL_EXT_blend_minmax 1
835 #define GL_EXT_color_table 1
836 #define GL_EXT_color_subtable 1
837 #define GL_SGI_color_table 1
838 #define GL_SGI_texture_color_table 1
839 #define GL_ARB_vertex_buffer_object 1
840 #define GL_EXT_multi_draw_arrays 1
841 #define GL_NV_vertex_array_range 1
842 #define GL_NV_register_combiners 1
843 #define GL_NV_texture_rectangle 1
844 #define GL_NV_texture_shader 1
845 #define GL_ARB_depth_texture 1
846 #define GL_ARB_shadow 1
847 #define GL_EXT_texture_rectangle 1
848 #define GL_ARB_fragment_program 1
849 #define GL_ARB_vertex_program 1
850 #define GL_ARB_shader_objects 1
851 #define GL_ARB_vertex_shader 1
852 #define GL_ARB_occlusion_query 1
853 
854 #else /* static binding */
855 
856 #define PROC(_glue_, _func_) (&_func_)
857 
858 #endif /* static binding */
859 
860 
861 static void
glglue_resolve_symbols(cc_glglue * w)862 glglue_resolve_symbols(cc_glglue * w)
863 {
864   /* Note that there's a good reason why we use version checking
865      *along* with dynamic resolving (if the platform allows it): the
866      OpenGL library could (prematurely) include function symbols
867      without having an actual valid implementation behind them. */
868 
869   /* Appeared in OpenGL v1.1. We store both the "real" function
870      pointer and the extension pointer, in case we need to work around
871      an SGI bug (see comments in cc_glglue_glPolygonOffset(). */
872   w->glPolygonOffset = NULL;
873   w->glPolygonOffsetEXT = NULL;
874 #ifdef GL_VERSION_1_1
875   if (cc_glglue_glversion_matches_at_least(w, 1, 1, 0)) {
876     w->glPolygonOffset = (COIN_PFNGLPOLYGONOFFSETPROC)PROC(w, glPolygonOffset);
877   }
878 #endif /* GL_VERSION_1_1 */
879 #ifdef GL_EXT_polygon_offset
880   if (cc_glglue_glext_supported(w, "GL_EXT_polygon_offset")) {
881     w->glPolygonOffsetEXT = (COIN_PFNGLPOLYGONOFFSETPROC)PROC(w, glPolygonOffsetEXT);
882   }
883 #endif /* GL_EXT_polygon_offset */
884 
885 
886 
887   /* Appeared in OpenGL v1.1. */
888   w->glGenTextures = NULL;
889   w->glBindTexture = NULL;
890   w->glDeleteTextures = NULL;
891 #ifdef GL_VERSION_1_1
892   if (cc_glglue_glversion_matches_at_least(w, 1, 1, 0)) {
893     w->glGenTextures = (COIN_PFNGLGENTEXTURESPROC)PROC(w, glGenTextures);
894     w->glBindTexture = (COIN_PFNGLBINDTEXTUREPROC)PROC(w, glBindTexture);
895     w->glDeleteTextures = (COIN_PFNGLDELETETEXTURESPROC)PROC(w, glDeleteTextures);
896   }
897 #endif /* GL_VERSION_1_1 */
898 #ifdef GL_EXT_texture_object
899   if (!w->glGenTextures && cc_glglue_glext_supported(w, "GL_EXT_texture_object")) {
900     w->glGenTextures = (COIN_PFNGLGENTEXTURESPROC)PROC(w, glGenTexturesEXT);
901     w->glBindTexture = (COIN_PFNGLBINDTEXTUREPROC)PROC(w, glBindTextureEXT);
902     w->glDeleteTextures = (COIN_PFNGLDELETETEXTURESPROC)PROC(w, glDeleteTexturesEXT);
903   }
904 #endif /* GL_EXT_texture_object */
905 
906   /* Appeared in OpenGL v1.1. */
907   w->glTexSubImage2D = NULL;
908 #ifdef GL_VERSION_1_1
909   if (cc_glglue_glversion_matches_at_least(w, 1, 1, 0)) {
910     w->glTexSubImage2D = (COIN_PFNGLTEXSUBIMAGE2DPROC)PROC(w, glTexSubImage2D);
911   }
912 #endif /* GL_VERSION_1_1 */
913 #ifdef GL_EXT_subtexture
914   if (!w->glTexSubImage2D && cc_glglue_glext_supported(w, "GL_EXT_subtexture")) {
915     w->glTexSubImage2D = (COIN_PFNGLTEXSUBIMAGE2DPROC)PROC(w, glTexSubImage2DEXT);
916   }
917 #endif /* GL_EXT_subtexture */
918 
919   /* Appeared in OpenGL 1.1 */
920   w->glPushClientAttrib = NULL;
921   w->glPopClientAttrib = NULL;
922 #ifdef GL_VERSION_1_1
923   if (cc_glglue_glversion_matches_at_least(w, 1, 1, 0)) {
924     w->glPushClientAttrib = (COIN_PFNGLPUSHCLIENTATTRIBPROC) PROC(w, glPushClientAttrib);
925     w->glPopClientAttrib = (COIN_PFNGLPOPCLIENTATTRIBPROC) PROC(w, glPopClientAttrib);
926   }
927 #endif /* GL_VERSION_1_1 */
928 
929   /* These were introduced with OpenGL v1.2. */
930   w->glTexImage3D = NULL;
931   w->glCopyTexSubImage3D = NULL;
932   w->glTexSubImage3D = NULL;
933 #ifdef GL_VERSION_1_2
934   if (cc_glglue_glversion_matches_at_least(w, 1, 2, 0)) {
935     w->glTexImage3D = (COIN_PFNGLTEXIMAGE3DPROC)PROC(w, glTexImage3D);
936     w->glCopyTexSubImage3D = (COIN_PFNGLCOPYTEXSUBIMAGE3DPROC)PROC(w, glCopyTexSubImage3D);
937     w->glTexSubImage3D = (COIN_PFNGLTEXSUBIMAGE3DPROC)PROC(w, glTexSubImage3D);
938   }
939 #endif /* GL_VERSION_1_2 */
940 #ifdef GL_EXT_texture3D
941   if (!w->glTexImage3D && cc_glglue_glext_supported(w, "GL_EXT_texture3D")) {
942     w->glTexImage3D = (COIN_PFNGLTEXIMAGE3DPROC)PROC(w, glTexImage3DEXT);
943     /* These are implicitly given if GL_EXT_texture3D is defined. */
944     w->glCopyTexSubImage3D = (COIN_PFNGLCOPYTEXSUBIMAGE3DPROC)PROC(w, glCopyTexSubImage3DEXT);
945     w->glTexSubImage3D = (COIN_PFNGLTEXSUBIMAGE3DPROC)PROC(w, glTexSubImage3DEXT);
946   }
947 #endif /* GL_EXT_texture3D */
948 
949   /* Multi-texturing appeared in OpenGL v1.3, or with the
950      GL_ARB_multitexture extension before that.
951   */
952   /*
953      FIXME: we've found a bug prevalent in drivers for the "Intel
954      Solano" graphcis chipset / driver. It manifests itself in the way
955      that visual artifacts are seen when multi-textured polygons are
956      partly outside the canvas view.
957 
958      The SoGuiExamples/nodes/textureunit example can be used to
959      reproduce the error. The driver info from one confirmed affected
960      system is as follows:
961 
962      GL_VERSION == 1.1.2 - Build 4.13.01.3196
963      GL_VENDOR == Intel
964      GL_RENDERER == Intel Solano
965      GL_EXTENSIONS = GL_ARB_multitexture [...]
966 
967      This problem is not yet handled in any way by Coin. What we
968      should do about this is to detect the above chipset / driver and
969      issue an on-screen warning to the end user (in very
970      "end-user-friendly" terms) when multi-texturing is first
971      attempted used, *plus* make a wgl- or glut-based example which
972      demonstrates the bug, for reporting to Intel.
973 
974      The bug was tested and confirmed with the latest Intel Solano
975      driver as of today.
976 
977      20041108 mortene, based on information provided by handegar.
978   */
979   w->glActiveTexture = NULL;
980   w->glClientActiveTexture = NULL;
981   w->glMultiTexCoord2f = NULL;
982   w->glMultiTexCoord2fv = NULL;
983   w->glMultiTexCoord3fv = NULL;
984   w->glMultiTexCoord4fv = NULL;
985 #ifdef GL_VERSION_1_3
986   if (cc_glglue_glversion_matches_at_least(w, 1, 3, 0)) {
987     w->glActiveTexture = (COIN_PFNGLACTIVETEXTUREPROC)PROC(w, glActiveTexture);
988     w->glClientActiveTexture = (COIN_PFNGLCLIENTACTIVETEXTUREPROC)PROC(w, glClientActiveTexture);
989     w->glMultiTexCoord2f = (COIN_PFNGLMULTITEXCOORD2FPROC)PROC(w, glMultiTexCoord2f);
990     w->glMultiTexCoord2fv = (COIN_PFNGLMULTITEXCOORD2FVPROC)PROC(w, glMultiTexCoord2fv);
991     w->glMultiTexCoord3fv = (COIN_PFNGLMULTITEXCOORD3FVPROC)PROC(w, glMultiTexCoord3fv);
992     w->glMultiTexCoord4fv = (COIN_PFNGLMULTITEXCOORD4FVPROC)PROC(w, glMultiTexCoord4fv);
993   }
994 #endif /* GL_VERSION_1_3 */
995 #ifdef GL_ARB_multitexture
996   if (!w->glActiveTexture && cc_glglue_glext_supported(w, "GL_ARB_multitexture")) {
997     w->glActiveTexture = (COIN_PFNGLACTIVETEXTUREPROC)PROC(w, glActiveTextureARB);
998     w->glClientActiveTexture = (COIN_PFNGLACTIVETEXTUREPROC)PROC(w, glClientActiveTextureARB);
999     w->glMultiTexCoord2f = (COIN_PFNGLMULTITEXCOORD2FPROC)PROC(w, glMultiTexCoord2fARB);
1000     w->glMultiTexCoord2fv = (COIN_PFNGLMULTITEXCOORD2FVPROC)PROC(w, glMultiTexCoord2fvARB);
1001     w->glMultiTexCoord3fv = (COIN_PFNGLMULTITEXCOORD3FVPROC)PROC(w, glMultiTexCoord3fvARB);
1002     w->glMultiTexCoord4fv = (COIN_PFNGLMULTITEXCOORD4FVPROC)PROC(w, glMultiTexCoord4fvARB);
1003   }
1004 #endif /* GL_ARB_multitexture */
1005 
1006   if (w->glActiveTexture) {
1007     if (!w->glClientActiveTexture ||
1008         !w->glMultiTexCoord2f ||
1009         !w->glMultiTexCoord2fv ||
1010         !w->glMultiTexCoord3fv ||
1011         !w->glMultiTexCoord4fv) {
1012       w->glActiveTexture = NULL; /* cc_glglue_has_multitexture() will return FALSE */
1013       if (COIN_DEBUG || coin_glglue_debug()) {
1014         cc_debugerror_postwarning("glglue_init",
1015                                   "glActiveTexture found, but one or more of the other "
1016                                   "multitexture functions were not found");
1017       }
1018     }
1019   }
1020   w->maxtextureunits = 1; /* when multitexturing is not available */
1021   if (w->glActiveTexture) {
1022     GLint tmp;
1023     glGetIntegerv(GL_MAX_TEXTURE_COORDS_ARB, &tmp);
1024     w->maxtextureunits = (int) tmp;
1025   }
1026 
1027   w->glCompressedTexImage1D = NULL;
1028   w->glCompressedTexImage2D = NULL;
1029   w->glCompressedTexImage3D = NULL;
1030   w->glCompressedTexSubImage1D = NULL;
1031   w->glCompressedTexSubImage2D = NULL;
1032   w->glCompressedTexSubImage3D = NULL;
1033   w->glGetCompressedTexImage = NULL;
1034 
1035 #ifdef GL_VERSION_1_3
1036   if (cc_glglue_glversion_matches_at_least(w, 1, 3, 0)) {
1037     w->glCompressedTexImage1D = (COIN_PFNGLCOMPRESSEDTEXIMAGE1DPROC)PROC(w, glCompressedTexImage1D);
1038     w->glCompressedTexImage2D = (COIN_PFNGLCOMPRESSEDTEXIMAGE2DPROC)PROC(w, glCompressedTexImage2D);
1039     w->glCompressedTexImage3D = (COIN_PFNGLCOMPRESSEDTEXIMAGE3DPROC)PROC(w, glCompressedTexImage3D);
1040     w->glCompressedTexSubImage1D = (COIN_PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)PROC(w, glCompressedTexSubImage1D);
1041     w->glCompressedTexSubImage2D = (COIN_PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)PROC(w, glCompressedTexSubImage2D);
1042     w->glCompressedTexSubImage3D = (COIN_PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)PROC(w, glCompressedTexSubImage3D);
1043     w->glGetCompressedTexImage = (COIN_PFNGLGETCOMPRESSEDTEXIMAGEPROC)PROC(w, glGetCompressedTexImage);
1044   }
1045 #endif /* GL_VERSION_1_3 */
1046 
1047 #ifdef GL_ARB_texture_compression
1048   if ((w->glCompressedTexImage1D == NULL) &&
1049       cc_glglue_glext_supported(w, "GL_ARB_texture_compression")) {
1050     w->glCompressedTexImage1D = (COIN_PFNGLCOMPRESSEDTEXIMAGE1DPROC)PROC(w, glCompressedTexImage1DARB);
1051     w->glCompressedTexImage2D = (COIN_PFNGLCOMPRESSEDTEXIMAGE2DPROC)PROC(w, glCompressedTexImage2DARB);
1052     w->glCompressedTexImage3D = (COIN_PFNGLCOMPRESSEDTEXIMAGE3DPROC)PROC(w, glCompressedTexImage3DARB);
1053     w->glCompressedTexSubImage1D = (COIN_PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)PROC(w, glCompressedTexSubImage1DARB);
1054     w->glCompressedTexSubImage2D = (COIN_PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)PROC(w, glCompressedTexSubImage2DARB);
1055     w->glCompressedTexSubImage3D = (COIN_PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)PROC(w, glCompressedTexSubImage3DARB);
1056     w->glGetCompressedTexImage = (COIN_PFNGLGETCOMPRESSEDTEXIMAGEPROC)PROC(w, glGetCompressedTexImageARB);
1057   }
1058 #endif /* GL_ARB_texture_compression */
1059 
1060   w->glColorTable = NULL;
1061   w->glColorSubTable = NULL;
1062   w->glGetColorTable = NULL;
1063   w->glGetColorTableParameteriv = NULL;
1064   w->glGetColorTableParameterfv = NULL;
1065 
1066 #if defined(GL_VERSION_1_2) && defined(GL_ARB_imaging)
1067   if (cc_glglue_glversion_matches_at_least(w, 1, 2, 0) &&
1068       cc_glglue_glext_supported(w, "GL_ARB_imaging")) {
1069     w->glColorTable = (COIN_PFNGLCOLORTABLEPROC)PROC(w, glColorTable);
1070     w->glColorSubTable = (COIN_PFNGLCOLORSUBTABLEPROC)PROC(w, glColorSubTable);
1071     w->glGetColorTable = (COIN_PFNGLGETCOLORTABLEPROC)PROC(w, glGetColorTable);
1072     w->glGetColorTableParameteriv = (COIN_PFNGLGETCOLORTABLEPARAMETERIVPROC)PROC(w, glGetColorTableParameteriv);
1073     w->glGetColorTableParameterfv = (COIN_PFNGLGETCOLORTABLEPARAMETERFVPROC)PROC(w, glGetColorTableParameterfv);
1074   }
1075 #endif /* GL_VERSION_1_2 && GL_ARB_imaging */
1076 
1077 #if defined(GL_EXT_color_table)
1078   if ((w->glColorTable == NULL) &&
1079       cc_glglue_glext_supported(w, "GL_EXT_color_table")) {
1080     w->glColorTable = (COIN_PFNGLCOLORTABLEPROC)PROC(w, glColorTableEXT);
1081     w->glGetColorTable = (COIN_PFNGLGETCOLORTABLEPROC)PROC(w, glGetColorTableEXT);
1082     w->glGetColorTableParameteriv = (COIN_PFNGLGETCOLORTABLEPARAMETERIVPROC)PROC(w, glGetColorTableParameterivEXT);
1083     w->glGetColorTableParameterfv = (COIN_PFNGLGETCOLORTABLEPARAMETERFVPROC)PROC(w, glGetColorTableParameterfvEXT);
1084   }
1085 #endif /* GL_EXT_color_table */
1086 
1087 #if defined(GL_SGI_color_table)
1088   if ((w->glColorTable == NULL) &&
1089       cc_glglue_glext_supported(w, "GL_SGI_color_table")) {
1090     w->glColorTable = (COIN_PFNGLCOLORTABLEPROC)PROC(w, glColorTableSGI);
1091     w->glGetColorTable = (COIN_PFNGLGETCOLORTABLEPROC)PROC(w, glGetColorTableSGI);
1092     w->glGetColorTableParameteriv = (COIN_PFNGLGETCOLORTABLEPARAMETERIVPROC)PROC(w, glGetColorTableParameterivSGI);
1093     w->glGetColorTableParameterfv = (COIN_PFNGLGETCOLORTABLEPARAMETERFVPROC)PROC(w, glGetColorTableParameterfvSGI);
1094   }
1095 #endif /* GL_SGI_color_table */
1096 
1097 #if defined(GL_EXT_color_subtable)
1098   if ((w->glColorSubTable == NULL) &&
1099       cc_glglue_glext_supported(w, "GL_EXT_color_subtable")) {
1100     w->glColorSubTable = (COIN_PFNGLCOLORSUBTABLEPROC)PROC(w, glColorSubTableEXT);
1101   }
1102 #endif /* GL_EXT_color_subtable */
1103 
1104   w->supportsPalettedTextures =
1105     cc_glglue_glext_supported(w, "GL_EXT_paletted_texture");
1106   /* FIXME: is paletted textures _really_ not supported through any
1107      non-extension mechanism for the later OpenGL spec versions?
1108      Investigate. 20031027 mortene. */
1109 
1110 #ifdef GL_EXT_paletted_texture
1111   /* Note that EXT_paletted_texture defines glColorTableEXT et al
1112      "on it's own", i.e. it doesn't need the presence of
1113      EXT_color_table / SGI_color_table / OGL1.2+ + ARB_imaging. It
1114      only defines a *subset* of what EXT_color_table etc defines,
1115      though. */
1116   if ((w->glColorTable == NULL) &&
1117       cc_glglue_glext_supported(w, "GL_EXT_paletted_texture")) {
1118     w->glColorTable = (COIN_PFNGLCOLORTABLEPROC)PROC(w, glColorTableEXT);
1119     w->glColorSubTable = (COIN_PFNGLCOLORSUBTABLEPROC)PROC(w, glColorSubTableEXT);
1120     w->glGetColorTable = (COIN_PFNGLGETCOLORTABLEPROC)PROC(w, glGetColorTableEXT);
1121     w->glGetColorTableParameteriv = (COIN_PFNGLGETCOLORTABLEPARAMETERIVPROC)PROC(w, glGetColorTableParameterivEXT);
1122     w->glGetColorTableParameterfv = (COIN_PFNGLGETCOLORTABLEPARAMETERFVPROC)PROC(w, glGetColorTableParameterfvEXT);
1123   }
1124 #endif /* GL_EXT_paletted_texture */
1125 
1126   /*
1127     Using the SGI_texture_color_table extension has been temporarily
1128     disabled, as it uses a different enum value for
1129     glColorTable(<target>,...), and seems to only support 2D
1130     textures. Quoting from the extension spec document:
1131 
1132         Accepted by the <cap> parameter of Enable, Disable, and
1133         IsEnabled, [...] and by the <target> parameter of
1134         ColorTableSGI, CopyColorTableSGI, GetColorTableSGI,
1135         ColorTableParameterfvSGI, ColorTableParameterivSGI,
1136         GetColorTableParameterfvSGI, GetColorTableParameterivSGI:
1137 
1138         TEXTURE_COLOR_TABLE_SGI         0x80BC
1139 
1140         Accepted by the <target> parameter of ColorTableSGI,
1141         GetColorTableParameterivSGI, and GetColorTableParameterfvSGI:
1142 
1143         PROXY_TEXTURE_COLOR_TABLE_SGI   0x80BD
1144 
1145     As paletted textures can only be supported through extensions, we
1146     should probably implement support for using this one in addition
1147     to EXT_paletted_texture.
1148 
1149     Note: our O2 supports this extension, but not
1150     EXT_paletted_texture, so it can be used for development and
1151     testing of support for this extension.
1152 
1153     20030129 mortene.
1154    */
1155 #if 0
1156   w->supportsPalettedTextures = w->supportsPalettedTextures ||
1157     cc_glglue_glext_supported(w, "GL_SGI_texture_color_table");
1158 
1159 #ifdef GL_SGI_texture_color_table
1160   /* Note that SGI_texture_color_table defines glColorTableEXT et al
1161      "on it's own", i.e. it doesn't need the presence of
1162      EXT_color_table / SGI_color_table / OGL1.2+ + ARB_imaging. It
1163      only defines a *subset* of what EXT_color_table etc defines,
1164      though. */
1165   if ((w->glColorTable == NULL) &&
1166       cc_glglue_glext_supported(w, "GL_SGI_texture_color_table")) {
1167     w->glColorTable = (COIN_PFNGLCOLORTABLEPROC)PROC(w, glColorTableSGI);
1168     w->glGetColorTable = (COIN_PFNGLGETCOLORTABLEPROC)PROC(w, glGetColorTableSGI);
1169     w->glGetColorTableParameteriv = (COIN_PFNGLGETCOLORTABLEPARAMETERIVPROC)PROC(w, glGetColorTableParameterivSGI);
1170     w->glGetColorTableParameterfv = (COIN_PFNGLGETCOLORTABLEPARAMETERFVPROC)PROC(w, glGetColorTableParameterfvSGI);
1171   }
1172 #endif /* GL_SGI_texture_color_table */
1173 #endif /* disabled */
1174 
1175 
1176   w->glBlendEquation = NULL;
1177   w->glBlendEquationEXT = NULL;
1178 
1179 #if defined(GL_VERSION_1_4)
1180   if (cc_glglue_glversion_matches_at_least(w, 1, 4, 0)) {
1181     w->glBlendEquation = (COIN_PFNGLBLENDEQUATIONPROC)PROC(w, glBlendEquation);
1182   }
1183 #endif /* GL_VERSION_1_4 */
1184 
1185   if (w->glBlendEquation == NULL) {
1186 #if defined(GL_VERSION_1_2) && defined(GL_ARB_imaging)
1187     if (cc_glglue_glversion_matches_at_least(w, 1, 2, 0) &&
1188         cc_glglue_glext_supported(w, "GL_ARB_imaging")) {
1189       w->glBlendEquation = (COIN_PFNGLBLENDEQUATIONPROC)PROC(w, glBlendEquation);
1190     }
1191 #endif /* GL_VERSION_1_2 && GL_ARB_imaging */
1192   }
1193 
1194 #ifdef GL_EXT_blend_minmax
1195   if (cc_glglue_glext_supported(w, "GL_EXT_blend_minmax")) {
1196     w->glBlendEquationEXT = (COIN_PFNGLBLENDEQUATIONPROC)PROC(w, glBlendEquationEXT);
1197   }
1198 #endif /* GL_EXT_blend_minmax */
1199 
1200   w->glBlendFuncSeparate = NULL;
1201 #if defined(GL_VERSION_1_4)
1202   if (cc_glglue_glversion_matches_at_least(w, 1, 4, 0)) {
1203     w->glBlendFuncSeparate = (COIN_PFNGLBLENDFUNCSEPARATEPROC)PROC(w, glBlendFuncSeparate);
1204   }
1205 #endif /* GL_VERSION_1_4 */
1206 
1207   w->glVertexPointer = NULL; /* for cc_glglue_has_vertex_array() */
1208 #if defined(GL_VERSION_1_1)
1209   if (cc_glglue_glversion_matches_at_least(w, 1, 1, 0)) {
1210     w->glVertexPointer = (COIN_PFNGLVERTEXPOINTERPROC) PROC(w, glVertexPointer);
1211     w->glTexCoordPointer = (COIN_PFNGLTEXCOORDPOINTERPROC) PROC(w, glTexCoordPointer);
1212     w->glNormalPointer = (COIN_PFNGLNORMALPOINTERPROC) PROC(w, glNormalPointer);
1213     w->glColorPointer = (COIN_PNFGLCOLORPOINTERPROC) PROC(w, glColorPointer);
1214     w->glIndexPointer = (COIN_PFNGLINDEXPOINTERPROC) PROC(w, glIndexPointer);
1215     w->glEnableClientState = (COIN_PFNGLENABLECLIENTSTATEPROC) PROC(w, glEnableClientState);
1216     w->glDisableClientState = (COIN_PFNGLDISABLECLIENTSTATEPROC) PROC(w, glDisableClientState);
1217     w->glInterleavedArrays = (COIN_PFNGLINTERLEAVEDARRAYSPROC) PROC(w, glInterleavedArrays);
1218     w->glDrawArrays = (COIN_PFNGLDRAWARRAYSPROC) PROC(w, glDrawArrays);
1219     w->glDrawElements = (COIN_PFNGLDRAWELEMENTSPROC) PROC(w, glDrawElements);
1220     w->glArrayElement = (COIN_PFNGLARRAYELEMENTPROC) PROC(w, glArrayElement);
1221   }
1222   if (w->glVertexPointer) {
1223     if (!w->glTexCoordPointer ||
1224         !w->glNormalPointer ||
1225         !w->glColorPointer ||
1226         !w->glIndexPointer ||
1227         !w->glEnableClientState ||
1228         !w->glDisableClientState ||
1229         !w->glInterleavedArrays ||
1230         !w->glDrawArrays ||
1231         !w->glDrawElements ||
1232         !w->glArrayElement) {
1233       w->glVertexPointer = NULL; /* cc_glglue_has_vertex_array() will return FALSE */
1234       if (COIN_DEBUG || coin_glglue_debug()) {
1235         cc_debugerror_postwarning("glglue_init",
1236                                   "glVertexPointer found, but one or more of the other "
1237                                   "vertex array functions were not found");
1238       }
1239     }
1240   }
1241 #endif /* GL_VERSION_1_1 */
1242 
1243 
1244 #if defined(GL_VERSION_1_2)
1245   w->glDrawRangeElements = NULL;
1246   if (cc_glglue_glversion_matches_at_least(w, 1, 2, 0))
1247     w->glDrawRangeElements = (COIN_PFNGLDRAWRANGEELEMENTSPROC) PROC(w, glDrawRangeElements);
1248 #endif /* GL_VERSION_1_2 */
1249 
1250 
1251   /* Appeared in OpenGL v1.4 (but also in GL_EXT_multi_draw_array extension */
1252   w->glMultiDrawArrays = NULL;
1253   w->glMultiDrawElements = NULL;
1254 #if defined(GL_VERSION_1_4)
1255   if (cc_glglue_glversion_matches_at_least(w, 1, 4, 0)) {
1256     w->glMultiDrawArrays = (COIN_PFNGLMULTIDRAWARRAYSPROC) PROC(w, glMultiDrawArrays);
1257     w->glMultiDrawElements = (COIN_PFNGLMULTIDRAWELEMENTSPROC) PROC(w, glMultiDrawElements);
1258   }
1259 #endif /* GL_VERSION_1_4 */
1260 #if defined(GL_EXT_multi_draw_arrays)
1261   if ((w->glMultiDrawArrays == NULL) && cc_glglue_glext_supported(w, "GL_EXT_multi_draw_arrays")) {
1262     w->glMultiDrawArrays = (COIN_PFNGLMULTIDRAWARRAYSPROC) PROC(w, glMultiDrawArraysEXT);
1263     w->glMultiDrawElements = (COIN_PFNGLMULTIDRAWELEMENTSPROC) PROC(w, glMultiDrawElementsEXT);
1264   }
1265 #endif /* GL_EXT_multi_draw_arrays */
1266 
1267   w->glBindBuffer = NULL; /* so that cc_glglue_has_vertex_buffer_objects() works  */
1268 #if defined(GL_VERSION_1_5)
1269   if (cc_glglue_glversion_matches_at_least(w, 1, 5, 0)) {
1270     w->glBindBuffer = (COIN_PFNGLBINDBUFFERPROC) PROC(w, glBindBuffer);
1271     w->glDeleteBuffers = (COIN_PFNGLDELETEBUFFERSPROC) PROC(w, glDeleteBuffers);
1272     w->glGenBuffers = (COIN_PFNGLGENBUFFERSPROC) PROC(w, glGenBuffers);
1273     w->glIsBuffer = (COIN_PFNGLISBUFFERPROC) PROC(w, glIsBuffer);
1274     w->glBufferData = (COIN_PFNGLBUFFERDATAPROC) PROC(w, glBufferData);
1275     w->glBufferSubData = (COIN_PFNGLBUFFERSUBDATAPROC) PROC(w, glBufferSubData);
1276     w->glGetBufferSubData = (COIN_PFNGLGETBUFFERSUBDATAPROC) PROC(w, glGetBufferSubData);
1277     w->glMapBuffer = (COIN_PNFGLMAPBUFFERPROC) PROC(w, glMapBuffer);
1278     w->glUnmapBuffer = (COIN_PFNGLUNMAPBUFFERPROC) PROC(w, glUnmapBuffer);
1279     w->glGetBufferParameteriv = (COIN_PFNGLGETBUFFERPARAMETERIVPROC) PROC(w, glGetBufferParameteriv);
1280     w->glGetBufferPointerv = (COIN_PFNGLGETBUFFERPOINTERVPROC) PROC(w, glGetBufferPointerv);
1281   }
1282 #endif /* GL_VERSION_1_5 */
1283 
1284 #if defined(GL_ARB_vertex_buffer_object)
1285   if ((w->glBindBuffer == NULL) && cc_glglue_glext_supported(w, "GL_ARB_vertex_buffer_object")) {
1286     w->glBindBuffer = (COIN_PFNGLBINDBUFFERPROC) PROC(w, glBindBufferARB);
1287     w->glDeleteBuffers = (COIN_PFNGLDELETEBUFFERSPROC) PROC(w, glDeleteBuffersARB);
1288     w->glGenBuffers = (COIN_PFNGLGENBUFFERSPROC) PROC(w, glGenBuffersARB);
1289     w->glIsBuffer = (COIN_PFNGLISBUFFERPROC) PROC(w, glIsBufferARB);
1290     w->glBufferData = (COIN_PFNGLBUFFERDATAPROC) PROC(w, glBufferDataARB);
1291     w->glBufferSubData = (COIN_PFNGLBUFFERSUBDATAPROC) PROC(w, glBufferSubDataARB);
1292     w->glGetBufferSubData = (COIN_PFNGLGETBUFFERSUBDATAPROC) PROC(w, glGetBufferSubDataARB);
1293     w->glMapBuffer = (COIN_PNFGLMAPBUFFERPROC) PROC(w, glMapBufferARB);
1294     w->glUnmapBuffer = (COIN_PFNGLUNMAPBUFFERPROC) PROC(w, glUnmapBufferARB);
1295     w->glGetBufferParameteriv = (COIN_PFNGLGETBUFFERPARAMETERIVPROC) PROC(w, glGetBufferParameterivARB);
1296     w->glGetBufferPointerv = (COIN_PFNGLGETBUFFERPOINTERVPROC) PROC(w, glGetBufferPointervARB);
1297   }
1298 
1299 #if defined(HAVE_GLX)
1300   /* ARB_vertex_buffer_object does not work properly on Linux when
1301      using the Nvidia 44.96 driver (version 1.4.0). The VBO extension
1302      is therefore disabled for this driver. The issue was solved for
1303      the 53.28 driver (version 1.4.1). */
1304   if (!strcmp(w->vendorstr, "NVIDIA Corporation")) {
1305     if (!cc_glglue_glversion_matches_at_least(w, 1, 4, 1)) {
1306       w->glBindBuffer = NULL;
1307     }
1308     /* VBOs seems really slow on the GeForce4 Go GPUs, but this test
1309        is disabled for now until we know for sure that VBOs will
1310        always be slow for this GPU */
1311     /*     else if (strstr(w->rendererstr, "GeForce4 420 Go")) { */
1312     /*       w->glBindBuffer = NULL; */
1313     /*     } */
1314     /* FIXME: I guess the above has been made obsolete by the VBO
1315        performance testing we now do..? pederb should confirm.
1316        20061027 mortene. */
1317   }
1318 #endif
1319 
1320   /* VBO support has been found to often trigger bugs in OpenGL
1321      drivers, so we make it possible to selectively disable that
1322      feature through an envvar.
1323 
1324      (Specifically, I've seen the following driver crash when using
1325      VBOs in an offscreen context: GL_RENDERER="GeForce 7950
1326      GX2/PCI/SSE2", GL_VERSION="2.0.2 NVIDIA 87.62", on an AMD64 with
1327      Linux. On-screen contexts with VBOs was ok on the exact same
1328      machine. -mortene.)
1329   */
1330   if (w->glBindBuffer) {
1331     const char * env = coin_getenv("COIN_GL_DISABLE_VBO");
1332     if (env && (atoi(env) > 0)) { w->glBindBuffer = NULL; }
1333   }
1334 
1335 
1336   /*
1337     All Intel drivers usually crash when we try to use VBO. This might be a bug in
1338     our VBO code, but we choose to disable VBO rendering for all Intel cards until
1339     we have time to look into this. pederb, 2007-08-16
1340   */
1341 
1342   if (w->glBindBuffer) {
1343     if (coin_runtime_os() != COIN_OS_X) { /* Apple has proper drivers */
1344       /* Enable users to override this workaround by setting COIN_VBO=1 */
1345       const char * env = coin_getenv("COIN_VBO");
1346       if (!env || (atoi(env) > 0)) {
1347         if (w->vendor_is_intel) {
1348           w->glBindBuffer = NULL;
1349         }
1350       }
1351     }
1352   }
1353 
1354   /*
1355     Sylvain Carette reported problems with some old 3DLabs drivers and VBO rendering.
1356     The drivers were from 2006, so we disable VBO rendering if 3DLabs and that driver
1357     version is detected (the driver version was 2.0)
1358    */
1359   if (w->glBindBuffer && w->vendor_is_3dlabs
1360       && !cc_glglue_glversion_matches_at_least(w, 2,0,1)) {
1361     /* Enable users to override this workaround by setting COIN_VBO=1 */
1362     const char * env = coin_getenv("COIN_VBO");
1363     if (!env || (atoi(env) > 0)) {
1364       w->glBindBuffer = NULL;
1365     }
1366   }
1367 
1368 #endif /* GL_ARB_vertex_buffer_object */
1369 
1370   if (w->glBindBuffer) {
1371     if (!w->glDeleteBuffers ||
1372         !w->glGenBuffers ||
1373         !w->glIsBuffer ||
1374         !w->glBufferData ||
1375         !w->glBufferSubData ||
1376         !w->glGetBufferSubData ||
1377         !w->glMapBuffer ||
1378         !w->glUnmapBuffer ||
1379         !w->glGetBufferParameteriv ||
1380         !w->glGetBufferPointerv) {
1381       w->glBindBuffer = NULL; /* so that cc_glglue_has_vertex_buffer_object() will return FALSE */
1382       if (COIN_DEBUG || coin_glglue_debug()) {
1383         cc_debugerror_postwarning("glglue_init",
1384                                   "glBindBuffer found, but one or more of the other "
1385                                   "vertex buffer object functions were not found");
1386       }
1387     }
1388   }
1389 
1390   /* GL_NV_register_combiners */
1391   w->glCombinerParameterfvNV = NULL;
1392   w->glCombinerParameterivNV = NULL;
1393   w->glCombinerParameterfNV = NULL;
1394   w->glCombinerParameteriNV = NULL;
1395   w->glCombinerInputNV = NULL;
1396   w->glCombinerOutputNV = NULL;
1397   w->glFinalCombinerInputNV = NULL;
1398   w->glGetCombinerInputParameterfvNV = NULL;
1399   w->glGetCombinerInputParameterivNV = NULL;
1400   w->glGetCombinerOutputParameterfvNV = NULL;
1401   w->glGetCombinerOutputParameterivNV = NULL;
1402   w->glGetFinalCombinerInputParameterfvNV = NULL;
1403   w->glGetFinalCombinerInputParameterivNV = NULL;
1404   w->has_nv_register_combiners = FALSE;
1405 
1406 #ifdef GL_NV_register_combiners
1407 
1408   if (cc_glglue_glext_supported(w, "GL_NV_register_combiners")) {
1409 
1410 #define BIND_FUNCTION_WITH_WARN(_func_, _type_) \
1411    w->_func_ = (_type_)PROC(w, _func_); \
1412    do { \
1413      if (!w->_func_) { \
1414        w->has_nv_register_combiners = FALSE; \
1415        if (COIN_DEBUG || coin_glglue_debug()) { \
1416          static SbBool error_reported = FALSE; \
1417          if (!error_reported) { \
1418            cc_debugerror_postwarning("glglue_init", \
1419                                      "GL_NV_register_combiners found, but %s " \
1420                                      "function missing.", SO__QUOTE(_func_)); \
1421            error_reported = TRUE; \
1422          } \
1423        } \
1424      } \
1425    } while (0)
1426 
1427     w->has_nv_register_combiners = TRUE;
1428     BIND_FUNCTION_WITH_WARN(glCombinerParameterfvNV, COIN_PFNGLCOMBINERPARAMETERFVNVPROC);
1429     BIND_FUNCTION_WITH_WARN(glCombinerParameterivNV, COIN_PFNGLCOMBINERPARAMETERIVNVPROC);
1430     BIND_FUNCTION_WITH_WARN(glCombinerParameterfNV, COIN_PFNGLCOMBINERPARAMETERFNVPROC);
1431     BIND_FUNCTION_WITH_WARN(glCombinerParameteriNV, COIN_PFNGLCOMBINERPARAMETERINVPROC);
1432     BIND_FUNCTION_WITH_WARN(glCombinerInputNV, COIN_PFNGLCOMBINERINPUTNVPROC);
1433     BIND_FUNCTION_WITH_WARN(glCombinerOutputNV, COIN_PFNGLCOMBINEROUTPUTNVPROC);
1434     BIND_FUNCTION_WITH_WARN(glFinalCombinerInputNV, COIN_PFNGLFINALCOMBINERINPUTNVPROC);
1435     BIND_FUNCTION_WITH_WARN(glGetCombinerInputParameterfvNV, COIN_PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC);
1436     BIND_FUNCTION_WITH_WARN(glGetCombinerInputParameterivNV, COIN_PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC);
1437     BIND_FUNCTION_WITH_WARN(glGetCombinerOutputParameterfvNV, COIN_PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC);
1438     BIND_FUNCTION_WITH_WARN(glGetCombinerOutputParameterivNV, COIN_PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC);
1439     BIND_FUNCTION_WITH_WARN(glGetFinalCombinerInputParameterfvNV, COIN_PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC);
1440     BIND_FUNCTION_WITH_WARN(glGetFinalCombinerInputParameterivNV, COIN_PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC);
1441 
1442 #undef BIND_FUNCTION_WITH_WARN
1443   }
1444 #endif /* GL_NV_register_combiners */
1445 
1446 
1447   /* GL_[NV/EXT]_texture_rectangle */
1448   w->has_ext_texture_rectangle = (cc_glglue_glext_supported(w, "GL_EXT_texture_rectangle") ||
1449                                   cc_glglue_glext_supported(w, "GL_NV_texture_rectangle"));
1450 
1451   /* GL_NV_texture_shader */
1452   w->has_nv_texture_shader = cc_glglue_glext_supported(w, "GL_NV_texture_shader");
1453 
1454   /* GL_ARB_shadow */
1455   w->has_shadow = (cc_glglue_glext_supported(w, "GL_ARB_shadow") ||
1456                    cc_glglue_glversion_matches_at_least(w, 1, 4, 0));
1457 
1458   /* GL_ARB_depth_texture */
1459   w->has_depth_texture = (cc_glglue_glext_supported(w, "GL_ARB_depth_texture") ||
1460                           cc_glglue_glversion_matches_at_least(w, 1, 4, 0));
1461 
1462   /* GL_[ARB/EXT]_texture_env_combine */
1463   w->has_texture_env_combine = (cc_glglue_glext_supported(w, "GL_ARB_texture_env_combine") ||
1464                                 cc_glglue_glext_supported(w, "GL_EXT_texture_env_combine") ||
1465                                 cc_glglue_glversion_matches_at_least(w, 1, 3, 0));
1466 
1467   /* GL_ARB_fragment_program */
1468   w->glProgramStringARB = NULL;
1469   w->glBindProgramARB = NULL;
1470   w->glDeleteProgramsARB = NULL;
1471   w->glGenProgramsARB = NULL;
1472   w->glProgramEnvParameter4dARB = NULL;
1473   w->glProgramEnvParameter4dvARB = NULL;
1474   w->glProgramEnvParameter4fARB = NULL;
1475   w->glProgramEnvParameter4fvARB = NULL;
1476   w->glProgramLocalParameter4dARB = NULL;
1477   w->glProgramLocalParameter4dvARB = NULL;
1478   w->glProgramLocalParameter4fARB = NULL;
1479   w->glProgramLocalParameter4fvARB = NULL;
1480   w->glGetProgramEnvParameterdvARB = NULL;
1481   w->glGetProgramEnvParameterfvARB = NULL;
1482   w->glGetProgramLocalParameterdvARB = NULL;
1483   w->glGetProgramLocalParameterfvARB = NULL;
1484   w->glGetProgramivARB = NULL;
1485   w->glGetProgramStringARB = NULL;
1486   w->glIsProgramARB = NULL;
1487   w->has_arb_fragment_program = FALSE;
1488 
1489 #ifdef GL_ARB_fragment_program
1490   if (cc_glglue_glext_supported(w, "GL_ARB_fragment_program")) {
1491 
1492 #define BIND_FUNCTION_WITH_WARN(_func_, _type_) \
1493    w->_func_ = (_type_)PROC(w, _func_); \
1494    do { \
1495      if (!w->_func_) { \
1496        w->has_arb_fragment_program = FALSE; \
1497        if (COIN_DEBUG || coin_glglue_debug()) { \
1498          static SbBool error_reported = FALSE; \
1499          if (!error_reported) { \
1500            cc_debugerror_postwarning("glglue_init", \
1501                                      "GL_ARB_fragment_program found, but %s " \
1502                                      "function missing.", SO__QUOTE(_func_)); \
1503            error_reported = TRUE; \
1504          } \
1505        } \
1506      } \
1507    } while (0)
1508 
1509     w->has_arb_fragment_program = TRUE;
1510     BIND_FUNCTION_WITH_WARN(glProgramStringARB, COIN_PFNGLPROGRAMSTRINGARBPROC);
1511     BIND_FUNCTION_WITH_WARN(glBindProgramARB, COIN_PFNGLBINDPROGRAMARBPROC);
1512     BIND_FUNCTION_WITH_WARN(glDeleteProgramsARB, COIN_PFNGLDELETEPROGRAMSARBPROC);
1513     BIND_FUNCTION_WITH_WARN(glGenProgramsARB, COIN_PFNGLGENPROGRAMSARBPROC);
1514     BIND_FUNCTION_WITH_WARN(glProgramEnvParameter4dARB, COIN_PFNGLPROGRAMENVPARAMETER4DARBPROC);
1515     BIND_FUNCTION_WITH_WARN(glProgramEnvParameter4dvARB, COIN_PFNGLPROGRAMENVPARAMETER4DVARBPROC);
1516     BIND_FUNCTION_WITH_WARN(glProgramEnvParameter4fARB, COIN_PFNGLPROGRAMENVPARAMETER4FARBPROC);
1517     BIND_FUNCTION_WITH_WARN(glProgramEnvParameter4fvARB, COIN_PFNGLPROGRAMENVPARAMETER4FVARBPROC);
1518     BIND_FUNCTION_WITH_WARN(glProgramLocalParameter4dARB, COIN_PFNGLPROGRAMLOCALPARAMETER4DARBPROC);
1519     BIND_FUNCTION_WITH_WARN(glProgramLocalParameter4dvARB, COIN_PFNGLPROGRAMLOCALPARAMETER4DVARBPROC);
1520     BIND_FUNCTION_WITH_WARN(glProgramLocalParameter4fARB, COIN_PFNGLPROGRAMLOCALPARAMETER4FARBPROC);
1521     BIND_FUNCTION_WITH_WARN(glProgramLocalParameter4fvARB, COIN_PFNGLPROGRAMLOCALPARAMETER4FVARBPROC);
1522     BIND_FUNCTION_WITH_WARN(glGetProgramEnvParameterdvARB, COIN_PFNGLGETPROGRAMENVPARAMETERDVARBPROC);
1523     BIND_FUNCTION_WITH_WARN(glGetProgramEnvParameterfvARB, COIN_PFNGLGETPROGRAMENVPARAMETERFVARBPROC);
1524     BIND_FUNCTION_WITH_WARN(glGetProgramLocalParameterdvARB, COIN_PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC);
1525     BIND_FUNCTION_WITH_WARN(glGetProgramLocalParameterfvARB, COIN_PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC);
1526     BIND_FUNCTION_WITH_WARN(glGetProgramivARB, COIN_PFNGLGETPROGRAMIVARBPROC);
1527     BIND_FUNCTION_WITH_WARN(glGetProgramStringARB, COIN_PFNGLGETPROGRAMSTRINGARBPROC);
1528     BIND_FUNCTION_WITH_WARN(glIsProgramARB, COIN_PFNGLISPROGRAMARBPROC);
1529 
1530 #undef BIND_FUNCTION_WITH_WARN
1531  }
1532 #endif /* GL_ARB_fragment_program */
1533 
1534   w->has_arb_vertex_program = FALSE;
1535   w->glVertexAttrib1sARB = NULL;
1536   w->glVertexAttrib1fARB = NULL;
1537   w->glVertexAttrib1dARB = NULL;
1538   w->glVertexAttrib2sARB = NULL;
1539   w->glVertexAttrib2fARB = NULL;
1540   w->glVertexAttrib2dARB = NULL;
1541   w->glVertexAttrib3sARB = NULL;
1542   w->glVertexAttrib3fARB = NULL;
1543   w->glVertexAttrib3dARB = NULL;
1544   w->glVertexAttrib4sARB = NULL;
1545   w->glVertexAttrib4fARB = NULL;
1546   w->glVertexAttrib4dARB = NULL;
1547   w->glVertexAttrib4NubARB = NULL;
1548   w->glVertexAttrib1svARB = NULL;
1549   w->glVertexAttrib1fvARB = NULL;
1550   w->glVertexAttrib1dvARB = NULL;
1551   w->glVertexAttrib2svARB = NULL;
1552   w->glVertexAttrib2fvARB = NULL;
1553   w->glVertexAttrib2dvARB = NULL;
1554   w->glVertexAttrib3svARB = NULL;
1555   w->glVertexAttrib3fvARB = NULL;
1556   w->glVertexAttrib3dvARB = NULL;
1557   w->glVertexAttrib4bvARB = NULL;
1558   w->glVertexAttrib4svARB = NULL;
1559   w->glVertexAttrib4ivARB = NULL;
1560   w->glVertexAttrib4ubvARB = NULL;
1561   w->glVertexAttrib4usvARB = NULL;
1562   w->glVertexAttrib4uivARB = NULL;
1563   w->glVertexAttrib4fvARB = NULL;
1564   w->glVertexAttrib4dvARB = NULL;
1565   w->glVertexAttrib4NbvARB = NULL;
1566   w->glVertexAttrib4NsvARB = NULL;
1567   w->glVertexAttrib4NivARB = NULL;
1568   w->glVertexAttrib4NubvARB = NULL;
1569   w->glVertexAttrib4NusvARB = NULL;
1570   w->glVertexAttrib4NuivARB = NULL;
1571   w->glVertexAttribPointerARB = NULL;
1572   w->glEnableVertexAttribArrayARB = NULL;
1573   w->glDisableVertexAttribArrayARB = NULL;
1574   w->glProgramStringARB = NULL;
1575   w->glBindProgramARB = NULL;
1576   w->glDeleteProgramsARB = NULL;
1577   w->glGenProgramsARB = NULL;
1578   w->glProgramEnvParameter4dARB = NULL;
1579   w->glProgramEnvParameter4dvARB = NULL;
1580   w->glProgramEnvParameter4fARB = NULL;
1581   w->glProgramEnvParameter4fvARB = NULL;
1582   w->glProgramLocalParameter4dARB = NULL;
1583   w->glProgramLocalParameter4dvARB = NULL;
1584   w->glProgramLocalParameter4fARB = NULL;
1585   w->glProgramLocalParameter4fvARB = NULL;
1586   w->glGetProgramEnvParameterdvARB = NULL;
1587   w->glGetProgramEnvParameterfvARB = NULL;
1588   w->glGetProgramLocalParameterdvARB = NULL;
1589   w->glGetProgramLocalParameterfvARB = NULL;
1590   w->glGetProgramivARB = NULL;
1591   w->glGetProgramStringARB = NULL;
1592   w->glGetVertexAttribdvARB = NULL;
1593   w->glGetVertexAttribfvARB = NULL;
1594   w->glGetVertexAttribivARB = NULL;
1595   w->glGetVertexAttribPointervARB = NULL;
1596   w->glIsProgramARB = NULL;
1597 
1598 
1599 #ifdef GL_ARB_vertex_program
1600 
1601   if (cc_glglue_glext_supported(w, "GL_ARB_vertex_program")) {
1602 
1603 #define BIND_FUNCTION_WITH_WARN(_func_, _type_) \
1604    w->_func_ = (_type_)PROC(w, _func_); \
1605    do { \
1606      if (!w->_func_) { \
1607        w->has_arb_vertex_program = FALSE; \
1608        if (COIN_DEBUG || coin_glglue_debug()) { \
1609          static SbBool error_reported = FALSE; \
1610          if (!error_reported) { \
1611            cc_debugerror_postwarning("glglue_init", \
1612                                      "GL_ARB_vertex_program found, but %s " \
1613                                      "function missing.", SO__QUOTE(_func_)); \
1614            error_reported = TRUE; \
1615          } \
1616        } \
1617      } \
1618    } while (0)
1619 
1620     w->has_arb_vertex_program = TRUE;
1621     BIND_FUNCTION_WITH_WARN(glVertexAttrib1sARB, COIN_PFNGLVERTEXATTRIB1SARBPROC);
1622     BIND_FUNCTION_WITH_WARN(glVertexAttrib1fARB, COIN_PFNGLVERTEXATTRIB1FARBPROC);
1623     BIND_FUNCTION_WITH_WARN(glVertexAttrib1dARB, COIN_PFNGLVERTEXATTRIB1DARBPROC);
1624     BIND_FUNCTION_WITH_WARN(glVertexAttrib2sARB, COIN_PFNGLVERTEXATTRIB2SARBPROC);
1625     BIND_FUNCTION_WITH_WARN(glVertexAttrib2fARB, COIN_PFNGLVERTEXATTRIB2FARBPROC);
1626     BIND_FUNCTION_WITH_WARN(glVertexAttrib2dARB, COIN_PFNGLVERTEXATTRIB2DARBPROC);
1627     BIND_FUNCTION_WITH_WARN(glVertexAttrib3sARB, COIN_PFNGLVERTEXATTRIB3SARBPROC);
1628     BIND_FUNCTION_WITH_WARN(glVertexAttrib3fARB, COIN_PFNGLVERTEXATTRIB3FARBPROC);
1629     BIND_FUNCTION_WITH_WARN(glVertexAttrib3dARB, COIN_PFNGLVERTEXATTRIB3DARBPROC);
1630     BIND_FUNCTION_WITH_WARN(glVertexAttrib4sARB, COIN_PFNGLVERTEXATTRIB4SARBPROC);
1631     BIND_FUNCTION_WITH_WARN(glVertexAttrib4fARB, COIN_PFNGLVERTEXATTRIB4FARBPROC);
1632     BIND_FUNCTION_WITH_WARN(glVertexAttrib4dARB, COIN_PFNGLVERTEXATTRIB4DARBPROC);
1633     BIND_FUNCTION_WITH_WARN(glVertexAttrib4NubARB, COIN_PFNGLVERTEXATTRIB4NUBARBPROC);
1634     BIND_FUNCTION_WITH_WARN(glVertexAttrib1svARB, COIN_PFNGLVERTEXATTRIB1SVARBPROC);
1635     BIND_FUNCTION_WITH_WARN(glVertexAttrib1fvARB, COIN_PFNGLVERTEXATTRIB1FVARBPROC);
1636     BIND_FUNCTION_WITH_WARN(glVertexAttrib1dvARB, COIN_PFNGLVERTEXATTRIB1DVARBPROC);
1637     BIND_FUNCTION_WITH_WARN(glVertexAttrib2svARB, COIN_PFNGLVERTEXATTRIB2SVARBPROC);
1638     BIND_FUNCTION_WITH_WARN(glVertexAttrib2fvARB, COIN_PFNGLVERTEXATTRIB2FVARBPROC);
1639     BIND_FUNCTION_WITH_WARN(glVertexAttrib2dvARB, COIN_PFNGLVERTEXATTRIB2DVARBPROC);
1640     BIND_FUNCTION_WITH_WARN(glVertexAttrib3svARB, COIN_PFNGLVERTEXATTRIB3SVARBPROC);
1641     BIND_FUNCTION_WITH_WARN(glVertexAttrib3fvARB, COIN_PFNGLVERTEXATTRIB3FVARBPROC);
1642     BIND_FUNCTION_WITH_WARN(glVertexAttrib3dvARB, COIN_PFNGLVERTEXATTRIB3DVARBPROC);
1643     BIND_FUNCTION_WITH_WARN(glVertexAttrib4bvARB, COIN_PFNGLVERTEXATTRIB4BVARBPROC);
1644     BIND_FUNCTION_WITH_WARN(glVertexAttrib4svARB, COIN_PFNGLVERTEXATTRIB4SVARBPROC);
1645     BIND_FUNCTION_WITH_WARN(glVertexAttrib4ivARB, COIN_PFNGLVERTEXATTRIB4IVARBPROC);
1646     BIND_FUNCTION_WITH_WARN(glVertexAttrib4ubvARB, COIN_PFNGLVERTEXATTRIB4UBVARBPROC);
1647     BIND_FUNCTION_WITH_WARN(glVertexAttrib4usvARB, COIN_PFNGLVERTEXATTRIB4USVARBPROC);
1648     BIND_FUNCTION_WITH_WARN(glVertexAttrib4uivARB, COIN_PFNGLVERTEXATTRIB4UIVARBPROC);
1649     BIND_FUNCTION_WITH_WARN(glVertexAttrib4fvARB, COIN_PFNGLVERTEXATTRIB4FVARBPROC);
1650     BIND_FUNCTION_WITH_WARN(glVertexAttrib4dvARB, COIN_PFNGLVERTEXATTRIB4DVARBPROC);
1651     BIND_FUNCTION_WITH_WARN(glVertexAttrib4NbvARB, COIN_PFNGLVERTEXATTRIB4NBVARBPROC);
1652     BIND_FUNCTION_WITH_WARN(glVertexAttrib4NsvARB, COIN_PFNGLVERTEXATTRIB4NSVARBPROC);
1653     BIND_FUNCTION_WITH_WARN(glVertexAttrib4NivARB, COIN_PFNGLVERTEXATTRIB4NIVARBPROC);
1654     BIND_FUNCTION_WITH_WARN(glVertexAttrib4NubvARB, COIN_PFNGLVERTEXATTRIB4NUBVARBPROC);
1655     BIND_FUNCTION_WITH_WARN(glVertexAttrib4NusvARB, COIN_PFNGLVERTEXATTRIB4NUSVARBPROC);
1656     BIND_FUNCTION_WITH_WARN(glVertexAttrib4NuivARB, COIN_PFNGLVERTEXATTRIB4NUIVARBPROC);
1657     BIND_FUNCTION_WITH_WARN(glVertexAttribPointerARB, COIN_PFNGLVERTEXATTRIBPOINTERARBPROC);
1658     BIND_FUNCTION_WITH_WARN(glEnableVertexAttribArrayARB, COIN_PFNGLENABLEVERTEXATTRIBARRAYARBPROC);
1659     BIND_FUNCTION_WITH_WARN(glDisableVertexAttribArrayARB, COIN_PFNGLDISABLEVERTEXATTRIBARRAYARBPROC);
1660     BIND_FUNCTION_WITH_WARN(glProgramStringARB, COIN_PFNGLPROGRAMSTRINGARBPROC);
1661     BIND_FUNCTION_WITH_WARN(glBindProgramARB, COIN_PFNGLBINDPROGRAMARBPROC);
1662     BIND_FUNCTION_WITH_WARN(glDeleteProgramsARB, COIN_PFNGLDELETEPROGRAMSARBPROC);
1663     BIND_FUNCTION_WITH_WARN(glGenProgramsARB, COIN_PFNGLGENPROGRAMSARBPROC);
1664     BIND_FUNCTION_WITH_WARN(glProgramEnvParameter4dARB, COIN_PFNGLPROGRAMENVPARAMETER4DARBPROC);
1665     BIND_FUNCTION_WITH_WARN(glProgramEnvParameter4dvARB, COIN_PFNGLPROGRAMENVPARAMETER4DVARBPROC);
1666     BIND_FUNCTION_WITH_WARN(glProgramEnvParameter4fARB, COIN_PFNGLPROGRAMENVPARAMETER4FARBPROC);
1667     BIND_FUNCTION_WITH_WARN(glProgramEnvParameter4fvARB, COIN_PFNGLPROGRAMENVPARAMETER4FVARBPROC);
1668     BIND_FUNCTION_WITH_WARN(glProgramLocalParameter4dARB, COIN_PFNGLPROGRAMLOCALPARAMETER4DARBPROC);
1669     BIND_FUNCTION_WITH_WARN(glProgramLocalParameter4dvARB, COIN_PFNGLPROGRAMLOCALPARAMETER4DVARBPROC);
1670     BIND_FUNCTION_WITH_WARN(glProgramLocalParameter4fARB, COIN_PFNGLPROGRAMLOCALPARAMETER4FARBPROC);
1671     BIND_FUNCTION_WITH_WARN(glProgramLocalParameter4fvARB, COIN_PFNGLPROGRAMLOCALPARAMETER4FVARBPROC);
1672     BIND_FUNCTION_WITH_WARN(glGetProgramEnvParameterdvARB, COIN_PFNGLGETPROGRAMENVPARAMETERDVARBPROC);
1673     BIND_FUNCTION_WITH_WARN(glGetProgramEnvParameterfvARB, COIN_PFNGLGETPROGRAMENVPARAMETERFVARBPROC);
1674     BIND_FUNCTION_WITH_WARN(glGetProgramLocalParameterdvARB, COIN_PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC);
1675     BIND_FUNCTION_WITH_WARN(glGetProgramLocalParameterfvARB, COIN_PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC);
1676     BIND_FUNCTION_WITH_WARN(glGetProgramivARB, COIN_PFNGLGETPROGRAMIVARBPROC);
1677     BIND_FUNCTION_WITH_WARN(glGetProgramStringARB, COIN_PFNGLGETPROGRAMSTRINGARBPROC);
1678     BIND_FUNCTION_WITH_WARN(glGetVertexAttribdvARB, COIN_PFNGLGETVERTEXATTRIBDVARBPROC);
1679     BIND_FUNCTION_WITH_WARN(glGetVertexAttribfvARB, COIN_PFNGLGETVERTEXATTRIBFVARBPROC);
1680     BIND_FUNCTION_WITH_WARN(glGetVertexAttribivARB, COIN_PFNGLGETVERTEXATTRIBIVARBPROC);
1681     BIND_FUNCTION_WITH_WARN(glGetVertexAttribPointervARB, COIN_PFNGLGETVERTEXATTRIBPOINTERVARBPROC);
1682     BIND_FUNCTION_WITH_WARN(glIsProgramARB, COIN_PFNGLISPROGRAMARBPROC);
1683 
1684 #undef BIND_FUNCTION_WITH_WARN
1685   }
1686 #endif /* GL_ARB_vertex_program */
1687 
1688 
1689 #ifdef GL_ARB_vertex_shader
1690 
1691   w->glBindAttribLocationARB = NULL;
1692   w->glGetActiveAttribARB = NULL;
1693   w->glGetAttribLocationARB = NULL;
1694 
1695   if (cc_glglue_glext_supported(w, "GL_ARB_vertex_shader")) {
1696 
1697 #define BIND_FUNCTION_WITH_WARN(_func_, _type_) \
1698    w->_func_ = (_type_)PROC(w, _func_); \
1699    do { \
1700      if (!w->_func_) { \
1701        w->has_arb_vertex_shader = FALSE; \
1702        if (COIN_DEBUG || coin_glglue_debug()) { \
1703          static SbBool error_reported = FALSE; \
1704          if (!error_reported) { \
1705            cc_debugerror_postwarning("glglue_init", \
1706                                      "GL_ARB_vertex_shader found, but %s " \
1707                                      "function missing.", SO__QUOTE(_func_)); \
1708            error_reported = TRUE; \
1709          } \
1710        } \
1711      } \
1712    } while (0)
1713 
1714     w->has_arb_vertex_shader = TRUE;
1715     BIND_FUNCTION_WITH_WARN(glBindAttribLocationARB, COIN_PFNGLBINDATTRIBLOCATIONARBPROC);
1716     BIND_FUNCTION_WITH_WARN(glGetActiveAttribARB, COIN_PFNGLGETACTIVEATTRIBARBPROC);
1717     BIND_FUNCTION_WITH_WARN(glGetAttribLocationARB, COIN_PFNGLGETATTRIBLOCATIONARBPROC);
1718 
1719 #undef BIND_FUNCTION_WITH_WARN
1720   }
1721 #endif /* GL_ARB_vertex_shader */
1722 
1723 
1724   w->glGetUniformLocationARB = NULL;
1725   w->glGetActiveUniformARB = NULL;
1726   w->glUniform1fARB = NULL;
1727   w->glUniform2fARB = NULL;
1728   w->glUniform3fARB = NULL;
1729   w->glUniform4fARB = NULL;
1730   w->glCreateShaderObjectARB = NULL;
1731   w->glShaderSourceARB = NULL;
1732   w->glCompileShaderARB = NULL;
1733   w->glGetObjectParameterivARB = NULL;
1734   w->glDeleteObjectARB = NULL;
1735   w->glAttachObjectARB = NULL;
1736   w->glDetachObjectARB = NULL;
1737   w->glGetInfoLogARB = NULL;
1738   w->glLinkProgramARB = NULL;
1739   w->glUseProgramObjectARB = NULL;
1740   w->glCreateProgramObjectARB = NULL;
1741   w->has_arb_shader_objects = FALSE;
1742   w->glUniform1fvARB = NULL;
1743   w->glUniform2fvARB = NULL;
1744   w->glUniform3fvARB = NULL;
1745   w->glUniform4fvARB = NULL;
1746   w->glUniform1iARB = NULL;
1747   w->glUniform2iARB = NULL;
1748   w->glUniform3iARB = NULL;
1749   w->glUniform4iARB = NULL;
1750   w->glUniform1ivARB = NULL;
1751   w->glUniform2ivARB = NULL;
1752   w->glUniform3ivARB = NULL;
1753   w->glUniform4ivARB = NULL;
1754   w->glUniformMatrix2fvARB = NULL;
1755   w->glUniformMatrix3fvARB = NULL;
1756   w->glUniformMatrix4fvARB = NULL;
1757 
1758 
1759 #ifdef GL_ARB_shader_objects
1760 
1761   if (cc_glglue_glext_supported(w, "GL_ARB_shader_objects")) {
1762 
1763 #define BIND_FUNCTION_WITH_WARN(_func_, _type_) \
1764    w->_func_ = (_type_)PROC(w, _func_); \
1765    do { \
1766      if (!w->_func_) { \
1767        w->has_arb_shader_objects = FALSE; \
1768        if (COIN_DEBUG || coin_glglue_debug()) { \
1769          static SbBool error_reported = FALSE; \
1770          if (!error_reported) { \
1771            cc_debugerror_postwarning("glglue_init", \
1772                                      "GL_ARB_shader_objects found, but %s " \
1773                                      "function missing.", SO__QUOTE(_func_)); \
1774            error_reported = TRUE; \
1775          } \
1776        } \
1777      } \
1778    } while (0)
1779 
1780     w->has_arb_shader_objects = TRUE;
1781     BIND_FUNCTION_WITH_WARN(glGetUniformLocationARB, COIN_PFNGLGETUNIFORMLOCATIONARBPROC);
1782     BIND_FUNCTION_WITH_WARN(glGetActiveUniformARB, COIN_PFNGLGETACTIVEUNIFORMARBPROC);
1783     BIND_FUNCTION_WITH_WARN(glUniform1fARB, COIN_PFNGLUNIFORM1FARBPROC);
1784     BIND_FUNCTION_WITH_WARN(glUniform2fARB, COIN_PFNGLUNIFORM2FARBPROC);
1785     BIND_FUNCTION_WITH_WARN(glUniform3fARB, COIN_PFNGLUNIFORM3FARBPROC);
1786     BIND_FUNCTION_WITH_WARN(glUniform4fARB, COIN_PFNGLUNIFORM4FARBPROC);
1787     BIND_FUNCTION_WITH_WARN(glCreateShaderObjectARB, COIN_PFNGLCREATESHADEROBJECTARBPROC);
1788     BIND_FUNCTION_WITH_WARN(glShaderSourceARB, COIN_PFNGLSHADERSOURCEARBPROC);
1789     BIND_FUNCTION_WITH_WARN(glCompileShaderARB, COIN_PFNGLCOMPILESHADERARBPROC);
1790     BIND_FUNCTION_WITH_WARN(glGetObjectParameterivARB, COIN_PFNGLGETOBJECTPARAMETERIVARBPROC);
1791     BIND_FUNCTION_WITH_WARN(glDeleteObjectARB, COIN_PFNGLDELETEOBJECTARBPROC);
1792     BIND_FUNCTION_WITH_WARN(glAttachObjectARB, COIN_PFNGLATTACHOBJECTARBPROC);
1793     BIND_FUNCTION_WITH_WARN(glDetachObjectARB, COIN_PFNGLDETACHOBJECTARBPROC);
1794     BIND_FUNCTION_WITH_WARN(glGetInfoLogARB, COIN_PFNGLGETINFOLOGARBPROC);
1795     BIND_FUNCTION_WITH_WARN(glLinkProgramARB, COIN_PFNGLLINKPROGRAMARBPROC);
1796     BIND_FUNCTION_WITH_WARN(glUseProgramObjectARB, COIN_PFNGLUSEPROGRAMOBJECTARBPROC);
1797     BIND_FUNCTION_WITH_WARN(glCreateProgramObjectARB, COIN_PFNGLCREATEPROGRAMOBJECTARBPROC);
1798     BIND_FUNCTION_WITH_WARN(glUniform1fvARB, COIN_PFNGLUNIFORM1FVARBPROC);
1799     BIND_FUNCTION_WITH_WARN(glUniform2fvARB, COIN_PFNGLUNIFORM2FVARBPROC);
1800     BIND_FUNCTION_WITH_WARN(glUniform3fvARB, COIN_PFNGLUNIFORM3FVARBPROC);
1801     BIND_FUNCTION_WITH_WARN(glUniform4fvARB, COIN_PFNGLUNIFORM4FVARBPROC);
1802     BIND_FUNCTION_WITH_WARN(glUniform1iARB, COIN_PFNGLUNIFORM1IARBPROC);
1803     BIND_FUNCTION_WITH_WARN(glUniform2iARB, COIN_PFNGLUNIFORM2IARBPROC);
1804     BIND_FUNCTION_WITH_WARN(glUniform3iARB, COIN_PFNGLUNIFORM3IARBPROC);
1805     BIND_FUNCTION_WITH_WARN(glUniform4iARB, COIN_PFNGLUNIFORM4IARBPROC);
1806     BIND_FUNCTION_WITH_WARN(glUniform1ivARB, COIN_PFNGLUNIFORM1IVARBPROC);
1807     BIND_FUNCTION_WITH_WARN(glUniform2ivARB, COIN_PFNGLUNIFORM2IVARBPROC);
1808     BIND_FUNCTION_WITH_WARN(glUniform3ivARB, COIN_PFNGLUNIFORM3IVARBPROC);
1809     BIND_FUNCTION_WITH_WARN(glUniform4ivARB, COIN_PFNGLUNIFORM4IVARBPROC);
1810     BIND_FUNCTION_WITH_WARN(glUniformMatrix2fvARB, COIN_PFNGLUNIFORMMATRIX2FVARBPROC);
1811     BIND_FUNCTION_WITH_WARN(glUniformMatrix3fvARB, COIN_PFNGLUNIFORMMATRIX3FVARBPROC);
1812     BIND_FUNCTION_WITH_WARN(glUniformMatrix4fvARB, COIN_PFNGLUNIFORMMATRIX4FVARBPROC);
1813 
1814 
1815     w->glProgramParameteriEXT = NULL;
1816     if (cc_glglue_glext_supported(w, "GL_EXT_geometry_shader4")) {
1817       BIND_FUNCTION_WITH_WARN(glProgramParameteriEXT, COIN_PFNGLPROGRAMPARAMETERIEXT);
1818     }
1819 #undef BIND_FUNCTION_WITH_WARN
1820   }
1821 #endif /* GL_ARB_shader_objects */
1822 
1823   w->glGenQueries = NULL; /* so that cc_glglue_has_occlusion_query() works  */
1824 #if defined(GL_VERSION_1_5)
1825   if (cc_glglue_glversion_matches_at_least(w, 1, 5, 0)) {
1826     w->glGenQueries = (COIN_PFNGLGENQUERIESPROC)PROC(w, glGenQueries);
1827     w->glDeleteQueries = (COIN_PFNGLDELETEQUERIESPROC)PROC(w, glDeleteQueries);
1828     w->glIsQuery = (COIN_PFNGLISQUERYPROC)PROC(w, glIsQuery);
1829     w->glBeginQuery = (COIN_PFNGLBEGINQUERYPROC)PROC(w, glBeginQuery);
1830     w->glEndQuery = (COIN_PFNGLENDQUERYPROC)PROC(w, glEndQuery);
1831     w->glGetQueryiv = (COIN_PFNGLGETQUERYIVPROC)PROC(w, glGetQueryiv);
1832     w->glGetQueryObjectiv = (COIN_PFNGLGETQUERYOBJECTIVPROC)PROC(w, glGetQueryObjectiv);
1833     w->glGetQueryObjectuiv = (COIN_PFNGLGETQUERYOBJECTUIVPROC)PROC(w, glGetQueryObjectuiv);
1834   }
1835 #endif /* GL_VERSION_1_5 */
1836 
1837 #if defined(GL_ARB_occlusion_query)
1838   if ((w->glGenQueries == NULL) && cc_glglue_glext_supported(w, "GL_ARB_occlusion_query")) {
1839     w->glGenQueries = (COIN_PFNGLGENQUERIESPROC)PROC(w, glGenQueriesARB);
1840     w->glDeleteQueries = (COIN_PFNGLDELETEQUERIESPROC)PROC(w, glDeleteQueriesARB);
1841     w->glIsQuery = (COIN_PFNGLISQUERYPROC)PROC(w, glIsQueryARB);
1842     w->glBeginQuery = (COIN_PFNGLBEGINQUERYPROC)PROC(w, glBeginQueryARB);
1843     w->glEndQuery = (COIN_PFNGLENDQUERYPROC)PROC(w, glEndQueryARB);
1844     w->glGetQueryiv = (COIN_PFNGLGETQUERYIVPROC)PROC(w, glGetQueryivARB);
1845     w->glGetQueryObjectiv = (COIN_PFNGLGETQUERYOBJECTIVPROC)PROC(w, glGetQueryObjectivARB);
1846     w->glGetQueryObjectuiv = (COIN_PFNGLGETQUERYOBJECTUIVPROC)PROC(w, glGetQueryObjectuivARB);
1847   }
1848 #endif /* GL_ARB_occlusion_query */
1849 
1850   if (w->glGenQueries) {
1851     if (!w->glDeleteQueries ||
1852         !w->glIsQuery ||
1853         !w->glBeginQuery ||
1854         !w->glEndQuery ||
1855         !w->glGetQueryiv ||
1856         !w->glGetQueryObjectiv ||
1857         !w->glGetQueryObjectuiv) {
1858       w->glGenQueries = NULL; /* so that cc_glglue_has_occlusion_query() will return FALSE */
1859       if (COIN_DEBUG || coin_glglue_debug()) {
1860         cc_debugerror_postwarning("glglue_init",
1861                                   "glGenQueries found, but one or more of the other "
1862                                   "occlusion query functions were not found");
1863       }
1864     }
1865   }
1866 
1867   w->glVertexArrayRangeNV = NULL;
1868 #if defined(GL_NV_vertex_array_range) && (defined(HAVE_GLX) || defined(HAVE_WGL))
1869   if (cc_glglue_glext_supported(w, "GL_NV_vertex_array_range")) {
1870     w->glVertexArrayRangeNV = (COIN_PFNGLVERTEXARRAYRANGENVPROC) PROC(w, glVertexArrayRangeNV);
1871     w->glFlushVertexArrayRangeNV = (COIN_PFNGLFLUSHVERTEXARRAYRANGENVPROC) PROC(w, glFlushVertexArrayRangeNV);
1872 #ifdef HAVE_GLX
1873     w->glAllocateMemoryNV = (COIN_PFNGLALLOCATEMEMORYNVPROC) PROC(w, glXAllocateMemoryNV);
1874     w->glFreeMemoryNV = (COIN_PFNGLFREEMEMORYNVPROC) PROC(w, glXFreeMemoryNV);
1875 #endif /* HAVE_GLX */
1876 #ifdef HAVE_WGL
1877     w->glAllocateMemoryNV = (COIN_PFNGLALLOCATEMEMORYNVPROC) PROC(w, wglAllocateMemoryNV);
1878     w->glFreeMemoryNV = (COIN_PFNGLFREEMEMORYNVPROC) PROC(w, wglFreeMemoryNV);
1879 #endif /* HAVE_WGL */
1880     if (w->glVertexArrayRangeNV) {
1881       if (!w->glFlushVertexArrayRangeNV ||
1882           !w->glAllocateMemoryNV ||
1883           !w->glFreeMemoryNV) {
1884         w->glVertexArrayRangeNV = NULL;
1885         if (COIN_DEBUG || coin_glglue_debug()) {
1886           cc_debugerror_postwarning("glglue_init",
1887                                     "glVertexArrayRangeNV found, but one or more of the other "
1888                                     "vertex array functions were not found");
1889         }
1890       }
1891     }
1892   }
1893 #endif /* HAVE_GLX || HAVE_WGL */
1894 
1895   w->can_do_bumpmapping = FALSE;
1896   if (w->glActiveTexture &&
1897       (cc_glglue_glversion_matches_at_least(w, 1, 3, 0) ||
1898        (cc_glglue_glext_supported(w, "GL_ARB_texture_cube_map") &&
1899         w->has_texture_env_combine &&
1900         cc_glglue_glext_supported(w, "GL_ARB_texture_env_dot3")))) {
1901     w->can_do_bumpmapping = TRUE;
1902   }
1903 
1904   /* FIXME: We should be able to support more than one way to do order
1905      independent transparency (eg. by using fragment
1906      programming). This would demand a different combinations of
1907      extensions (and thus; a different codepath in
1908      SoGLRenderAction). (20031124 handegar) */
1909   w->can_do_sortedlayersblend =
1910     (w->has_nv_register_combiners &&
1911      w->has_ext_texture_rectangle &&
1912      w->has_nv_texture_shader &&
1913      w->has_depth_texture &&
1914      w->has_shadow) ||
1915     w->has_arb_fragment_program;
1916 
1917   if (cc_glglue_glext_supported(w, "GL_ARB_framebuffer_object") ||
1918       cc_glglue_glversion_matches_at_least(w, 3, 0, 0)) {
1919     w->glGenerateMipmap = (COIN_PFNGLGENERATEMIPMAPPROC)
1920       cc_glglue_getprocaddress(w, "glGenerateMipmap");
1921     if (!w->glGenerateMipmap) {
1922       w->glGenerateMipmap = (COIN_PFNGLGENERATEMIPMAPPROC)
1923         cc_glglue_getprocaddress(w, "glGenerateMipmapARB");
1924     }
1925   }
1926   if (!w->glGenerateMipmap) {
1927     if (cc_glglue_glext_supported(w, "GL_EXT_framebuffer_object")) {
1928       w->glGenerateMipmap = (COIN_PFNGLGENERATEMIPMAPPROC)
1929         cc_glglue_getprocaddress(w, "glGenerateMipmapEXT");
1930     }
1931   }
1932 
1933   if (cc_glglue_glext_supported(w, "GL_EXT_framebuffer_object")) {
1934     w->glIsRenderbuffer = (COIN_PFNGLISRENDERBUFFERPROC) cc_glglue_getprocaddress(w, "glIsRenderbufferEXT");
1935     w->glBindRenderbuffer = (COIN_PFNGLBINDRENDERBUFFERPROC) cc_glglue_getprocaddress(w, "glBindRenderbufferEXT");
1936     w->glDeleteRenderbuffers = (COIN_PFNGLDELETERENDERBUFFERSPROC)cc_glglue_getprocaddress(w, "glDeleteRenderbuffersEXT");
1937     w->glGenRenderbuffers = (COIN_PFNGLGENRENDERBUFFERSPROC)cc_glglue_getprocaddress(w, "glGenRenderbuffersEXT");
1938     w->glRenderbufferStorage = (COIN_PFNGLRENDERBUFFERSTORAGEPROC)cc_glglue_getprocaddress(w, "glRenderbufferStorageEXT");
1939     w->glGetRenderbufferParameteriv = (COIN_PFNGLGETRENDERBUFFERPARAMETERIVPROC)cc_glglue_getprocaddress(w, "glGetRenderbufferParameterivEXT");
1940     w->glIsFramebuffer = (COIN_PFNGLISFRAMEBUFFERPROC)cc_glglue_getprocaddress(w, "glIsFramebufferEXT");
1941     w->glBindFramebuffer = (COIN_PFNGLBINDFRAMEBUFFERPROC)cc_glglue_getprocaddress(w, "glBindFramebufferEXT");
1942     w->glDeleteFramebuffers = (COIN_PFNGLDELETEFRAMEBUFFERSPROC)cc_glglue_getprocaddress(w, "glDeleteFramebuffersEXT");
1943     w->glGenFramebuffers = (COIN_PFNGLGENFRAMEBUFFERSPROC)cc_glglue_getprocaddress(w, "glGenFramebuffersEXT");
1944     w->glCheckFramebufferStatus = (COIN_PFNGLCHECKFRAMEBUFFERSTATUSPROC)cc_glglue_getprocaddress(w, "glCheckFramebufferStatusEXT");
1945     w->glFramebufferTexture1D = (COIN_PFNGLFRAMEBUFFERTEXTURE1DPROC)cc_glglue_getprocaddress(w, "glFramebufferTexture1DEXT");
1946     w->glFramebufferTexture2D = (COIN_PFNGLFRAMEBUFFERTEXTURE2DPROC)cc_glglue_getprocaddress(w, "glFramebufferTexture2DEXT");
1947     w->glFramebufferTexture3D = (COIN_PFNGLFRAMEBUFFERTEXTURE3DPROC)cc_glglue_getprocaddress(w, "glFramebufferTexture3DEXT");
1948     w->glFramebufferRenderbuffer = (COIN_PFNGLFRAMEBUFFERRENDERBUFFERPROC)cc_glglue_getprocaddress(w, "glFramebufferRenderbufferEXT");
1949     w->glGetFramebufferAttachmentParameteriv = (COIN_PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)
1950       cc_glglue_getprocaddress(w, "glGetFramebufferAttachmentParameterivEXT");
1951 
1952     if (!w->glIsRenderbuffer || !w->glBindRenderbuffer || !w->glDeleteRenderbuffers ||
1953         !w->glGenRenderbuffers || !w->glRenderbufferStorage || !w->glGetRenderbufferParameteriv ||
1954         !w->glIsFramebuffer || !w->glBindFramebuffer || !w->glDeleteFramebuffers ||
1955         !w->glGenFramebuffers || !w->glCheckFramebufferStatus || !w->glFramebufferTexture1D ||
1956         !w->glFramebufferTexture2D || !w->glFramebufferTexture3D || !w->glFramebufferRenderbuffer ||
1957         !w->glGetFramebufferAttachmentParameteriv || !w->glGenerateMipmap) {
1958       w->has_fbo = FALSE;
1959     }
1960     else {
1961       w->has_fbo = TRUE;
1962     }
1963   }
1964 
1965   /*
1966      Disable features based on known driver bugs  here.
1967      FIXME: move the driver workarounds to some other module. pederb, 2007-07-04
1968   */
1969 
1970   if (coin_runtime_os() == COIN_MSWINDOWS) {
1971     if (w->vendor_is_nvidia && w->has_fbo) {
1972       w->has_fbo = !glglue_has_nvidia_framebuffer_object_bug(w->version.major, w->version.minor, w->version.release);
1973     }
1974   }
1975 
1976   /*
1977      Option to disable FBO feature even if it's available.
1978      FIXME: FBO rendering fails in at least one application. To fix it properly
1979      we need to reproduce this bug in a minimal testcase. jkg, 2007-09-28
1980   */
1981   if ((glglue_resolve_envvar("COIN_DONT_USE_FBO") == 1) && w->has_fbo) {
1982     w->has_fbo = FALSE;
1983   }
1984 
1985 }
1986 
1987 #undef PROC
1988 
1989 static SbBool
glglue_check_trident_clampedge_bug(const char * vendor,const char * renderer,const char * version)1990 glglue_check_trident_clampedge_bug(const char * vendor,
1991                                    const char * renderer,
1992                                    const char * version)
1993 {
1994   return
1995     (strcmp(vendor, "Trident") == 0) &&
1996     (strcmp(renderer, "Blade XP/AGP") == 0) &&
1997     (strcmp(version, "1.2.1") == 0);
1998 }
1999 
2000 static SbBool
glglue_check_ati_vbo_in_displaylist_bug(const char * vendor,const char * COIN_UNUSED_ARG (renderer),const char * COIN_UNUSED_ARG (version))2001 glglue_check_ati_vbo_in_displaylist_bug(const char * vendor,
2002                                         const char * COIN_UNUSED_ARG(renderer),
2003                                         const char * COIN_UNUSED_ARG(version))
2004 {
2005   /*
2006    * FIXME: is there a better way to test if we're on Mac OS X
2007    * pederb, 20051026
2008    */
2009 #if !defined(HAVE_AGL) && !defined(HAVE_CGL) /* bug is not present on Mac OS X */
2010   /*
2011    * The ATI Windows/Linux driver has a nasty bug which causes a crash
2012    * in OpenGL whenever a VBO render call is added to a display
2013    * list. This has been confirmed on several ATI drivers.  (tested
2014    * drivers on Windows: 1.4.4145, 1.4.4054, and on Linux: 1.3.4641)
2015    *
2016    * FIXME: Check version string if ATI ever fixes this bug. The
2017    * scene graph below can be used to reproduce the bug:
2018 
2019    #Inventor V2.1 ascii
2020 
2021    MaterialBinding { value PER_VERTEX_INDEXED }
2022    LightModel { model BASE_COLOR }
2023 
2024    BaseColor {
2025      rgb [
2026       1 0 0, 0 1 0, 0 0 1, 1 1 0,
2027       1 0 0, 0 1 0, 0 0 1, 1 1 0,
2028       1 0 0, 0 1 0, 0 0 1, 1 1 0,
2029       1 0 0, 0 1 0, 0 0 1, 1 1 0,
2030       1 0 0, 0 1 0, 0 0 1, 1 1 0,
2031       1 0 0, 0 1 0, 0 0 1, 1 1 0,
2032       1 0 0, 0 1 0, 0 0 1, 1 1 0,
2033       1 0 0, 0 1 0, 0 0 1, 1 1 0,
2034       1 0 0, 0 1 0, 0 0 1, 1 1 0,
2035       1 0 0, 0 1 0, 0 0 1, 1 1 0,
2036       1 0 0, 0 1 0, 0 0 1, 1 1 0
2037       ]
2038    }
2039    Coordinate3 {
2040      point [
2041       0 0 0, 1 0 0, 1 1 0, 0 1 0,
2042       0 0 0, 1 0 0, 1 1 0, 0 1 0,
2043       0 0 0, 1 0 0, 1 1 0, 0 1 0,
2044       0 0 0, 1 0 0, 1 1 0, 0 1 0,
2045       0 0 0, 1 0 0, 1 1 0, 0 1 0,
2046       0 0 0, 1 0 0, 1 1 0, 0 1 0,
2047       0 0 0, 1 0 0, 1 1 0, 0 1 0,
2048       0 0 0, 1 0 0, 1 1 0, 0 1 0,
2049       0 0 0, 1 0 0, 1 1 0, 0 1 0,
2050       0 0 0, 1 0 0, 1 1 0, 0 1 0,
2051       0 0 0, 1 0 0, 1 1 0, 0 1 0
2052      ]
2053    }
2054    PointSet {
2055      numPoints 44
2056    }
2057    ShapeHints {
2058      vertexOrdering COUNTERCLOCKWISE
2059      faceType CONVEX
2060      shapeType UNKNOWN_SHAPE_TYPE
2061    }
2062    IndexedFaceSet {
2063      coordIndex [
2064        0,1,2,3,-1,
2065        4,5,6,7, -1,
2066        8,9,10,11, -1,
2067        12,13,14,15, -1,
2068        16,17,18,19,-1,
2069        20,21,22,23,-1,
2070        24,25,26,27,-1,
2071        28,29,30,31,-1,
2072        32,33,34,35,-1,
2073        36,37,38,39,-1,
2074        40,41,42,43,-1
2075      ]
2076    }
2077    IndexedLineSet {
2078      coordIndex [
2079        0,1,2,3,-1,
2080        4,5,6,7, -1,
2081        8,9,10,11, -1,
2082        12,13,14,15, -1,
2083        16,17,18,19,-1,
2084        20,21,22,23,-1,
2085        24,25,26,27,-1,
2086        28,29,30,31,-1,
2087        32,33,34,35,-1,
2088        36,37,38,39,-1,
2089        40,41,42,43,-1
2090      ]
2091    }
2092   *
2093   */
2094   return
2095     (strcmp(vendor, "ATI Technologies Inc.") == 0);
2096 #else /* ATI driver bug */
2097   return FALSE;
2098 #endif /* Mac OS X drivers are ok */
2099 }
2100 
2101 /* Give warnings on known faulty drivers. */
2102 static void
glglue_check_driver(const char * vendor,const char * renderer,const char * version)2103 glglue_check_driver(const char * vendor, const char * renderer,
2104                     const char * version)
2105 {
2106 #ifdef COIN_DEBUG
2107   /* Only spit out this in debug builds, as the bug was never properly
2108      confirmed. */
2109   if (coin_glglue_radeon_warning()) {
2110     if (strcmp(renderer, "Radeon 7500 DDR x86/SSE2") == 0) {
2111       cc_debugerror_postwarning("glglue_check_driver",
2112                                 "We've had an unconfirmed bugreport that "
2113                                 "this OpenGL driver ('%s') may crash upon "
2114                                 "attempts to use 3D texturing. "
2115                                 "We would like to get assistance to help "
2116                                 "us debug the cause of this problem, so "
2117                                 "please get in touch with us at "
2118                                 "<coin-support@coin3d.org>. "
2119                                 "This debug message can be turned off "
2120                                 "permanently by setting the environment "
2121                                 "variable COIN_GLGLUE_NO_RADEON_WARNING=1.",
2122                                 renderer);
2123 
2124       /*
2125         Some additional information:
2126 
2127         The full driver information for the driver where this was
2128         reported is as follows:
2129 
2130         GL_VENDOR == 'ATI Technologies Inc.'
2131         GL_RENDERER == 'Radeon 7500 DDR x86/SSE2'
2132         GL_VERSION == '1.3.3302 Win2000 Release'
2133 
2134         The driver was reported to crash on MSWin with the
2135         SoGuiExamples/nodes/texture3 example. The reporter couldn't
2136         help us debug it, as he could a) not get a call-stack
2137         backtrace, and b) swapped his card for an NVidia card.
2138 
2139         Perhaps we should get hold of a Radeon card ourselves, to test
2140         and debug the problem.
2141 
2142         <mortene@sim.no>
2143       */
2144     }
2145   }
2146 #endif /* COIN_DEBUG */
2147 
2148   if (coin_glglue_old_matrox_warning() &&
2149       (strcmp(renderer, "Matrox G400") == 0) &&
2150       (strcmp(version, "1.1.3 Aug 30 2001") == 0)) {
2151     cc_debugerror_postwarning("glglue_check_driver",
2152                               "This old OpenGL driver (\"%s\" \"%s\") has "
2153                               "known bugs, please upgrade.  "
2154                               "(This debug message can be turned off "
2155                               "permanently by setting the environment "
2156                               "variable COIN_GLGLUE_NO_G400_WARNING=1).",
2157                               renderer, version);
2158   }
2159 
2160   if (coin_glglue_old_elsa_warning() &&
2161       (strcmp(renderer, "ELSA TNT2 Vanta/PCI/SSE") == 0) &&
2162       (strcmp(version, "1.1.4 (4.06.00.266)") == 0)) {
2163     cc_debugerror_postwarning("glglue_check_driver",
2164                               "This old OpenGL driver (\"%s\" \"%s\") has "
2165                               "known bugs, please upgrade.  "
2166                               "(This debug message can be turned off "
2167                               "permanently by setting the environment "
2168                               "variable COIN_GLGLUE_NO_ELSA_WARNING=1).",
2169                               renderer, version);
2170   }
2171 
2172   /*
2173     The full driver information for the driver where this was reported
2174     is as follows:
2175 
2176     GL_VENDOR == 'Matrox Graphics Inc.'
2177     GL_RENDERER == 'Matrox G400'
2178     GL_VERSION == '1.1.3 Aug 30 2001'
2179 
2180     GL_VENDOR == 'ELSA AG (Aachen, Germany).'
2181     GL_RENDERER == 'ELSA TNT2 Vanta/PCI/SSE'
2182     GL_VERSION == '1.1.4 (4.06.00.266)'
2183 
2184     The driver was reported to crash on MSWin under following
2185     conditions, quoted verbatim from the problem report:
2186 
2187     ------8<---- [snip] -----------8<---- [snip] -----
2188 
2189     I observe a bit of strange behaviour on my NT4 systems. I have an
2190     appliction which uses the the following bit of code:
2191 
2192     // Define line width
2193     SoDrawStyle *drawStyle = new SoDrawStyle;
2194     drawStyle->lineWidth.setValue(3);
2195     drawStyle->linePattern.setValue(0x0F0F);
2196     root->addChild(drawStyle);
2197 
2198     // Define line connection
2199     SoCoordinate3 *coords = new SoCoordinate3;
2200     coords->point.setValues(0, 2, vert);
2201     root->addChild(coords);
2202 
2203     SoLineSet *lineSet = new SoLineSet ;
2204     lineSet->numVertices.set1Value(0, 2) ;
2205     root->addChild(lineSet);
2206 
2207     It defines a line with a dashed pattern. When the line is in a
2208     direction and the viewing direction is not parrallel to this line
2209     all works fine. In case the viewing direction is the same as the
2210     line direction one of my systems crashes [...]
2211 
2212     ------8<---- [snip] -----------8<---- [snip] -----
2213 
2214     <mortene@sim.no>
2215 
2216     UPDATE 20030116 mortene: as of this date, the most recent Matrox
2217     driver (version 5.86.032, from 2002-11-21) still exhibits the same
2218     problem, while the ELSA driver can be upgraded to a version that
2219     does not have the bug any more.
2220   */
2221 
2222   if (coin_glglue_sun_expert3d_warning() &&
2223       (strcmp(renderer, "Sun Expert3D, VIS") == 0) &&
2224       (strcmp(version, "1.2 Sun OpenGL 1.2.1 patch 109544-19 for Solaris") == 0)) {
2225     cc_debugerror_postwarning("glglue_check_driver",
2226                               "This OpenGL driver (\"%s\" \"%s\") has known "
2227                               "problems with dual screen configurations, "
2228                               "please upgrade.  "
2229                               "(This debug message can be turned off "
2230                               "permanently by setting the environment variable"
2231                               " COIN_GLGLUE_NO_SUN_EXPERT3D_WARNING=1).",
2232                               renderer, version);
2233   /*
2234     The full driver information for the driver where this was reported
2235     is as follows:
2236 
2237     GL_VENDOR == 'Sun Microsystems, Inc.'
2238     GL_RENDERER == 'Sun Expert3D, VIS'
2239     GL_VERSION == '1.2 Sun OpenGL 1.2.1 patch 109544-19 for Solaris'
2240 
2241     The driver was reported to fail when running on a Sun Solaris
2242     system with the XVR1000 graphics card. Quoted verbatim from the
2243     problem report:
2244 
2245     ------8<---- [snip] -----------8<---- [snip] -----
2246 
2247     [The client] works with two screens. One of the screen works as it
2248     should, while the otherone has erronious apperance (see uploaded
2249     image). The errors are the stripes on the texture (It should be
2250     one continious texture). The texture is wrapped on a rectangle
2251     (i.e. two large triangles). It is not only the OpenGl part of the
2252     window that is weired.  Some buttons are missing and other buttons
2253     have wrong colors++.
2254 
2255     ------8<---- [snip] -----------8<---- [snip] -----
2256 
2257     The error disappeared after a driver upgrade.
2258 
2259     <mortene@sim.no>
2260   */
2261   }
2262 
2263   if (coin_glglue_trident_warning() &&
2264       glglue_check_trident_clampedge_bug(vendor, renderer, version)) {
2265     cc_debugerror_postwarning("glglue_check_driver",
2266                               "This OpenGL driver (\"%s\" \"%s\" \"%s\") has "
2267                               "a known problem: it doesn't support the "
2268                               "GL_CLAMP_TO_EDGE texture wrapping mode. "
2269                               "(This debug message can be turned off "
2270                               "permanently by setting the environment variable"
2271                               " COIN_GLGLUE_NO_TRIDENT_WARNING=1).",
2272                               vendor, renderer, version);
2273     /*
2274       This problem manifests itself in the form of a glGetError()
2275       reporting GL_INVALID_ENUM if GL_TEXTURE_WRAP_[S|T] is attempted
2276       set to GL_CLAMP_TO_EDGE. GL_CLAMP_TO_EDGE was introduced with
2277       OpenGL v1.2.0, and the driver reports v1.2.1, so it is supposed
2278       to work.
2279     */
2280   }
2281 }
2282 
check_force_agl()2283 static void check_force_agl()
2284 {
2285 #ifdef HAVE_AGL
2286   if (COIN_USE_AGL == -1) {
2287     const char * env = coin_getenv("COIN_FORCE_AGL");
2288     if (env) {
2289       COIN_USE_AGL = atoi(env);
2290     }
2291     else
2292 #ifdef HAVE_CGL
2293     COIN_USE_AGL = 0;
2294 #else
2295     COIN_USE_AGL = 1;
2296 #endif
2297   }
2298 #endif
2299 }
2300 
2301 /* We're basically using the Singleton pattern to instantiate and
2302    return OpenGL-glue "object structs". We're constructing one
2303    instance for each OpenGL context, though.  */
2304 const cc_glglue *
cc_glglue_instance(int contextid)2305 cc_glglue_instance(int contextid)
2306 {
2307   SbBool found;
2308   void * ptr;
2309   GLint gltmp;
2310 
2311   cc_glglue * gi = NULL;
2312 
2313   CC_SYNC_BEGIN(cc_glglue_instance);
2314 
2315   /* check environment variables */
2316   if (COIN_MAXIMUM_TEXTURE2_SIZE == 0) {
2317     const char * env = coin_getenv("COIN_MAXIMUM_TEXTURE2_SIZE");
2318     if (env) COIN_MAXIMUM_TEXTURE2_SIZE = atoi(env);
2319     else COIN_MAXIMUM_TEXTURE2_SIZE = -1;
2320   }
2321   if (COIN_MAXIMUM_TEXTURE3_SIZE == 0) {
2322     const char * env = coin_getenv("COIN_MAXIMUM_TEXTURE3_SIZE");
2323     if (env) COIN_MAXIMUM_TEXTURE3_SIZE = atoi(env);
2324     else COIN_MAXIMUM_TEXTURE3_SIZE = -1;
2325   }
2326   check_force_agl();
2327 
2328   if (!gldict) {  /* First invocation, do initializations. */
2329     gldict = cc_dict_construct(16, 0.75f);
2330     coin_atexit((coin_atexit_f *)glglue_cleanup, CC_ATEXIT_NORMAL);
2331   }
2332 
2333   found = cc_dict_get(gldict, (uintptr_t)contextid, &ptr);
2334 
2335   if (!found) {
2336     GLenum glerr;
2337 
2338     /* Internal consistency checking.
2339 
2340        Make it possible to disabled this assert because GLX in Mesa
2341        version 3.4.2 (GL_VENDOR "VA Linux Systems, Inc", GL_RENDERER
2342        "Mesa GLX Indirect", GL_VERSION "1.2 Mesa 3.4.2") returns NULL
2343        even though there really is a current context set up. (Reported
2344        by kintel.)
2345     */
2346     static int chk = -1;
2347     if (chk == -1) {
2348       /* Note: don't change envvar name without updating the assert
2349          text below. */
2350       chk = coin_getenv("COIN_GL_NO_CURRENT_CONTEXT_CHECK") ? 0 : 1;
2351     }
2352     if (chk) {
2353       const void * current_ctx = coin_gl_current_context();
2354       assert(current_ctx && "Must have a current GL context when instantiating cc_glglue!! (Note: if you are using an old Mesa GL version, set the environment variable COIN_GL_NO_CURRENT_CONTEXT_CHECK to get around what may be a Mesa bug.)");
2355     }
2356 
2357     /* FIXME: this is not free'd until app exit, which is bad because
2358        it opens a small window of possibility for errors; the value of
2359        id/key inputs could in principle be reused, so we'd get an old,
2360        invalid instance instead of creating a new one. Should rather
2361        hook into SoContextHandler and kill off an instance when a GL
2362        context is taken out. 20051104 mortene. */
2363     gi = (cc_glglue*)malloc(sizeof(cc_glglue));
2364     /* clear to set all pointers and variables to NULL or 0 */
2365     memset(gi, 0, sizeof(cc_glglue));
2366     /* FIXME: handle out-of-memory on malloc(). 20000928 mortene. */
2367 
2368     gi->contextid = (uint32_t) contextid;
2369 
2370     /* create dict that makes a quick lookup for GL extensions */
2371     gi->glextdict = cc_dict_construct(256, 0.75f);
2372 
2373     ptr = gi;
2374     cc_dict_put(gldict, (uintptr_t)contextid, ptr);
2375 
2376     /*
2377        Make sure all GL errors are cleared before we do our assert
2378        test below. The OpenGL context might be set up by the user, and
2379        it's better to print a warning than asserting here if the user
2380        did something wrong while creating it.
2381     */
2382     glerr = glGetError();
2383     while (glerr != GL_NO_ERROR) {
2384       cc_debugerror_postwarning("cc_glglue_instance",
2385                                 "Error when setting up the GL context. This can happen if "
2386                                 "there is no current context, or if the context has been set "
2387                                 "up incorrectly.");
2388       glerr = glGetError();
2389 
2390       /* We might get this error if there is no current context.
2391          Break out and assert later in that case */
2392       if (glerr == GL_INVALID_OPERATION) break;
2393     }
2394 
2395     /* NB: if you are getting a crash here, it's because an attempt at
2396      * setting up a cc_glglue instance was made when there is no
2397      * current OpenGL context. */
2398     gi->versionstr = (const char *)glGetString(GL_VERSION);
2399     assert(gi->versionstr && "could not call glGetString() -- no current GL context?");
2400     assert(glGetError() == GL_NO_ERROR && "GL error when calling glGetString() -- no current GL context?");
2401 
2402     glglue_set_glVersion(gi);
2403     glxglue_init(gi);
2404 
2405     gi->vendorstr = (const char *)glGetString(GL_VENDOR);
2406     gi->vendor_is_SGI = strcmp((const char *)gi->vendorstr, "SGI") == 0;
2407     gi->vendor_is_nvidia = strcmp((const char*)gi->vendorstr, "NVIDIA Corporation") == 0;
2408     gi->vendor_is_intel =
2409       strstr((const char *)gi->vendorstr, "Tungsten") ||
2410       strstr((const char *)gi->vendorstr, "Intel");
2411     gi->vendor_is_ati = (strcmp((const char *) gi->vendorstr, "ATI Technologies Inc.") == 0);
2412     gi->vendor_is_3dlabs = strcmp((const char *) gi->vendorstr, "3Dlabs") == 0;
2413 
2414     /* FIXME: update when nVidia fixes their driver. pederb, 2004-09-01 */
2415     gi->nvidia_color_per_face_bug = gi->vendor_is_nvidia;
2416     if (gi->nvidia_color_per_face_bug) {
2417       const char * env = coin_getenv("COIN_NO_NVIDIA_COLOR_PER_FACE_BUG_WORKAROUND");
2418       if (env) gi->nvidia_color_per_face_bug = 0;
2419     }
2420 
2421     gi->rendererstr = (const char *)glGetString(GL_RENDERER);
2422     gi->extensionsstr = (const char *)glGetString(GL_EXTENSIONS);
2423 
2424     /* Randall O'Reilly reports that the above call is deprecated from OpenGL 3.0
2425        onwards and may, particularly on some Linux systems, return NULL.
2426 
2427        The recommended method is to use glGetStringi to get each string in turn.
2428        The following code, supplied by Randall, implements this to end up with the
2429        same result as the old method.
2430     */
2431     if (gi->extensionsstr == NULL) {
2432       COIN_PFNGLGETSTRINGIPROC glGetStringi = NULL;
2433       glGetStringi = (COIN_PFNGLGETSTRINGIPROC)cc_glglue_getprocaddress(gi, "glGetStringi");
2434       if (glGetStringi != NULL) {
2435         GLint num_strings = 0;
2436         glGetIntegerv(GL_NUM_EXTENSIONS, &num_strings);
2437         if (num_strings > 0) {
2438           int buffer_size = 1024;
2439           char *ext_strings_buffer = (char *)malloc(buffer_size * sizeof (char));
2440           int buffer_pos = 0;
2441           for (int i_string = 0 ; i_string < num_strings ; i_string++) {
2442             const char * extension_string = (char *)glGetStringi (GL_EXTENSIONS, i_string);
2443             int extension_string_length = (int)strlen(extension_string);
2444             if (buffer_pos + extension_string_length + 1 > buffer_size) {
2445               buffer_size += 1024;
2446               ext_strings_buffer = (char *)realloc(ext_strings_buffer, buffer_size * sizeof (char));
2447             }
2448             strcpy(ext_strings_buffer + buffer_pos, extension_string);
2449             buffer_pos += extension_string_length;
2450             ext_strings_buffer[buffer_pos++] = ' '; // Space separated, overwrites NULL.
2451           }
2452           ext_strings_buffer[++buffer_pos] = '\0';  // NULL terminate.
2453           gi->extensionsstr = ext_strings_buffer;   // Handing over ownership, don't free here.
2454         } else {
2455           cc_debugerror_postwarning ("cc_glglue_instance",
2456                                      "glGetIntegerv(GL_NUM_EXTENSIONS) did not return a value, "
2457                                      "so unable to get extensions for this GL driver, ",
2458                                      "version: %s, vendor: %s", gi->versionstr, gi->vendorstr);
2459         }
2460       } else {
2461         cc_debugerror_postwarning ("cc_glglue_instance",
2462                                    "glGetString(GL_EXTENSIONS) returned null, but glGetStringi "
2463                                    "procedure not found, so unable to get extensions for this GL driver, "
2464                                    "version: %s, vendor: %s", gi->versionstr, gi->vendorstr);
2465       }
2466     }
2467 
2468     /* read some limits */
2469 
2470     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gltmp);
2471     gi->max_texture_size = gltmp;
2472 
2473     glGetIntegerv(GL_MAX_LIGHTS, &gltmp);
2474     gi->max_lights = (int) gltmp;
2475 
2476     {
2477       GLfloat vals[2];
2478       glGetFloatv(GL_POINT_SIZE_RANGE, vals);
2479 
2480       /* Matthias Koenig reported on coin-discuss that the OpenGL
2481          implementation on SGI Onyx 2 InfiniteReality returns 0 for the
2482          lowest pointsize, but it will still set the return value of
2483          glGetError() to GL_INVALID_VALUE if this size is attempted
2484          used. So the boundary range fix in the next line of code is a
2485          workaround for that OpenGL implementation bug.
2486 
2487          0.0f and lower values are explicitly disallowed, according to
2488          the OpenGL 1.3 specification, Chapter 3.3. */
2489       if (vals[0] <= 0.0f) {
2490         vals[0] = vals[1] < 1.0f ? vals[1] : 1.0f;
2491       }
2492       gi->point_size_range[0] = vals[0];
2493       gi->point_size_range[1] = vals[1];
2494     }
2495     {
2496       GLfloat vals[2];
2497       glGetFloatv(GL_LINE_WIDTH_RANGE, vals);
2498 
2499       /* Matthias Koenig reported on coin-discuss that the OpenGL
2500          implementation on SGI Onyx 2 InfiniteReality returns 0 for the
2501          lowest linewidth, but it will still set the return value of
2502          glGetError() to GL_INVALID_VALUE if this size is attempted
2503          used. This is a workaround for what looks like an OpenGL bug. */
2504 
2505       if (vals[0] <= 0.0f) {
2506         vals[0] = vals[1] < 1.0f ? vals[1] : 1.0f;
2507       }
2508       gi->line_width_range[0] = vals[0];
2509       gi->line_width_range[1] = vals[1];
2510     }
2511 
2512     if (coin_glglue_debug()) {
2513       cc_debugerror_postinfo("cc_glglue_instance",
2514                              "glGetString(GL_VENDOR)=='%s' (=> vendor_is_SGI==%s)",
2515                              gi->vendorstr,
2516                              gi->vendor_is_SGI ? "TRUE" : "FALSE");
2517       cc_debugerror_postinfo("cc_glglue_instance",
2518                              "glGetString(GL_RENDERER)=='%s'",
2519                              gi->rendererstr);
2520       cc_debugerror_postinfo("cc_glglue_instance",
2521                              "glGetString(GL_EXTENSIONS)=='%s'",
2522                              gi->extensionsstr);
2523 
2524       cc_debugerror_postinfo("cc_glglue_instance",
2525                              "Rendering is %sdirect.",
2526                              gi->glx.isdirect ? "" : "in");
2527     }
2528 
2529     /* anisotropic test */
2530     gi->can_do_anisotropic_filtering = FALSE;
2531     gi->max_anisotropy = 0.0f;
2532     if (cc_glglue_glext_supported(gi, "GL_EXT_texture_filter_anisotropic")) {
2533       gi->can_do_anisotropic_filtering = TRUE;
2534       glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gi->max_anisotropy);
2535       if (coin_glglue_debug()) {
2536         cc_debugerror_postinfo("cc_glglue_instance",
2537                                "Anisotropic filtering: %s (%g)",
2538                                gi->can_do_anisotropic_filtering ? "TRUE" : "FALSE",
2539                                gi->max_anisotropy);
2540       }
2541     }
2542 
2543     /* check for ATI vbo in displaylist bug */
2544     gi->vbo_in_displaylist_ok = !glglue_check_ati_vbo_in_displaylist_bug(gi->vendorstr,
2545                                                                          gi->rendererstr,
2546                                                                          gi->versionstr);
2547 
2548     glglue_check_driver(gi->vendorstr, gi->rendererstr, gi->versionstr);
2549 
2550     gi->non_power_of_two_textures =
2551       (cc_glglue_glversion_matches_at_least(gi, 2, 1, 0) ||
2552        cc_glglue_glext_supported(gi, "GL_ARB_texture_non_power_of_two"));
2553 
2554     /* Resolve our function pointers. */
2555       glglue_resolve_symbols(gi);
2556   }
2557   else {
2558     gi = (cc_glglue *)ptr;
2559   }
2560 
2561   CC_SYNC_END(cc_glglue_instance);
2562 
2563   if (!found && gl_instance_created_cblist) {
2564     int i, n = cc_list_get_length(gl_instance_created_cblist) / 2;
2565     for (i = 0; i < n; i++) {
2566       coin_glglue_instance_created_cb * cb =
2567         (coin_glglue_instance_created_cb *) cc_list_get(gl_instance_created_cblist, i*2);
2568       cb(contextid, cc_list_get(gl_instance_created_cblist, i*2+1));
2569     }
2570   }
2571   return gi;
2572 }
2573 
2574 const cc_glglue *
cc_glglue_instance_from_context_ptr(void * ctx)2575 cc_glglue_instance_from_context_ptr(void * ctx)
2576 {
2577   /* The id can really be anything unique for the current context, but
2578      we should avoid a crash with the possible ids defined by
2579      SoGLCacheContextElement. It's a bit of a hack, this. */
2580 
2581   /* MSVC7 on 64-bit Windows wants this extra cast. */
2582   const uintptr_t cast_aid = (uintptr_t)ctx;
2583   /* FIXME: holy shit! This doesn't look sensible at all! (Could this
2584      e.g. be where the remote rendering bugs are coming from?)
2585      20050525 mortene.*/
2586   const int id = (int)cast_aid;
2587 
2588   return cc_glglue_instance(id);
2589 }
2590 
2591 void
coin_glglue_destruct(uint32_t contextid)2592 coin_glglue_destruct(uint32_t contextid)
2593 {
2594   SbBool found;
2595   void * ptr;
2596   CC_SYNC_BEGIN(cc_glglue_instance);
2597   if (gldict) { // might happen if a context is destructed without using the cc_glglue interface
2598     found = cc_dict_get(gldict, (uintptr_t)contextid, &ptr);
2599     if (found) {
2600       cc_glglue * glue = (cc_glglue*) ptr;
2601       if (glue->normalizationcubemap) {
2602         cc_glglue_glDeleteTextures(glue, 1, &glue->normalizationcubemap);
2603       }
2604       (void)cc_dict_remove(gldict, (uintptr_t)contextid);
2605 
2606       if (glue->dl_handle) {
2607         cc_dl_close(glue->dl_handle);
2608       }
2609     }
2610   }
2611   CC_SYNC_END(cc_glglue_instance);
2612 }
2613 
2614 SbBool
cc_glglue_isdirect(const cc_glglue * w)2615 cc_glglue_isdirect(const cc_glglue * w)
2616 {
2617   return w->glx.isdirect;
2618 }
2619 
2620 
2621 /*!
2622   Whether glPolygonOffset() is availble or not: either we're on OpenGL
2623   1.1 or the GL_EXT_polygon_offset extension is available.
2624 
2625   Method then available for use:
2626   \li cc_glglue_glPolygonOffset
2627 */
2628 SbBool
cc_glglue_has_polygon_offset(const cc_glglue * w)2629 cc_glglue_has_polygon_offset(const cc_glglue * w)
2630 {
2631   if (!glglue_allow_newer_opengl(w)) return FALSE;
2632 
2633   return (w->glPolygonOffset || w->glPolygonOffsetEXT) ? TRUE : FALSE;
2634 }
2635 
2636 /* Returns the glPolygonOffset() we're actually going to use. */
2637 static COIN_PFNGLPOLYGONOFFSETPROC
glglue_glPolygonOffset(const cc_glglue * w)2638 glglue_glPolygonOffset(const cc_glglue * w)
2639 {
2640   COIN_PFNGLPOLYGONOFFSETPROC poff = NULL;
2641 
2642   assert(w->glPolygonOffset ||  w->glPolygonOffsetEXT);
2643 
2644   poff = w->glPolygonOffset;
2645 
2646   /* Some SGI OpenGL 1.1 driver(s) seems to have a buggy
2647      implementation of glPolygonOffset(), according to pederb after
2648      some debugging he did for Fedem. These drivers'
2649      glPolygonOffsetEXT() actually seems to work better, so we prefer
2650      that if available. */
2651   if (w->vendor_is_SGI && w->glPolygonOffsetEXT &&
2652       cc_glglue_glversion_matches_at_least(w, 1, 1, 0) &&
2653       !cc_glglue_glversion_matches_at_least(w, 1, 2, 0)) {
2654     poff = w->glPolygonOffsetEXT;
2655   }
2656 
2657   /* Since we know glPolygonOffset() can be problematic, we also
2658      provide a way to prefer the EXT function instead through an
2659      environment variable "COIN_PREFER_GLPOLYGONOFFSET_EXT" (which
2660      could be handy for help debugging remote systems, at least). */
2661   if (w->glPolygonOffsetEXT && glglue_prefer_glPolygonOffsetEXT()) {
2662     poff = w->glPolygonOffsetEXT;
2663   }
2664 
2665   /* If glPolygonOffset() is not available (and the function pointer
2666      was not set by any of the bug workaround if-checks above), fall
2667      back on extension. */
2668   if (poff == NULL) { poff = w->glPolygonOffsetEXT; }
2669 
2670   return poff;
2671 }
2672 
2673 /*!
2674   Enable or disable z-buffer offsetting for the given primitive types.
2675 */
2676 void
cc_glglue_glPolygonOffsetEnable(const cc_glglue * w,SbBool enable,int m)2677 cc_glglue_glPolygonOffsetEnable(const cc_glglue * w,
2678                                 SbBool enable, int m)
2679 {
2680   COIN_PFNGLPOLYGONOFFSETPROC poff = glglue_glPolygonOffset(w);
2681 
2682   if (enable) {
2683     if (poff == w->glPolygonOffset) {
2684       if (m & cc_glglue_FILLED) glEnable(GL_POLYGON_OFFSET_FILL);
2685       else glDisable(GL_POLYGON_OFFSET_FILL);
2686       if (m & cc_glglue_LINES) glEnable(GL_POLYGON_OFFSET_LINE);
2687       else glDisable(GL_POLYGON_OFFSET_LINE);
2688       if (m & cc_glglue_POINTS) glEnable(GL_POLYGON_OFFSET_POINT);
2689       else glDisable(GL_POLYGON_OFFSET_POINT);
2690     }
2691     else { /* using glPolygonOffsetEXT() */
2692       /* The old pre-1.1 extension only supports filled polygon
2693          offsetting. */
2694       if (m & cc_glglue_FILLED) glEnable(GL_POLYGON_OFFSET_EXT);
2695       else glDisable(GL_POLYGON_OFFSET_EXT);
2696 
2697       if (coin_glglue_debug() && (m != cc_glglue_FILLED)) {
2698         static SbBool first = TRUE;
2699         if (first) {
2700           cc_debugerror_postwarning("cc_glglue_glPolygonOffsetEnable",
2701                                     "using EXT_polygon_offset, which only "
2702                                     "supports filled-polygon offsetting");
2703           first = FALSE;
2704         }
2705       }
2706     }
2707   }
2708   else { /* disable */
2709     if (poff == w->glPolygonOffset) {
2710       if (m & cc_glglue_FILLED) glDisable(GL_POLYGON_OFFSET_FILL);
2711       if (m & cc_glglue_LINES) glDisable(GL_POLYGON_OFFSET_LINE);
2712       if (m & cc_glglue_POINTS) glDisable(GL_POLYGON_OFFSET_POINT);
2713     }
2714     else { /* using glPolygonOffsetEXT() */
2715       if (m & cc_glglue_FILLED) glDisable(GL_POLYGON_OFFSET_EXT);
2716       /* Pre-1.1 glPolygonOffset extension only supported filled primitives.*/
2717     }
2718   }
2719 }
2720 
2721 void
cc_glglue_glPolygonOffset(const cc_glglue * w,GLfloat factor,GLfloat units)2722 cc_glglue_glPolygonOffset(const cc_glglue * w,
2723                           GLfloat factor,
2724                           GLfloat units)
2725 {
2726   COIN_PFNGLPOLYGONOFFSETPROC poff = glglue_glPolygonOffset(w);
2727 
2728   if (poff == w->glPolygonOffsetEXT) {
2729     /* Try to detect if user actually attempted to specify a valid
2730        bias value, like the old glPolygonOffsetEXT() extension
2731        needs. If not, assume that the "units" argument was set up for
2732        the "real" glPolygonOffset() function, and use a default value
2733        that should work fairly ok under most circumstances. */
2734     SbBool isbias = (units > 0.0f) && (units < 0.01f);
2735     if (!isbias) units = 0.000001f;
2736 
2737     /* FIXME: shouldn't there be an attempt to convert the other way
2738        around too? Ie, if it *is* a "bias" value and we're using the
2739        "real" 1.1 glPolygonOffset() function, try to convert it into a
2740        valid "units" value? 20020919 mortene. */
2741   }
2742 
2743   poff(factor, units);
2744 }
2745 
2746 /*!
2747   Whether 3D texture objects are available or not: either we're on OpenGL
2748   1.1, or the GL_EXT_texture_object extension is available.
2749 
2750   Methods then available for use:
2751 
2752   \li cc_glglue_glGenTextures
2753   \li cc_glglue_glBindTexture
2754   \li cc_glglue_glDeleteTextures
2755 */
2756 SbBool
cc_glglue_has_texture_objects(const cc_glglue * w)2757 cc_glglue_has_texture_objects(const cc_glglue * w)
2758 {
2759   if (!glglue_allow_newer_opengl(w)) return FALSE;
2760 
2761   return w->glGenTextures && w->glBindTexture && w->glDeleteTextures;
2762 }
2763 
2764 void
cc_glglue_glGenTextures(const cc_glglue * w,GLsizei n,GLuint * textures)2765 cc_glglue_glGenTextures(const cc_glglue * w, GLsizei n, GLuint * textures)
2766 {
2767   assert(w->glGenTextures);
2768   w->glGenTextures(n, textures);
2769 
2770 #if 0 /* debug */
2771   cc_debugerror_postinfo("cc_glglue_glGenTextures", "%p, size==%d, textures==%p", w, n, textures);
2772 #endif /* debug */
2773 }
2774 
2775 void
cc_glglue_glBindTexture(const cc_glglue * w,GLenum target,GLuint texture)2776 cc_glglue_glBindTexture(const cc_glglue * w, GLenum target, GLuint texture)
2777 {
2778   assert(w->glBindTexture);
2779   w->glBindTexture(target, texture);
2780 
2781 #if 0 /* debug */
2782   cc_debugerror_postinfo("cc_glglue_glBindTexture", "%p, ..., %d", w, texture);
2783 #endif /* debug */
2784 }
2785 
2786 void
cc_glglue_glDeleteTextures(const cc_glglue * w,GLsizei n,const GLuint * textures)2787 cc_glglue_glDeleteTextures(const cc_glglue * w, GLsizei n, const GLuint * textures)
2788 {
2789   assert(w->glDeleteTextures);
2790   w->glDeleteTextures(n, textures);
2791 
2792 #if 0 /* debug */
2793   cc_debugerror_postinfo("cc_glglue_glDeleteTextures", "%p, size==%d, textures==%p", w, n, textures);
2794 #endif /* debug */
2795 }
2796 
2797 /*!
2798   Whether sub-textures are supported: either we're on OpenGL 1.2, or
2799   the GL_EXT_texture3D extension is available.
2800 
2801   Methods then available for use:
2802 
2803   \li cc_glglue_glTexImage3D
2804   \li cc_glglue_glTexSubImage3D
2805   \li cc_glglue_glCopyTexSubImage3D
2806 */
2807 SbBool
cc_glglue_has_texsubimage(const cc_glglue * w)2808 cc_glglue_has_texsubimage(const cc_glglue * w)
2809 {
2810   if (!glglue_allow_newer_opengl(w)) return FALSE;
2811 
2812   return w->glTexSubImage2D ? TRUE : FALSE;
2813 }
2814 
2815 void
cc_glglue_glTexSubImage2D(const cc_glglue * w,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,const GLvoid * pixels)2816 cc_glglue_glTexSubImage2D(const cc_glglue * w,
2817                           GLenum target,
2818                           GLint level,
2819                           GLint xoffset,
2820                           GLint yoffset,
2821                           GLsizei width,
2822                           GLsizei height,
2823                           GLenum format,
2824                           GLenum type,
2825                           const GLvoid * pixels)
2826 {
2827   assert(w->glTexSubImage2D);
2828   w->glTexSubImage2D(target, level, xoffset, yoffset,
2829                      width, height, format, type, pixels);
2830 }
2831 
2832 /*!
2833   Whether 3D textures are available or not: either we're on OpenGL
2834   1.2, or the GL_EXT_texture3D extension is available.
2835 
2836   Methods then available for use:
2837 
2838   \li cc_glglue_glTexImage3D
2839   \li cc_glglue_glTexSubImage3D
2840   \li cc_glglue_glCopyTexSubImage3D
2841 */
2842 SbBool
cc_glglue_has_3d_textures(const cc_glglue * w)2843 cc_glglue_has_3d_textures(const cc_glglue * w)
2844 {
2845   if (!glglue_allow_newer_opengl(w)) return FALSE;
2846 
2847   return
2848     w->glTexImage3D &&
2849     w->glCopyTexSubImage3D &&
2850     w->glTexSubImage3D;
2851 }
2852 
2853 SbBool
cc_glglue_has_2d_proxy_textures(const cc_glglue * w)2854 cc_glglue_has_2d_proxy_textures(const cc_glglue * w)
2855 {
2856   if (!glglue_allow_newer_opengl(w)) return FALSE;
2857 
2858   // Our Proxy code seems to not be compatible with Intel drivers
2859   // FIXME: should be handled by SoGLDriverDatabase
2860   if (w->vendor_is_intel) return FALSE;
2861 
2862   /* FIXME: there are differences between the 1.1 proxy mechanisms and
2863      the GL_EXT_texture proxy extension; the 1.1 support considers
2864      mipmaps. I think. Check documentation in the GL spec. If that is
2865      correct, we can't really use them interchangeable versus each
2866      other like we now do in Coin code. 20030121 mortene. */
2867   return
2868     cc_glglue_glversion_matches_at_least(w, 1, 1, 0) ||
2869     cc_glglue_glext_supported(w, "GL_EXT_texture");
2870 }
2871 
2872 SbBool
cc_glglue_has_texture_edge_clamp(const cc_glglue * w)2873 cc_glglue_has_texture_edge_clamp(const cc_glglue * w)
2874 {
2875   static int buggytrident = -1;
2876 
2877   if (!glglue_allow_newer_opengl(w)) return FALSE;
2878 
2879   if (buggytrident == -1) {
2880     buggytrident = glglue_check_trident_clampedge_bug(w->vendorstr,
2881                                                       w->rendererstr,
2882                                                       w->versionstr);
2883   }
2884   if (buggytrident) { return FALSE; }
2885 
2886   return
2887     cc_glglue_glversion_matches_at_least(w, 1, 2, 0) ||
2888     cc_glglue_glext_supported(w, "GL_EXT_texture_edge_clamp") ||
2889     cc_glglue_glext_supported(w, "GL_SGIS_texture_edge_clamp");
2890 }
2891 
2892 void
cc_glglue_glPushClientAttrib(const cc_glglue * w,GLbitfield mask)2893 cc_glglue_glPushClientAttrib(const cc_glglue * w, GLbitfield mask)
2894 {
2895   if (!glglue_allow_newer_opengl(w)) return;
2896   assert(w->glPushClientAttrib);
2897   w->glPushClientAttrib(mask);
2898 }
2899 
2900 void
cc_glglue_glPopClientAttrib(const cc_glglue * w)2901 cc_glglue_glPopClientAttrib(const cc_glglue * w)
2902 {
2903   if (!glglue_allow_newer_opengl(w)) return;
2904   assert(w->glPopClientAttrib);
2905   w->glPopClientAttrib();
2906 }
2907 
2908 
2909 SbBool
cc_glglue_has_multitexture(const cc_glglue * w)2910 cc_glglue_has_multitexture(const cc_glglue * w)
2911 {
2912   if (!glglue_allow_newer_opengl(w)) return FALSE;
2913   return w->glActiveTexture != NULL;
2914 }
2915 
2916 int
cc_glglue_max_texture_units(const cc_glglue * w)2917 cc_glglue_max_texture_units(const cc_glglue * w)
2918 {
2919   if (!glglue_allow_newer_opengl(w)) return 1;
2920   return w->maxtextureunits; /* will be 1 when multitexturing is not available */
2921 }
2922 
2923 
2924 void
cc_glglue_glTexImage3D(const cc_glglue * w,GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,const GLvoid * pixels)2925 cc_glglue_glTexImage3D(const cc_glglue * w,
2926                        GLenum target,
2927                        GLint level,
2928                        GLenum internalformat,
2929                        GLsizei width,
2930                        GLsizei height,
2931                        GLsizei depth,
2932                        GLint border,
2933                        GLenum format,
2934                        GLenum type,
2935                        const GLvoid *pixels)
2936 {
2937   assert(w->glTexImage3D);
2938   w->glTexImage3D(target, level, internalformat,
2939                   width, height, depth, border,
2940                   format, type, pixels);
2941 }
2942 
2943 void
cc_glglue_glTexSubImage3D(const cc_glglue * w,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const GLvoid * pixels)2944 cc_glglue_glTexSubImage3D(const cc_glglue * w,
2945                           GLenum target,
2946                           GLint level,
2947                           GLint xoffset,
2948                           GLint yoffset,
2949                           GLint zoffset,
2950                           GLsizei width,
2951                           GLsizei height,
2952                           GLsizei depth,
2953                           GLenum format,
2954                           GLenum type,
2955                           const GLvoid * pixels)
2956 {
2957   assert(w->glTexSubImage3D);
2958   w->glTexSubImage3D(target, level, xoffset, yoffset,
2959                      zoffset, width, height, depth, format,
2960                      type, pixels);
2961 }
2962 
2963 void
cc_glglue_glCopyTexSubImage3D(const cc_glglue * w,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height)2964 cc_glglue_glCopyTexSubImage3D(const cc_glglue * w,
2965                               GLenum target,
2966                               GLint level,
2967                               GLint xoffset,
2968                               GLint yoffset,
2969                               GLint zoffset,
2970                               GLint x,
2971                               GLint y,
2972                               GLsizei width,
2973                               GLsizei height)
2974 {
2975   assert(w->glCopyTexSubImage3D);
2976   w->glCopyTexSubImage3D(target,
2977                          level,
2978                          xoffset,
2979                          yoffset,
2980                          zoffset,
2981                          x,
2982                          y,
2983                          width,
2984                          height);
2985 }
2986 
2987 void
cc_glglue_glActiveTexture(const cc_glglue * w,GLenum texture)2988 cc_glglue_glActiveTexture(const cc_glglue * w,
2989                           GLenum texture)
2990 {
2991   assert(w->glActiveTexture);
2992   w->glActiveTexture(texture);
2993 }
2994 
2995 void
cc_glglue_glClientActiveTexture(const cc_glglue * w,GLenum texture)2996 cc_glglue_glClientActiveTexture(const cc_glglue * w,
2997                                 GLenum texture)
2998 {
2999   if (!w->glClientActiveTexture && texture == GL_TEXTURE0)
3000     return;
3001   assert(w->glClientActiveTexture);
3002   w->glClientActiveTexture(texture);
3003 }
3004 void
cc_glglue_glMultiTexCoord2f(const cc_glglue * w,GLenum target,GLfloat s,GLfloat t)3005 cc_glglue_glMultiTexCoord2f(const cc_glglue * w,
3006                             GLenum target,
3007                             GLfloat s,
3008                             GLfloat t)
3009 {
3010   assert(w->glMultiTexCoord2f);
3011   w->glMultiTexCoord2f(target, s, t);
3012 }
3013 
3014 void
cc_glglue_glMultiTexCoord2fv(const cc_glglue * w,GLenum target,const GLfloat * v)3015 cc_glglue_glMultiTexCoord2fv(const cc_glglue * w,
3016                              GLenum target,
3017                              const GLfloat * v)
3018 {
3019   assert(w->glMultiTexCoord2fv);
3020   w->glMultiTexCoord2fv(target, v);
3021 }
3022 
3023 void
cc_glglue_glMultiTexCoord3fv(const cc_glglue * w,GLenum target,const GLfloat * v)3024 cc_glglue_glMultiTexCoord3fv(const cc_glglue * w,
3025                              GLenum target,
3026                              const GLfloat * v)
3027 {
3028   assert(w->glMultiTexCoord3fv);
3029   w->glMultiTexCoord3fv(target, v);
3030 }
3031 
3032 void
cc_glglue_glMultiTexCoord4fv(const cc_glglue * w,GLenum target,const GLfloat * v)3033 cc_glglue_glMultiTexCoord4fv(const cc_glglue * w,
3034                              GLenum target,
3035                              const GLfloat * v)
3036 {
3037   assert(w->glMultiTexCoord4fv);
3038   w->glMultiTexCoord4fv(target, v);
3039 }
3040 
3041 SbBool
cc_glue_has_texture_compression(const cc_glglue * glue)3042 cc_glue_has_texture_compression(const cc_glglue * glue)
3043 {
3044   if (!glglue_allow_newer_opengl(glue)) return FALSE;
3045 
3046   return
3047     glue->glCompressedTexImage1D &&
3048     glue->glCompressedTexImage2D &&
3049     glue->glCompressedTexImage3D &&
3050     glue->glGetCompressedTexImage;
3051 }
3052 
3053 SbBool
cc_glue_has_texture_compression_2d(const cc_glglue * glue)3054 cc_glue_has_texture_compression_2d(const cc_glglue * glue)
3055 {
3056   if (!glglue_allow_newer_opengl(glue)) return FALSE;
3057   return glue->glCompressedTexImage2D && glue->glGetCompressedTexImage;
3058 }
3059 
3060 SbBool
cc_glue_has_texture_compression_3d(const cc_glglue * glue)3061 cc_glue_has_texture_compression_3d(const cc_glglue * glue)
3062 {
3063   if (!glglue_allow_newer_opengl(glue)) return FALSE;
3064   return glue->glCompressedTexImage3D && glue->glGetCompressedTexImage;
3065 }
3066 
3067 void
cc_glglue_glCompressedTexImage3D(const cc_glglue * glue,GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei imageSize,const GLvoid * data)3068 cc_glglue_glCompressedTexImage3D(const cc_glglue * glue,
3069                                  GLenum target,
3070                                  GLint level,
3071                                  GLenum internalformat,
3072                                  GLsizei width,
3073                                  GLsizei height,
3074                                  GLsizei depth,
3075                                  GLint border,
3076                                  GLsizei imageSize,
3077                                  const GLvoid * data)
3078 {
3079   assert(glue->glCompressedTexImage3D);
3080   glue->glCompressedTexImage3D(target,
3081                                level,
3082                                internalformat,
3083                                width,
3084                                height,
3085                                depth,
3086                                border,
3087                                imageSize,
3088                                data);
3089 }
3090 
3091 void
cc_glglue_glCompressedTexImage2D(const cc_glglue * glue,GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLint border,GLsizei imageSize,const GLvoid * data)3092 cc_glglue_glCompressedTexImage2D(const cc_glglue * glue,
3093                                  GLenum target,
3094                                  GLint level,
3095                                  GLenum internalformat,
3096                                  GLsizei width,
3097                                  GLsizei height,
3098                                  GLint border,
3099                                  GLsizei imageSize,
3100                                  const GLvoid *data)
3101 {
3102   assert(glue->glCompressedTexImage2D);
3103   glue->glCompressedTexImage2D(target,
3104                                level,
3105                                internalformat,
3106                                width,
3107                                height,
3108                                border,
3109                                imageSize,
3110                                data);
3111 }
3112 
3113 void
cc_glglue_glCompressedTexImage1D(const cc_glglue * glue,GLenum target,GLint level,GLenum internalformat,GLsizei width,GLint border,GLsizei imageSize,const GLvoid * data)3114 cc_glglue_glCompressedTexImage1D(const cc_glglue * glue,
3115                                  GLenum target,
3116                                  GLint level,
3117                                  GLenum internalformat,
3118                                  GLsizei width,
3119                                  GLint border,
3120                                  GLsizei imageSize,
3121                                  const GLvoid *data)
3122 {
3123   assert(glue->glCompressedTexImage1D);
3124   glue->glCompressedTexImage1D(target,
3125                                level,
3126                                internalformat,
3127                                width,
3128                                border,
3129                                imageSize,
3130                                data);
3131 }
3132 
3133 void
cc_glglue_glCompressedTexSubImage3D(const cc_glglue * glue,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,const GLvoid * data)3134 cc_glglue_glCompressedTexSubImage3D(const cc_glglue * glue,
3135                                     GLenum target,
3136                                     GLint level,
3137                                     GLint xoffset,
3138                                     GLint yoffset,
3139                                     GLint zoffset,
3140                                     GLsizei width,
3141                                     GLsizei height,
3142                                     GLsizei depth,
3143                                     GLenum format,
3144                                     GLsizei imageSize,
3145                                     const GLvoid *data)
3146 {
3147   assert(glue->glCompressedTexSubImage3D);
3148   glue->glCompressedTexSubImage3D(target,
3149                                   level,
3150                                   xoffset,
3151                                   yoffset,
3152                                   zoffset,
3153                                   width,
3154                                   height,
3155                                   depth,
3156                                   format,
3157                                   imageSize,
3158                                   data);
3159 }
3160 
3161 void
cc_glglue_glCompressedTexSubImage2D(const cc_glglue * glue,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLsizei imageSize,const GLvoid * data)3162 cc_glglue_glCompressedTexSubImage2D(const cc_glglue * glue,
3163                                     GLenum target,
3164                                     GLint level,
3165                                     GLint xoffset,
3166                                     GLint yoffset,
3167                                     GLsizei width,
3168                                     GLsizei height,
3169                                     GLenum format,
3170                                     GLsizei imageSize,
3171                                     const GLvoid *data)
3172 {
3173   assert(glue->glCompressedTexSubImage2D);
3174   glue->glCompressedTexSubImage2D(target,
3175                                   level,
3176                                   xoffset,
3177                                   yoffset,
3178                                   width,
3179                                   height,
3180                                   format,
3181                                   imageSize,
3182                                   data);
3183 }
3184 
3185 void
cc_glglue_glCompressedTexSubImage1D(const cc_glglue * glue,GLenum target,GLint level,GLint xoffset,GLsizei width,GLenum format,GLsizei imageSize,const GLvoid * data)3186 cc_glglue_glCompressedTexSubImage1D(const cc_glglue * glue,
3187                                     GLenum target,
3188                                     GLint level,
3189                                     GLint xoffset,
3190                                     GLsizei width,
3191                                     GLenum format,
3192                                     GLsizei imageSize,
3193                                     const GLvoid *data)
3194 {
3195   assert(glue->glCompressedTexSubImage1D);
3196   glue->glCompressedTexSubImage1D(target,
3197                                   level,
3198                                   xoffset,
3199                                   width,
3200                                   format,
3201                                   imageSize,
3202                                   data);
3203 }
3204 
3205 void
cc_glglue_glGetCompressedTexImage(const cc_glglue * glue,GLenum target,GLint level,void * img)3206 cc_glglue_glGetCompressedTexImage(const cc_glglue * glue,
3207                                   GLenum target,
3208                                   GLint level,
3209                                   void * img)
3210 {
3211   assert(glue->glGetCompressedTexImage);
3212   glue->glGetCompressedTexImage(target,
3213                                 level,
3214                                 img);
3215 }
3216 
3217 SbBool
cc_glglue_has_paletted_textures(const cc_glglue * glue)3218 cc_glglue_has_paletted_textures(const cc_glglue * glue)
3219 {
3220   static int disable = -1;
3221   if (disable == -1) {
3222     disable = glglue_resolve_envvar("COIN_GLGLUE_DISABLE_PALETTED_TEXTURE");
3223   }
3224   if (disable) { return FALSE; }
3225 
3226   if (!glglue_allow_newer_opengl(glue)) { return FALSE; }
3227   return glue->supportsPalettedTextures;
3228 }
3229 
3230 SbBool
cc_glglue_has_color_tables(const cc_glglue * glue)3231 cc_glglue_has_color_tables(const cc_glglue * glue)
3232 {
3233   if (!glglue_allow_newer_opengl(glue)) return FALSE;
3234   return glue->glColorTable != NULL;
3235 }
3236 
3237 SbBool
cc_glglue_has_color_subtables(const cc_glglue * glue)3238 cc_glglue_has_color_subtables(const cc_glglue * glue)
3239 {
3240   if (!glglue_allow_newer_opengl(glue)) return FALSE;
3241   return glue->glColorSubTable != NULL;
3242 }
3243 
3244 void
cc_glglue_glColorTable(const cc_glglue * glue,GLenum target,GLenum internalFormat,GLsizei width,GLenum format,GLenum type,const GLvoid * table)3245 cc_glglue_glColorTable(const cc_glglue * glue,
3246                        GLenum target,
3247                        GLenum internalFormat,
3248                        GLsizei width,
3249                        GLenum format,
3250                        GLenum type,
3251                        const GLvoid *table)
3252 {
3253   assert(glue->glColorTable);
3254   glue->glColorTable(target,
3255                      internalFormat,
3256                      width,
3257                      format,
3258                      type,
3259                      table);
3260 }
3261 
3262 void
cc_glglue_glColorSubTable(const cc_glglue * glue,GLenum target,GLsizei start,GLsizei count,GLenum format,GLenum type,const GLvoid * data)3263 cc_glglue_glColorSubTable(const cc_glglue * glue,
3264                           GLenum target,
3265                           GLsizei start,
3266                           GLsizei count,
3267                           GLenum format,
3268                           GLenum type,
3269                           const GLvoid * data)
3270 {
3271   assert(glue->glColorSubTable);
3272   glue->glColorSubTable(target,
3273                         start,
3274                         count,
3275                         format,
3276                         type,
3277                         data);
3278 }
3279 
3280 void
cc_glglue_glGetColorTable(const cc_glglue * glue,GLenum target,GLenum format,GLenum type,GLvoid * data)3281 cc_glglue_glGetColorTable(const cc_glglue * glue,
3282                           GLenum target,
3283                           GLenum format,
3284                           GLenum type,
3285                           GLvoid *data)
3286 {
3287   assert(glue->glGetColorTable);
3288   glue->glGetColorTable(target,
3289                         format,
3290                         type,
3291                         data);
3292 }
3293 
3294 void
cc_glglue_glGetColorTableParameteriv(const cc_glglue * glue,GLenum target,GLenum pname,GLint * params)3295 cc_glglue_glGetColorTableParameteriv(const cc_glglue * glue,
3296                                      GLenum target,
3297                                      GLenum pname,
3298                                      GLint *params)
3299 {
3300   assert(glue->glGetColorTableParameteriv);
3301   glue->glGetColorTableParameteriv(target,
3302                                    pname,
3303                                    params);
3304 }
3305 
3306 void
cc_glglue_glGetColorTableParameterfv(const cc_glglue * glue,GLenum target,GLenum pname,GLfloat * params)3307 cc_glglue_glGetColorTableParameterfv(const cc_glglue * glue,
3308                                      GLenum target,
3309                                      GLenum pname,
3310                                      GLfloat *params)
3311 {
3312   assert(glue->glGetColorTableParameterfv);
3313   glue->glGetColorTableParameterfv(target,
3314                                    pname,
3315                                    params);
3316 }
3317 
3318 SbBool
cc_glglue_has_blendequation(const cc_glglue * glue)3319 cc_glglue_has_blendequation(const cc_glglue * glue)
3320 {
3321   if (!glglue_allow_newer_opengl(glue)) return FALSE;
3322 
3323   return glue->glBlendEquation || glue->glBlendEquationEXT;
3324 }
3325 
3326 void
cc_glglue_glBlendEquation(const cc_glglue * glue,GLenum mode)3327 cc_glglue_glBlendEquation(const cc_glglue * glue, GLenum mode)
3328 {
3329   assert(glue->glBlendEquation || glue->glBlendEquationEXT);
3330 
3331   if (glue->glBlendEquation) glue->glBlendEquation(mode);
3332   else glue->glBlendEquationEXT(mode);
3333 }
3334 
3335 SbBool
cc_glglue_has_blendfuncseparate(const cc_glglue * glue)3336 cc_glglue_has_blendfuncseparate(const cc_glglue * glue)
3337 {
3338   if (!glglue_allow_newer_opengl(glue)) return FALSE;
3339 
3340   return glue->glBlendFuncSeparate != NULL;
3341 }
3342 
3343 void
cc_glglue_glBlendFuncSeparate(const cc_glglue * glue,GLenum rgbsrc,GLenum rgbdst,GLenum alphasrc,GLenum alphadst)3344 cc_glglue_glBlendFuncSeparate(const cc_glglue * glue,
3345                               GLenum rgbsrc, GLenum rgbdst,
3346                               GLenum alphasrc, GLenum alphadst)
3347 {
3348   assert(glue->glBlendFuncSeparate);
3349   glue->glBlendFuncSeparate(rgbsrc, rgbdst, alphasrc, alphadst);
3350 }
3351 
3352 SbBool
cc_glglue_has_vertex_array(const cc_glglue * glue)3353 cc_glglue_has_vertex_array(const cc_glglue * glue)
3354 {
3355   if (!glglue_allow_newer_opengl(glue)) return FALSE;
3356   return glue->glVertexPointer != NULL;
3357 }
3358 
3359 void
cc_glglue_glVertexPointer(const cc_glglue * glue,GLint size,GLenum type,GLsizei stride,const GLvoid * pointer)3360 cc_glglue_glVertexPointer(const cc_glglue * glue,
3361                           GLint size, GLenum type, GLsizei stride, const GLvoid * pointer)
3362 {
3363   assert(glue->glVertexPointer);
3364   glue->glVertexPointer(size, type, stride, pointer);
3365 }
3366 
3367 void
cc_glglue_glTexCoordPointer(const cc_glglue * glue,GLint size,GLenum type,GLsizei stride,const GLvoid * pointer)3368 cc_glglue_glTexCoordPointer(const cc_glglue * glue,
3369                             GLint size, GLenum type,
3370                             GLsizei stride, const GLvoid * pointer)
3371 {
3372   assert(glue->glTexCoordPointer);
3373   glue->glTexCoordPointer(size, type, stride, pointer);
3374 }
3375 
3376 void
cc_glglue_glNormalPointer(const cc_glglue * glue,GLenum type,GLsizei stride,const GLvoid * pointer)3377 cc_glglue_glNormalPointer(const cc_glglue * glue,
3378                           GLenum type, GLsizei stride, const GLvoid *pointer)
3379 {
3380   assert(glue->glNormalPointer);
3381   glue->glNormalPointer(type, stride, pointer);
3382 }
3383 
3384 void
cc_glglue_glColorPointer(const cc_glglue * glue,GLint size,GLenum type,GLsizei stride,const GLvoid * pointer)3385 cc_glglue_glColorPointer(const cc_glglue * glue,
3386                          GLint size, GLenum type,
3387                          GLsizei stride, const GLvoid * pointer)
3388 {
3389   assert(glue->glColorPointer);
3390   glue->glColorPointer(size, type, stride, pointer);
3391 }
3392 
3393 void
cc_glglue_glIndexPointer(const cc_glglue * glue,GLenum type,GLsizei stride,const GLvoid * pointer)3394 cc_glglue_glIndexPointer(const cc_glglue * glue,
3395                          GLenum type, GLsizei stride, const GLvoid * pointer)
3396 {
3397   assert(glue->glIndexPointer);
3398   glue->glIndexPointer(type, stride, pointer);
3399 }
3400 
3401 void
cc_glglue_glEnableClientState(const cc_glglue * glue,GLenum array)3402 cc_glglue_glEnableClientState(const cc_glglue * glue, GLenum array)
3403 {
3404   assert(glue->glEnableClientState);
3405   glue->glEnableClientState(array);
3406 }
3407 
3408 void
cc_glglue_glDisableClientState(const cc_glglue * glue,GLenum array)3409 cc_glglue_glDisableClientState(const cc_glglue * glue, GLenum array)
3410 {
3411   assert(glue->glDisableClientState);
3412   glue->glDisableClientState(array);
3413 }
3414 
3415 void
cc_glglue_glInterleavedArrays(const cc_glglue * glue,GLenum format,GLsizei stride,const GLvoid * pointer)3416 cc_glglue_glInterleavedArrays(const cc_glglue * glue,
3417                               GLenum format, GLsizei stride, const GLvoid * pointer)
3418 {
3419   assert(glue->glInterleavedArrays);
3420   glue->glInterleavedArrays(format, stride, pointer);
3421 }
3422 
3423 void
cc_glglue_glDrawArrays(const cc_glglue * glue,GLenum mode,GLint first,GLsizei count)3424 cc_glglue_glDrawArrays(const cc_glglue * glue,
3425                        GLenum mode, GLint first, GLsizei count)
3426 {
3427   assert(glue->glDrawArrays);
3428   glue->glDrawArrays(mode, first, count);
3429 }
3430 
3431 void
cc_glglue_glDrawElements(const cc_glglue * glue,GLenum mode,GLsizei count,GLenum type,const GLvoid * indices)3432 cc_glglue_glDrawElements(const cc_glglue * glue,
3433                          GLenum mode, GLsizei count, GLenum type,
3434                          const GLvoid * indices)
3435 {
3436   assert(glue->glDrawElements);
3437   glue->glDrawElements(mode, count, type, indices);
3438 }
3439 
3440 void
cc_glglue_glDrawRangeElements(const cc_glglue * glue,GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid * indices)3441 cc_glglue_glDrawRangeElements(const cc_glglue * glue,
3442                               GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type,
3443                               const GLvoid * indices)
3444 {
3445   assert(glue->glDrawRangeElements);
3446   glue->glDrawRangeElements(mode, start, end, count, type, indices);
3447 }
3448 
3449 void
cc_glglue_glArrayElement(const cc_glglue * glue,GLint i)3450 cc_glglue_glArrayElement(const cc_glglue * glue, GLint i)
3451 {
3452   assert(glue->glArrayElement);
3453   glue->glArrayElement(i);
3454 }
3455 
3456 SbBool
cc_glglue_has_multidraw_vertex_arrays(const cc_glglue * glue)3457 cc_glglue_has_multidraw_vertex_arrays(const cc_glglue * glue)
3458 {
3459   if (!glglue_allow_newer_opengl(glue)) return FALSE;
3460   return glue->glMultiDrawArrays && glue->glMultiDrawElements;
3461 }
3462 
3463 void
cc_glglue_glMultiDrawArrays(const cc_glglue * glue,GLenum mode,const GLint * first,const GLsizei * count,GLsizei primcount)3464 cc_glglue_glMultiDrawArrays(const cc_glglue * glue, GLenum mode, const GLint * first,
3465                             const GLsizei * count, GLsizei primcount)
3466 {
3467   assert(glue->glMultiDrawArrays);
3468   glue->glMultiDrawArrays(mode, first, count, primcount);
3469 }
3470 
3471 void
cc_glglue_glMultiDrawElements(const cc_glglue * glue,GLenum mode,const GLsizei * count,GLenum type,const GLvoid ** indices,GLsizei primcount)3472 cc_glglue_glMultiDrawElements(const cc_glglue * glue, GLenum mode, const GLsizei * count,
3473                               GLenum type, const GLvoid ** indices, GLsizei primcount)
3474 {
3475   assert(glue->glMultiDrawElements);
3476   glue->glMultiDrawElements(mode, count, type, indices, primcount);
3477 }
3478 
3479 SbBool
cc_glglue_has_nv_vertex_array_range(const cc_glglue * glue)3480 cc_glglue_has_nv_vertex_array_range(const cc_glglue * glue)
3481 {
3482   if (!glglue_allow_newer_opengl(glue)) return FALSE;
3483   return glue->glVertexArrayRangeNV != NULL;
3484 }
3485 
3486 void
cc_glglue_glFlushVertexArrayRangeNV(const cc_glglue * glue)3487 cc_glglue_glFlushVertexArrayRangeNV(const cc_glglue * glue)
3488 {
3489   assert(glue->glFlushVertexArrayRangeNV);
3490   glue->glFlushVertexArrayRangeNV();
3491 }
3492 
3493 void
cc_glglue_glVertexArrayRangeNV(const cc_glglue * glue,GLsizei size,const GLvoid * pointer)3494 cc_glglue_glVertexArrayRangeNV(const cc_glglue * glue, GLsizei size, const GLvoid * pointer)
3495 {
3496   assert(glue->glVertexArrayRangeNV);
3497   glue->glVertexArrayRangeNV(size, pointer);
3498 }
3499 
3500 void *
cc_glglue_glAllocateMemoryNV(const cc_glglue * glue,GLsizei size,GLfloat readfreq,GLfloat writefreq,GLfloat priority)3501 cc_glglue_glAllocateMemoryNV(const cc_glglue * glue,
3502                              GLsizei size, GLfloat readfreq,
3503                              GLfloat writefreq, GLfloat priority)
3504 {
3505   assert(glue->glAllocateMemoryNV);
3506   return glue->glAllocateMemoryNV(size, readfreq, writefreq, priority);
3507 }
3508 
3509 void
cc_glglue_glFreeMemoryNV(const cc_glglue * glue,GLvoid * buffer)3510 cc_glglue_glFreeMemoryNV(const cc_glglue * glue, GLvoid * buffer)
3511 {
3512   assert(glue->glFreeMemoryNV);
3513   glue->glFreeMemoryNV(buffer);
3514 }
3515 
3516 SbBool
cc_glglue_has_vertex_buffer_object(const cc_glglue * glue)3517 cc_glglue_has_vertex_buffer_object(const cc_glglue * glue)
3518 {
3519   if (!glglue_allow_newer_opengl(glue)) return FALSE;
3520 
3521   /* check only one function for speed. It's set to NULL when
3522      initializing if one of the other functions wasn't found */
3523   return glue->glBindBuffer != NULL;
3524 }
3525 
3526 void
cc_glglue_glBindBuffer(const cc_glglue * glue,GLenum target,GLuint buffer)3527 cc_glglue_glBindBuffer(const cc_glglue * glue, GLenum target, GLuint buffer)
3528 {
3529   assert(glue->glBindBuffer);
3530   glue->glBindBuffer(target, buffer);
3531 }
3532 
3533 void
cc_glglue_glDeleteBuffers(const cc_glglue * glue,GLsizei n,const GLuint * buffers)3534 cc_glglue_glDeleteBuffers(const cc_glglue * glue, GLsizei n, const GLuint *buffers)
3535 {
3536   assert(glue->glDeleteBuffers);
3537   glue->glDeleteBuffers(n, buffers);
3538 }
3539 
3540 void
cc_glglue_glGenBuffers(const cc_glglue * glue,GLsizei n,GLuint * buffers)3541 cc_glglue_glGenBuffers(const cc_glglue * glue, GLsizei n, GLuint *buffers)
3542 {
3543   assert(glue->glGenBuffers);
3544   glue->glGenBuffers(n, buffers);
3545 }
3546 
3547 GLboolean
cc_glglue_glIsBuffer(const cc_glglue * glue,GLuint buffer)3548 cc_glglue_glIsBuffer(const cc_glglue * glue, GLuint buffer)
3549 {
3550   assert(glue->glIsBuffer);
3551   return glue->glIsBuffer(buffer);
3552 }
3553 
3554 void
cc_glglue_glBufferData(const cc_glglue * glue,GLenum target,intptr_t size,const GLvoid * data,GLenum usage)3555 cc_glglue_glBufferData(const cc_glglue * glue,
3556                        GLenum target,
3557                        intptr_t size, /* 64 bit on 64 bit systems */
3558                        const GLvoid *data,
3559                        GLenum usage)
3560 {
3561   assert(glue->glBufferData);
3562   glue->glBufferData(target, size, data, usage);
3563 }
3564 
3565 void
cc_glglue_glBufferSubData(const cc_glglue * glue,GLenum target,intptr_t offset,intptr_t size,const GLvoid * data)3566 cc_glglue_glBufferSubData(const cc_glglue * glue,
3567                           GLenum target,
3568                           intptr_t offset, /* 64 bit */
3569                           intptr_t size, /* 64 bit */
3570                           const GLvoid * data)
3571 {
3572   assert(glue->glBufferSubData);
3573   glue->glBufferSubData(target, offset, size, data);
3574 }
3575 
3576 void
cc_glglue_glGetBufferSubData(const cc_glglue * glue,GLenum target,intptr_t offset,intptr_t size,GLvoid * data)3577 cc_glglue_glGetBufferSubData(const cc_glglue * glue,
3578                              GLenum target,
3579                              intptr_t offset, /* 64 bit */
3580                              intptr_t size, /* 64 bit */
3581                              GLvoid *data)
3582 {
3583   assert(glue->glGetBufferSubData);
3584   glue->glGetBufferSubData(target, offset, size, data);
3585 }
3586 
3587 GLvoid *
cc_glglue_glMapBuffer(const cc_glglue * glue,GLenum target,GLenum access)3588 cc_glglue_glMapBuffer(const cc_glglue * glue,
3589                       GLenum target, GLenum access)
3590 {
3591   assert(glue->glMapBuffer);
3592   return glue->glMapBuffer(target, access);
3593 }
3594 
3595 GLboolean
cc_glglue_glUnmapBuffer(const cc_glglue * glue,GLenum target)3596 cc_glglue_glUnmapBuffer(const cc_glglue * glue,
3597                         GLenum target)
3598 {
3599   assert(glue->glUnmapBuffer);
3600   return glue->glUnmapBuffer(target);
3601 }
3602 
3603 void
cc_glglue_glGetBufferParameteriv(const cc_glglue * glue,GLenum target,GLenum pname,GLint * params)3604 cc_glglue_glGetBufferParameteriv(const cc_glglue * glue,
3605                                  GLenum target,
3606                                  GLenum pname,
3607                                  GLint * params)
3608 {
3609   assert(glue->glGetBufferParameteriv);
3610   glue->glGetBufferParameteriv(target, pname, params);
3611 }
3612 
3613 void
cc_glglue_glGetBufferPointerv(const cc_glglue * glue,GLenum target,GLenum pname,GLvoid ** params)3614 cc_glglue_glGetBufferPointerv(const cc_glglue * glue,
3615                               GLenum target,
3616                               GLenum pname,
3617                               GLvoid ** params)
3618 {
3619   assert(glue->glGetBufferPointerv);
3620   glue->glGetBufferPointerv(target, pname, params);
3621 }
3622 
3623 
3624 SbBool
cc_glglue_can_do_bumpmapping(const cc_glglue * glue)3625 cc_glglue_can_do_bumpmapping(const cc_glglue * glue)
3626 {
3627   if (!glglue_allow_newer_opengl(glue)) return FALSE;
3628   return glue->can_do_bumpmapping;
3629 }
3630 
3631 SbBool
cc_glglue_can_do_sortedlayersblend(const cc_glglue * glue)3632 cc_glglue_can_do_sortedlayersblend(const cc_glglue * glue)
3633 {
3634   if (!glglue_allow_newer_opengl(glue)) return FALSE;
3635   return glue->can_do_sortedlayersblend;
3636 }
3637 
3638 int
cc_glglue_get_max_lights(const cc_glglue * glue)3639 cc_glglue_get_max_lights(const cc_glglue * glue)
3640 {
3641   return glue->max_lights;
3642 }
3643 
3644 const float *
cc_glglue_get_line_width_range(const cc_glglue * glue)3645 cc_glglue_get_line_width_range(const cc_glglue * glue)
3646 {
3647   return glue->line_width_range;
3648 }
3649 
3650 const float *
cc_glglue_get_point_size_range(const cc_glglue * glue)3651 cc_glglue_get_point_size_range(const cc_glglue * glue)
3652 {
3653   return glue->point_size_range;
3654 }
3655 
3656 /* GL_NV_register_combiners functions */
3657 SbBool
cc_glglue_has_nv_register_combiners(const cc_glglue * glue)3658 cc_glglue_has_nv_register_combiners(const cc_glglue * glue)
3659 {
3660   if (!glglue_allow_newer_opengl(glue)) return FALSE;
3661   return glue->has_nv_register_combiners;
3662 }
3663 
3664 void
cc_glglue_glCombinerParameterfvNV(const cc_glglue * glue,GLenum pname,const GLfloat * params)3665 cc_glglue_glCombinerParameterfvNV(const cc_glglue * glue,
3666                                   GLenum pname,
3667                                   const GLfloat *params)
3668 {
3669   glue->glCombinerParameterfvNV(pname, params);
3670 }
3671 
3672 void
cc_glglue_glCombinerParameterivNV(const cc_glglue * glue,GLenum pname,const GLint * params)3673 cc_glglue_glCombinerParameterivNV(const cc_glglue * glue,
3674                                   GLenum pname,
3675                                   const GLint *params)
3676 {
3677   glue->glCombinerParameterivNV(pname, params);
3678 }
3679 
3680 void
cc_glglue_glCombinerParameterfNV(const cc_glglue * glue,GLenum pname,GLfloat param)3681 cc_glglue_glCombinerParameterfNV(const cc_glglue * glue,
3682                                  GLenum pname,
3683                                  GLfloat param)
3684 {
3685   glue->glCombinerParameterfNV(pname, param);
3686 }
3687 
3688 void
cc_glglue_glCombinerParameteriNV(const cc_glglue * glue,GLenum pname,GLint param)3689 cc_glglue_glCombinerParameteriNV(const cc_glglue * glue,
3690                                  GLenum pname,
3691                                  GLint param)
3692 {
3693   glue->glCombinerParameteriNV(pname, param);
3694 }
3695 
3696 void
cc_glglue_glCombinerInputNV(const cc_glglue * glue,GLenum stage,GLenum portion,GLenum variable,GLenum input,GLenum mapping,GLenum componentUsage)3697 cc_glglue_glCombinerInputNV(const cc_glglue * glue,
3698                             GLenum stage,
3699                             GLenum portion,
3700                             GLenum variable,
3701                             GLenum input,
3702                             GLenum mapping,
3703                             GLenum componentUsage)
3704 {
3705   glue->glCombinerInputNV(stage, portion, variable, input, mapping, componentUsage);
3706 }
3707 
3708 void
cc_glglue_glCombinerOutputNV(const cc_glglue * glue,GLenum stage,GLenum portion,GLenum abOutput,GLenum cdOutput,GLenum sumOutput,GLenum scale,GLenum bias,GLboolean abDotProduct,GLboolean cdDotProduct,GLboolean muxSum)3709 cc_glglue_glCombinerOutputNV(const cc_glglue * glue,
3710                              GLenum stage,
3711                              GLenum portion,
3712                              GLenum abOutput,
3713                              GLenum cdOutput,
3714                              GLenum sumOutput,
3715                              GLenum scale,
3716                              GLenum bias,
3717                              GLboolean abDotProduct,
3718                              GLboolean cdDotProduct,
3719                              GLboolean muxSum)
3720 {
3721   glue->glCombinerOutputNV(stage, portion, abOutput, cdOutput, sumOutput, scale, bias,
3722                            abDotProduct, cdDotProduct, muxSum);
3723 }
3724 
3725 void
cc_glglue_glFinalCombinerInputNV(const cc_glglue * glue,GLenum variable,GLenum input,GLenum mapping,GLenum componentUsage)3726 cc_glglue_glFinalCombinerInputNV(const cc_glglue * glue,
3727                                  GLenum variable,
3728                                  GLenum input,
3729                                  GLenum mapping,
3730                                  GLenum componentUsage)
3731 {
3732   glue->glFinalCombinerInputNV(variable, input, mapping, componentUsage);
3733 }
3734 
3735 void
cc_glglue_glGetCombinerInputParameterfvNV(const cc_glglue * glue,GLenum stage,GLenum portion,GLenum variable,GLenum pname,GLfloat * params)3736 cc_glglue_glGetCombinerInputParameterfvNV(const cc_glglue * glue,
3737                                           GLenum stage,
3738                                           GLenum portion,
3739                                           GLenum variable,
3740                                           GLenum pname,
3741                                           GLfloat *params)
3742 {
3743   glue->glGetCombinerInputParameterfvNV(stage, portion, variable, pname, params);
3744 }
3745 
3746 void
cc_glglue_glGetCombinerInputParameterivNV(const cc_glglue * glue,GLenum stage,GLenum portion,GLenum variable,GLenum pname,GLint * params)3747 cc_glglue_glGetCombinerInputParameterivNV(const cc_glglue * glue,
3748                                           GLenum stage,
3749                                           GLenum portion,
3750                                           GLenum variable,
3751                                           GLenum pname,
3752                                           GLint *params)
3753 {
3754   glue->glGetCombinerInputParameterivNV(stage, portion, variable, pname, params);
3755 }
3756 
3757 void
cc_glglue_glGetCombinerOutputParameterfvNV(const cc_glglue * glue,GLenum stage,GLenum portion,GLenum pname,GLfloat * params)3758 cc_glglue_glGetCombinerOutputParameterfvNV(const cc_glglue * glue,
3759                                            GLenum stage,
3760                                            GLenum portion,
3761                                            GLenum pname,
3762                                            GLfloat *params)
3763 {
3764   glue->glGetCombinerOutputParameterfvNV(stage, portion, pname, params);
3765 }
3766 
3767 void
cc_glglue_glGetCombinerOutputParameterivNV(const cc_glglue * glue,GLenum stage,GLenum portion,GLenum pname,GLint * params)3768 cc_glglue_glGetCombinerOutputParameterivNV(const cc_glglue * glue,
3769                                            GLenum stage,
3770                                            GLenum portion,
3771                                            GLenum pname,
3772                                            GLint *params)
3773 {
3774   glue->glGetCombinerOutputParameterivNV(stage, portion, pname, params);
3775 }
3776 
3777 void
cc_glglue_glGetFinalCombinerInputParameterfvNV(const cc_glglue * glue,GLenum variable,GLenum pname,GLfloat * params)3778 cc_glglue_glGetFinalCombinerInputParameterfvNV(const cc_glglue * glue,
3779                                                GLenum variable,
3780                                                GLenum pname,
3781                                                GLfloat *params)
3782 {
3783   glue->glGetFinalCombinerInputParameterfvNV(variable, pname, params);
3784 }
3785 
3786 void
cc_glglue_glGetFinalCombinerInputParameterivNV(const cc_glglue * glue,GLenum variable,GLenum pname,GLint * params)3787 cc_glglue_glGetFinalCombinerInputParameterivNV(const cc_glglue * glue,
3788                                                GLenum variable,
3789                                                GLenum pname,
3790                                                GLint *params)
3791 {
3792   glue->glGetFinalCombinerInputParameterivNV(variable, pname, params);
3793 }
3794 
3795 /* ARB_shader_objects */
3796 SbBool
cc_glglue_has_arb_shader_objects(const cc_glglue * glue)3797 cc_glglue_has_arb_shader_objects(const cc_glglue * glue)
3798 {
3799   if (!glglue_allow_newer_opengl(glue)) return FALSE;
3800   return glue->has_arb_shader_objects;
3801 }
3802 
3803 
3804 /* ARB_fragment_program functions */
3805 SbBool
cc_glglue_has_arb_fragment_program(const cc_glglue * glue)3806 cc_glglue_has_arb_fragment_program(const cc_glglue * glue)
3807 {
3808   if (!glglue_allow_newer_opengl(glue)) return FALSE;
3809   return glue->has_arb_fragment_program;
3810 }
3811 
3812 void
cc_glglue_glProgramString(const cc_glglue * glue,GLenum target,GLenum format,GLsizei len,const GLvoid * string)3813 cc_glglue_glProgramString(const cc_glglue * glue,
3814                           GLenum target,
3815                           GLenum format,
3816                           GLsizei len,
3817                           const GLvoid *string)
3818 {
3819   glue->glProgramStringARB(target, format, len, string);
3820 }
3821 
3822 void
cc_glglue_glBindProgram(const cc_glglue * glue,GLenum target,GLuint program)3823 cc_glglue_glBindProgram(const cc_glglue * glue,
3824                         GLenum target,
3825                         GLuint program)
3826 {
3827   glue->glBindProgramARB(target, program);
3828 }
3829 
3830 void
cc_glglue_glDeletePrograms(const cc_glglue * glue,GLsizei n,const GLuint * programs)3831 cc_glglue_glDeletePrograms(const cc_glglue * glue,
3832                            GLsizei n,
3833                            const GLuint *programs)
3834 {
3835   glue->glDeleteProgramsARB(n, programs);
3836 }
3837 
3838 void
cc_glglue_glGenPrograms(const cc_glglue * glue,GLsizei n,GLuint * programs)3839 cc_glglue_glGenPrograms(const cc_glglue * glue,
3840                         GLsizei n,
3841                         GLuint *programs)
3842 {
3843   glue->glGenProgramsARB(n, programs);
3844 }
3845 
3846 void
cc_glglue_glProgramEnvParameter4d(const cc_glglue * glue,GLenum target,GLuint index,GLdouble x,GLdouble y,GLdouble z,GLdouble w)3847 cc_glglue_glProgramEnvParameter4d(const cc_glglue * glue,
3848                                   GLenum target,
3849                                   GLuint index,
3850                                   GLdouble x,
3851                                   GLdouble y,
3852                                   GLdouble z,
3853                                   GLdouble w)
3854 {
3855   glue->glProgramEnvParameter4dARB(target, index, x, y, z, w);
3856 }
3857 
3858 void
cc_glglue_glProgramEnvParameter4dv(const cc_glglue * glue,GLenum target,GLuint index,const GLdouble * params)3859 cc_glglue_glProgramEnvParameter4dv(const cc_glglue * glue,
3860                                    GLenum target,
3861                                    GLuint index,
3862                                    const GLdouble *params)
3863 {
3864   glue->glProgramEnvParameter4dvARB(target, index, params);
3865 }
3866 
3867 void
cc_glglue_glProgramEnvParameter4f(const cc_glglue * glue,GLenum target,GLuint index,GLfloat x,GLfloat y,GLfloat z,GLfloat w)3868 cc_glglue_glProgramEnvParameter4f(const cc_glglue * glue,
3869                                   GLenum target,
3870                                   GLuint index,
3871                                   GLfloat x,
3872                                   GLfloat y,
3873                                   GLfloat z,
3874                                   GLfloat w)
3875 {
3876   glue->glProgramEnvParameter4fARB(target, index, x, y, z, w);
3877 }
3878 
3879 void
cc_glglue_glProgramEnvParameter4fv(const cc_glglue * glue,GLenum target,GLuint index,const GLfloat * params)3880 cc_glglue_glProgramEnvParameter4fv(const cc_glglue * glue,
3881                                    GLenum target,
3882                                    GLuint index,
3883                                    const GLfloat *params)
3884 {
3885   glue->glProgramEnvParameter4fvARB(target, index, params);
3886 }
3887 
3888 void
cc_glglue_glProgramLocalParameter4d(const cc_glglue * glue,GLenum target,GLuint index,GLdouble x,GLdouble y,GLdouble z,GLdouble w)3889 cc_glglue_glProgramLocalParameter4d(const cc_glglue * glue,
3890                                     GLenum target,
3891                                     GLuint index,
3892                                     GLdouble x,
3893                                     GLdouble y,
3894                                     GLdouble z,
3895                                     GLdouble w)
3896 {
3897   glue->glProgramLocalParameter4dARB(target, index, x, y, z, w);
3898 }
3899 
3900 void
cc_glglue_glProgramLocalParameter4dv(const cc_glglue * glue,GLenum target,GLuint index,const GLdouble * params)3901 cc_glglue_glProgramLocalParameter4dv(const cc_glglue * glue,
3902                                      GLenum target,
3903                                      GLuint index,
3904                                      const GLdouble *params)
3905 {
3906   glue->glProgramLocalParameter4dvARB(target, index, params);
3907 }
3908 
3909 void
cc_glglue_glProgramLocalParameter4f(const cc_glglue * glue,GLenum target,GLuint index,GLfloat x,GLfloat y,GLfloat z,GLfloat w)3910 cc_glglue_glProgramLocalParameter4f(const cc_glglue * glue,
3911                                     GLenum target,
3912                                     GLuint index,
3913                                     GLfloat x,
3914                                     GLfloat y,
3915                                     GLfloat z,
3916                                     GLfloat w)
3917 {
3918   glue->glProgramLocalParameter4fARB(target, index, x, y, z, w);
3919 }
3920 
3921 void
cc_glglue_glProgramLocalParameter4fv(const cc_glglue * glue,GLenum target,GLuint index,const GLfloat * params)3922 cc_glglue_glProgramLocalParameter4fv(const cc_glglue * glue,
3923                                      GLenum target,
3924                                      GLuint index,
3925                                      const GLfloat *params)
3926 {
3927   glue->glProgramLocalParameter4fvARB(target, index, params);
3928 }
3929 
3930 void
cc_glglue_glGetProgramEnvParameterdv(const cc_glglue * glue,GLenum target,GLuint index,GLdouble * params)3931 cc_glglue_glGetProgramEnvParameterdv(const cc_glglue * glue,
3932                                      GLenum target,
3933                                      GLuint index,
3934                                      GLdouble *params)
3935 {
3936   glue->glGetProgramEnvParameterdvARB(target, index, params);
3937 }
3938 
3939 void
cc_glglue_glGetProgramEnvParameterfv(const cc_glglue * glue,GLenum target,GLuint index,GLfloat * params)3940 cc_glglue_glGetProgramEnvParameterfv(const cc_glglue * glue,
3941                                      GLenum target,
3942                                      GLuint index,
3943                                      GLfloat *params)
3944 {
3945   glue->glGetProgramEnvParameterfvARB(target, index, params);
3946 }
3947 
3948 void
cc_glglue_glGetProgramLocalParameterdv(const cc_glglue * glue,GLenum target,GLuint index,GLdouble * params)3949 cc_glglue_glGetProgramLocalParameterdv(const cc_glglue * glue,
3950                                        GLenum target,
3951                                        GLuint index,
3952                                        GLdouble *params)
3953 {
3954   glue->glGetProgramLocalParameterdvARB(target, index, params);
3955 }
3956 
3957 void
cc_glglue_glGetProgramLocalParameterfv(const cc_glglue * glue,GLenum target,GLuint index,GLfloat * params)3958 cc_glglue_glGetProgramLocalParameterfv(const cc_glglue * glue,
3959                                        GLenum target,
3960                                        GLuint index,
3961                                        GLfloat *params)
3962 {
3963   glue->glGetProgramLocalParameterfvARB(target, index, params);
3964 }
3965 
3966 void
cc_glglue_glGetProgramiv(const cc_glglue * glue,GLenum target,GLenum pname,GLint * params)3967 cc_glglue_glGetProgramiv(const cc_glglue * glue,
3968                          GLenum target,
3969                          GLenum pname,
3970                          GLint *params)
3971 {
3972   glue->glGetProgramivARB(target, pname, params);
3973 }
3974 
3975 void
cc_glglue_glGetProgramString(const cc_glglue * glue,GLenum target,GLenum pname,GLvoid * string)3976 cc_glglue_glGetProgramString(const cc_glglue * glue,
3977                              GLenum target,
3978                              GLenum pname,
3979                              GLvoid *string)
3980 {
3981   glue->glGetProgramStringARB(target, pname, string);
3982 }
3983 
3984 SbBool
cc_glglue_glIsProgram(const cc_glglue * glue,GLuint program)3985 cc_glglue_glIsProgram(const cc_glglue * glue,
3986                       GLuint program)
3987 {
3988   return glue->glIsProgramARB(program);
3989 }
3990 
3991 
3992 /* ARB_vertex_program functions */
3993 SbBool
cc_glglue_has_arb_vertex_program(const cc_glglue * glue)3994 cc_glglue_has_arb_vertex_program(const cc_glglue * glue)
3995 {
3996   if (!glglue_allow_newer_opengl(glue)) return FALSE;
3997   return glue->has_arb_vertex_program;
3998 }
3999 
4000 /* ARB_vertex_shaders functions */
4001 SbBool
cc_glglue_has_arb_vertex_shader(const cc_glglue * glue)4002 cc_glglue_has_arb_vertex_shader(const cc_glglue * glue)
4003 {
4004   if (!glglue_allow_newer_opengl(glue)) return FALSE;
4005   return glue->has_arb_vertex_shader;
4006 }
4007 
4008 void
cc_glglue_glVertexAttrib1s(const cc_glglue * glue,GLuint index,GLshort x)4009 cc_glglue_glVertexAttrib1s(const cc_glglue * glue,
4010                            GLuint index, GLshort x)
4011 {
4012   glue->glVertexAttrib1sARB(index, x);
4013 }
4014 
4015 void
cc_glglue_glVertexAttrib1f(const cc_glglue * glue,GLuint index,GLfloat x)4016 cc_glglue_glVertexAttrib1f(const cc_glglue * glue,
4017                            GLuint index, GLfloat x)
4018 {
4019   glue->glVertexAttrib1fARB(index, x);
4020 }
4021 
4022 void
cc_glglue_glVertexAttrib1d(const cc_glglue * glue,GLuint index,GLdouble x)4023 cc_glglue_glVertexAttrib1d(const cc_glglue * glue,
4024                            GLuint index, GLdouble x)
4025 {
4026   glue->glVertexAttrib1dARB(index, x);
4027 }
4028 
4029 void
cc_glglue_glVertexAttrib2s(const cc_glglue * glue,GLuint index,GLshort x,GLshort y)4030 cc_glglue_glVertexAttrib2s(const cc_glglue * glue,
4031                            GLuint index, GLshort x, GLshort y)
4032 {
4033   glue->glVertexAttrib2sARB(index, x, y);
4034 }
4035 
4036 void
cc_glglue_glVertexAttrib2f(const cc_glglue * glue,GLuint index,GLfloat x,GLfloat y)4037 cc_glglue_glVertexAttrib2f(const cc_glglue * glue,
4038                            GLuint index, GLfloat x, GLfloat y)
4039 {
4040   glue->glVertexAttrib2fARB(index, x, y);
4041 }
4042 
4043 void
cc_glglue_glVertexAttrib2d(const cc_glglue * glue,GLuint index,GLdouble x,GLdouble y)4044 cc_glglue_glVertexAttrib2d(const cc_glglue * glue,
4045                            GLuint index, GLdouble x, GLdouble y)
4046 {
4047   glue->glVertexAttrib2dARB(index, x, y);
4048 }
4049 
4050 void
cc_glglue_glVertexAttrib3s(const cc_glglue * glue,GLuint index,GLshort x,GLshort y,GLshort z)4051 cc_glglue_glVertexAttrib3s(const cc_glglue * glue,
4052                            GLuint index, GLshort x,
4053                            GLshort y, GLshort z)
4054 {
4055   glue->glVertexAttrib3sARB(index, x, y, z);
4056 }
4057 
4058 void
cc_glglue_glVertexAttrib3f(const cc_glglue * glue,GLuint index,GLfloat x,GLfloat y,GLfloat z)4059 cc_glglue_glVertexAttrib3f(const cc_glglue * glue,
4060                            GLuint index, GLfloat x,
4061                            GLfloat y, GLfloat z)
4062 {
4063   glue->glVertexAttrib3fARB(index, x, y, z);
4064 }
4065 
4066 void
cc_glglue_glVertexAttrib3d(const cc_glglue * glue,GLuint index,GLdouble x,GLdouble y,GLdouble z)4067 cc_glglue_glVertexAttrib3d(const cc_glglue * glue,
4068                            GLuint index, GLdouble x,
4069                            GLdouble y, GLdouble z)
4070 {
4071   glue->glVertexAttrib3dARB(index, x, y, z);
4072 }
4073 
4074 void
cc_glglue_glVertexAttrib4s(const cc_glglue * glue,GLuint index,GLshort x,GLshort y,GLshort z,GLshort w)4075 cc_glglue_glVertexAttrib4s(const cc_glglue * glue,
4076                            GLuint index, GLshort x,
4077                            GLshort y, GLshort z, GLshort w)
4078 {
4079   glue->glVertexAttrib4sARB(index, x, y, z, w);
4080 }
4081 
4082 void
cc_glglue_glVertexAttrib4f(const cc_glglue * glue,GLuint index,GLfloat x,GLfloat y,GLfloat z,GLfloat w)4083 cc_glglue_glVertexAttrib4f(const cc_glglue * glue,
4084                            GLuint index, GLfloat x,
4085                            GLfloat y, GLfloat z, GLfloat w)
4086 {
4087   glue->glVertexAttrib4fARB(index, x, y, z, w);
4088 }
4089 
4090 void
cc_glglue_glVertexAttrib4d(const cc_glglue * glue,GLuint index,GLdouble x,GLdouble y,GLdouble z,GLdouble w)4091 cc_glglue_glVertexAttrib4d(const cc_glglue * glue,
4092                            GLuint index, GLdouble x,
4093                            GLdouble y, GLdouble z, GLdouble w)
4094 {
4095   glue->glVertexAttrib4dARB(index, x, y, z, w);
4096 }
4097 
4098 void
cc_glglue_glVertexAttrib4Nub(const cc_glglue * glue,GLuint index,GLubyte x,GLubyte y,GLubyte z,GLubyte w)4099 cc_glglue_glVertexAttrib4Nub(const cc_glglue * glue,
4100                              GLuint index, GLubyte x,
4101                              GLubyte y, GLubyte z, GLubyte w)
4102 {
4103   glue->glVertexAttrib4NubARB(index, x, y, z, w);
4104 }
4105 
4106 void
cc_glglue_glVertexAttrib1sv(const cc_glglue * glue,GLuint index,const GLshort * v)4107 cc_glglue_glVertexAttrib1sv(const cc_glglue * glue,
4108                             GLuint index, const GLshort *v)
4109 {
4110   glue->glVertexAttrib1svARB(index, v);
4111 }
4112 
4113 void
cc_glglue_glVertexAttrib1fv(const cc_glglue * glue,GLuint index,const GLfloat * v)4114 cc_glglue_glVertexAttrib1fv(const cc_glglue * glue,
4115                             GLuint index, const GLfloat *v)
4116 {
4117   glue->glVertexAttrib1fvARB(index, v);
4118 }
4119 
4120 void
cc_glglue_glVertexAttrib1dv(const cc_glglue * glue,GLuint index,const GLdouble * v)4121 cc_glglue_glVertexAttrib1dv(const cc_glglue * glue,
4122                             GLuint index, const GLdouble *v)
4123 {
4124   glue->glVertexAttrib1dvARB(index, v);
4125 }
4126 
4127 void
cc_glglue_glVertexAttrib2sv(const cc_glglue * glue,GLuint index,const GLshort * v)4128 cc_glglue_glVertexAttrib2sv(const cc_glglue * glue,
4129                             GLuint index, const GLshort *v)
4130 {
4131   glue->glVertexAttrib2svARB(index, v);
4132 }
4133 
4134 void
cc_glglue_glVertexAttrib2fv(const cc_glglue * glue,GLuint index,const GLfloat * v)4135 cc_glglue_glVertexAttrib2fv(const cc_glglue * glue,
4136                             GLuint index, const GLfloat *v)
4137 {
4138   glue->glVertexAttrib2fvARB(index, v);
4139 }
4140 
4141 void
cc_glglue_glVertexAttrib2dv(const cc_glglue * glue,GLuint index,const GLdouble * v)4142 cc_glglue_glVertexAttrib2dv(const cc_glglue * glue,
4143                             GLuint index, const GLdouble *v)
4144 {
4145   glue->glVertexAttrib2dvARB(index, v);
4146 }
4147 
4148 void
cc_glglue_glVertexAttrib3sv(const cc_glglue * glue,GLuint index,const GLshort * v)4149 cc_glglue_glVertexAttrib3sv(const cc_glglue * glue,
4150                             GLuint index, const GLshort *v)
4151 {
4152   glue->glVertexAttrib3svARB(index, v);
4153 }
4154 
4155 void
cc_glglue_glVertexAttrib3fv(const cc_glglue * glue,GLuint index,const GLfloat * v)4156 cc_glglue_glVertexAttrib3fv(const cc_glglue * glue,
4157                             GLuint index, const GLfloat *v)
4158 {
4159   glue->glVertexAttrib3fvARB(index, v);
4160 }
4161 
4162 void
cc_glglue_glVertexAttrib3dv(const cc_glglue * glue,GLuint index,const GLdouble * v)4163 cc_glglue_glVertexAttrib3dv(const cc_glglue * glue,
4164                             GLuint index, const GLdouble *v)
4165 {
4166   glue->glVertexAttrib3dvARB(index, v);
4167 }
4168 
4169 void
cc_glglue_glVertexAttrib4bv(const cc_glglue * glue,GLuint index,const GLbyte * v)4170 cc_glglue_glVertexAttrib4bv(const cc_glglue * glue,
4171                             GLuint index, const GLbyte *v)
4172 {
4173   glue->glVertexAttrib4bvARB(index, v);
4174 }
4175 
4176 void
cc_glglue_glVertexAttrib4sv(const cc_glglue * glue,GLuint index,const GLshort * v)4177 cc_glglue_glVertexAttrib4sv(const cc_glglue * glue,
4178                             GLuint index, const GLshort *v)
4179 {
4180   glue->glVertexAttrib4svARB(index, v);
4181 }
4182 
4183 void
cc_glglue_glVertexAttrib4iv(const cc_glglue * glue,GLuint index,const GLint * v)4184 cc_glglue_glVertexAttrib4iv(const cc_glglue * glue,
4185                             GLuint index, const GLint *v)
4186 {
4187   glue->glVertexAttrib4ivARB(index, v);
4188 }
4189 
4190 void
cc_glglue_glVertexAttrib4ubv(const cc_glglue * glue,GLuint index,const GLubyte * v)4191 cc_glglue_glVertexAttrib4ubv(const cc_glglue * glue,
4192                              GLuint index, const GLubyte *v)
4193 {
4194   glue->glVertexAttrib4ubvARB(index, v);
4195 }
4196 
4197 void
cc_glglue_glVertexAttrib4usv(const cc_glglue * glue,GLuint index,const GLushort * v)4198 cc_glglue_glVertexAttrib4usv(const cc_glglue * glue,
4199                              GLuint index, const GLushort *v)
4200 {
4201   glue->glVertexAttrib4usvARB(index, v);
4202 }
4203 
4204 void
cc_glglue_glVertexAttrib4uiv(const cc_glglue * glue,GLuint index,const GLuint * v)4205 cc_glglue_glVertexAttrib4uiv(const cc_glglue * glue,
4206                              GLuint index, const GLuint *v)
4207 {
4208   glue->glVertexAttrib4uivARB(index, v);
4209 }
4210 
4211 void
cc_glglue_glVertexAttrib4fv(const cc_glglue * glue,GLuint index,const GLfloat * v)4212 cc_glglue_glVertexAttrib4fv(const cc_glglue * glue,
4213                             GLuint index, const GLfloat *v)
4214 {
4215   glue->glVertexAttrib4fvARB(index, v);
4216 }
4217 
4218 void
cc_glglue_glVertexAttrib4dv(const cc_glglue * glue,GLuint index,const GLdouble * v)4219 cc_glglue_glVertexAttrib4dv(const cc_glglue * glue,
4220                             GLuint index, const GLdouble *v)
4221 {
4222   glue->glVertexAttrib4dvARB(index, v);
4223 }
4224 
4225 void
cc_glglue_glVertexAttrib4Nbv(const cc_glglue * glue,GLuint index,const GLbyte * v)4226 cc_glglue_glVertexAttrib4Nbv(const cc_glglue * glue,
4227                              GLuint index, const GLbyte *v)
4228 {
4229   glue->glVertexAttrib4NbvARB(index, v);
4230 }
4231 
4232 void
cc_glglue_glVertexAttrib4Nsv(const cc_glglue * glue,GLuint index,const GLshort * v)4233 cc_glglue_glVertexAttrib4Nsv(const cc_glglue * glue,
4234                              GLuint index, const GLshort *v)
4235 {
4236   glue->glVertexAttrib4NsvARB(index, v);
4237 }
4238 
4239 void
cc_glglue_glVertexAttrib4Niv(const cc_glglue * glue,GLuint index,const GLint * v)4240 cc_glglue_glVertexAttrib4Niv(const cc_glglue * glue,
4241                              GLuint index, const GLint *v)
4242 {
4243   glue->glVertexAttrib4NivARB(index, v);
4244 }
4245 
4246 void
cc_glglue_glVertexAttrib4Nubv(const cc_glglue * glue,GLuint index,const GLubyte * v)4247 cc_glglue_glVertexAttrib4Nubv(const cc_glglue * glue,
4248                               GLuint index, const GLubyte *v)
4249 {
4250   glue->glVertexAttrib4NubvARB(index, v);
4251 }
4252 
4253 void
cc_glglue_glVertexAttrib4Nusv(const cc_glglue * glue,GLuint index,const GLushort * v)4254 cc_glglue_glVertexAttrib4Nusv(const cc_glglue * glue,
4255                               GLuint index, const GLushort *v)
4256 {
4257   glue->glVertexAttrib4NusvARB(index, v);
4258 }
4259 
4260 void
cc_glglue_glVertexAttrib4Nuiv(const cc_glglue * glue,GLuint index,const GLuint * v)4261 cc_glglue_glVertexAttrib4Nuiv(const cc_glglue * glue,
4262                               GLuint index, const GLuint *v)
4263 {
4264   glue->glVertexAttrib4NuivARB(index, v);
4265 }
4266 
4267 void
cc_glglue_glVertexAttribPointer(const cc_glglue * glue,GLuint index,GLint size,GLenum type,GLboolean normalized,GLsizei stride,const GLvoid * pointer)4268 cc_glglue_glVertexAttribPointer(const cc_glglue * glue,
4269                                 GLuint index, GLint size,
4270                                 GLenum type, GLboolean normalized,
4271                                 GLsizei stride,
4272                                 const GLvoid *pointer)
4273 {
4274   glue->glVertexAttribPointerARB(index, size, type, normalized, stride, pointer);
4275 }
4276 
4277 void
cc_glglue_glEnableVertexAttribArray(const cc_glglue * glue,GLuint index)4278 cc_glglue_glEnableVertexAttribArray(const cc_glglue * glue,
4279                                     GLuint index)
4280 {
4281   glue->glEnableVertexAttribArrayARB(index);
4282 }
4283 
4284 void
cc_glglue_glDisableVertexAttribArray(const cc_glglue * glue,GLuint index)4285 cc_glglue_glDisableVertexAttribArray(const cc_glglue * glue,
4286                                      GLuint index)
4287 {
4288   glue->glDisableVertexAttribArrayARB(index);
4289 }
4290 
4291 void
cc_glglue_glGetVertexAttribdv(const cc_glglue * glue,GLuint index,GLenum pname,GLdouble * params)4292 cc_glglue_glGetVertexAttribdv(const cc_glglue * glue,
4293                               GLuint index, GLenum pname,
4294                               GLdouble *params)
4295 {
4296   glue->glGetVertexAttribdvARB(index, pname, params);
4297 }
4298 
4299 void
cc_glglue_glGetVertexAttribfv(const cc_glglue * glue,GLuint index,GLenum pname,GLfloat * params)4300 cc_glglue_glGetVertexAttribfv(const cc_glglue * glue,
4301                               GLuint index, GLenum pname,
4302                               GLfloat *params)
4303 {
4304   glue->glGetVertexAttribfvARB(index, pname, params);
4305 }
4306 
4307 void
cc_glglue_glGetVertexAttribiv(const cc_glglue * glue,GLuint index,GLenum pname,GLint * params)4308 cc_glglue_glGetVertexAttribiv(const cc_glglue * glue,
4309                               GLuint index, GLenum pname,
4310                               GLint *params)
4311 {
4312   glue->glGetVertexAttribivARB(index, pname, params);
4313 }
4314 
4315 void
cc_glglue_glGetVertexAttribPointerv(const cc_glglue * glue,GLuint index,GLenum pname,GLvoid ** pointer)4316 cc_glglue_glGetVertexAttribPointerv(const cc_glglue * glue,
4317                                     GLuint index, GLenum pname,
4318                                     GLvoid **pointer)
4319 {
4320   glue->glGetVertexAttribPointervARB(index, pname, pointer);
4321 }
4322 
4323 /* GL_ARB_occlusion_query */
4324 
4325 SbBool
cc_glglue_has_occlusion_query(const cc_glglue * glue)4326 cc_glglue_has_occlusion_query(const cc_glglue * glue)
4327 {
4328   if (!glglue_allow_newer_opengl(glue)) return FALSE;
4329 
4330   /* check only one function for speed. It's set to NULL when
4331      initializing if one of the other functions wasn't found */
4332   return glue->glGenQueries != NULL;
4333 }
4334 
4335 void
cc_glglue_glGenQueries(const cc_glglue * glue,GLsizei n,GLuint * ids)4336 cc_glglue_glGenQueries(const cc_glglue * glue,
4337                        GLsizei n, GLuint * ids)
4338 {
4339   glue->glGenQueries(n, ids);
4340 }
4341 
4342 void
cc_glglue_glDeleteQueries(const cc_glglue * glue,GLsizei n,const GLuint * ids)4343 cc_glglue_glDeleteQueries(const cc_glglue * glue,
4344                           GLsizei n, const GLuint *ids)
4345 {
4346   glue->glDeleteQueries(n, ids);
4347 }
4348 
4349 GLboolean
cc_glglue_glIsQuery(const cc_glglue * glue,GLuint id)4350 cc_glglue_glIsQuery(const cc_glglue * glue,
4351                     GLuint id)
4352 {
4353   return glue->glIsQuery(id);
4354 }
4355 
4356 void
cc_glglue_glBeginQuery(const cc_glglue * glue,GLenum target,GLuint id)4357 cc_glglue_glBeginQuery(const cc_glglue * glue,
4358                        GLenum target, GLuint id)
4359 {
4360   glue->glBeginQuery(target, id);
4361 }
4362 
4363 void
cc_glglue_glEndQuery(const cc_glglue * glue,GLenum target)4364 cc_glglue_glEndQuery(const cc_glglue * glue,
4365                      GLenum target)
4366 {
4367   glue->glEndQuery(target);
4368 }
4369 
4370 void
cc_glglue_glGetQueryiv(const cc_glglue * glue,GLenum target,GLenum pname,GLint * params)4371 cc_glglue_glGetQueryiv(const cc_glglue * glue,
4372                        GLenum target, GLenum pname,
4373                        GLint * params)
4374 {
4375   glue->glGetQueryiv(target, pname, params);
4376 }
4377 
4378 void
cc_glglue_glGetQueryObjectiv(const cc_glglue * glue,GLuint id,GLenum pname,GLint * params)4379 cc_glglue_glGetQueryObjectiv(const cc_glglue * glue,
4380                              GLuint id, GLenum pname,
4381                              GLint * params)
4382 {
4383   glue->glGetQueryObjectiv(id, pname, params);
4384 }
4385 
4386 void
cc_glglue_glGetQueryObjectuiv(const cc_glglue * glue,GLuint id,GLenum pname,GLuint * params)4387 cc_glglue_glGetQueryObjectuiv(const cc_glglue * glue,
4388                               GLuint id, GLenum pname,
4389                               GLuint * params)
4390 {
4391   glue->glGetQueryObjectuiv(id, pname, params);
4392 }
4393 
4394 /* GL_NV_texture_rectangle (identical to GL_EXT_texture_rectangle) */
4395 SbBool
cc_glglue_has_nv_texture_rectangle(const cc_glglue * glue)4396 cc_glglue_has_nv_texture_rectangle(const cc_glglue * glue)
4397 {
4398   if (!glglue_allow_newer_opengl(glue)) return FALSE;
4399   return glue->has_ext_texture_rectangle;
4400 }
4401 
4402 /* GL_EXT_texture_rectangle */
4403 SbBool
cc_glglue_has_ext_texture_rectangle(const cc_glglue * glue)4404 cc_glglue_has_ext_texture_rectangle(const cc_glglue * glue)
4405 {
4406   if (!glglue_allow_newer_opengl(glue)) return FALSE;
4407   return glue->has_ext_texture_rectangle;
4408 }
4409 
4410 /* GL_NV_texture_shader */
4411 SbBool
cc_glglue_has_nv_texture_shader(const cc_glglue * glue)4412 cc_glglue_has_nv_texture_shader(const cc_glglue * glue)
4413 {
4414   if (!glglue_allow_newer_opengl(glue)) return FALSE;
4415   return glue->has_nv_texture_shader;
4416 }
4417 
4418 /* GL_ARB_shadow */
4419 SbBool
cc_glglue_has_arb_shadow(const cc_glglue * glue)4420 cc_glglue_has_arb_shadow(const cc_glglue * glue)
4421 {
4422   if (!glglue_allow_newer_opengl(glue)) return FALSE;
4423   return glue->has_shadow;
4424 }
4425 
4426 /* GL_ARB_depth_texture */
4427 SbBool
cc_glglue_has_arb_depth_texture(const cc_glglue * glue)4428 cc_glglue_has_arb_depth_texture(const cc_glglue * glue)
4429 {
4430   if (!glglue_allow_newer_opengl(glue)) return FALSE;
4431   return glue->has_depth_texture;
4432 }
4433 
4434 /* GL_EXT_texture_env_combine || GL_ARB_texture_env_combine || OGL 1.4 */
4435 SbBool
cc_glglue_has_texture_env_combine(const cc_glglue * glue)4436 cc_glglue_has_texture_env_combine(const cc_glglue * glue)
4437 {
4438   if (!glglue_allow_newer_opengl(glue)) return FALSE;
4439   return glue->has_texture_env_combine;
4440 }
4441 
4442 /*!
4443   Returns current X11 display the OpenGL context is in. If none, or if
4444   the glXGetCurrentDisplay() method is not available (it was
4445   introduced with GLX 1.3), returns \c NULL.
4446 */
4447 void *
cc_glglue_glXGetCurrentDisplay(const cc_glglue * w)4448 cc_glglue_glXGetCurrentDisplay(const cc_glglue * w)
4449 {
4450   return w->glx.glXGetCurrentDisplay ? w->glx.glXGetCurrentDisplay() : NULL;
4451 }
4452 
4453 /*** Offscreen buffer handling. *********************************************/
4454 
4455 /*
4456   Below is a stand-alone example that can be compiled and linked with
4457   the Coin library for testing that the context handling interface
4458   works:
4459  */
4460 /*
4461   #include <Inventor/C/glue/gl.h>
4462   #include <Inventor/elements/SoGLCacheContextElement.h>
4463   #include <Inventor/SoDB.h>
4464   #include <cassert>
4465   #include <cstdio>
4466 
4467   int
4468   main(void)
4469   {
4470     SoDB::init();
4471     void * ctx = cc_glglue_context_create_offscreen(128, 128);
4472     assert(ctx);
4473     SbBool ok = cc_glglue_context_make_current(ctx);
4474     assert(ok);
4475 
4476     const GLubyte * str = glGetString(GL_VERSION);
4477     assert(str && "could not call glGetString() -- no current GL context?");
4478     assert(glGetError() == GL_NO_ERROR && "GL error when calling glGetString() -- no current GL context?");
4479 
4480     (void)fprintf(stdout, "glGetString(GL_VERSION)=='%s'\n", str);
4481     (void)fprintf(stdout, "glGetString(GL_VENDOR)=='%s'\n", glGetString(GL_VENDOR));
4482     (void)fprintf(stdout, "glGetString(GL_RENDERER)=='%s'\n", glGetString(GL_RENDERER));
4483 
4484     uint32_t contextid = SoGLCacheContextElement::getUniqueCacheContext();
4485     const cc_glglue * glue = cc_glglue_instance(contextid);
4486     (void)fprintf(stdout, "glGenTextures=='%p'\n",
4487                   cc_glglue_getprocaddress(glue, "glGenTextures"));
4488 
4489     (void)fprintf(stdout, "glGenTexturesEXT=='%p'\n",
4490                   cc_glglue_getprocaddress(glue, "glGenTexturesEXT"));
4491 
4492     cc_glglue_context_reinstate_previous(ctx);
4493     cc_glglue_context_destruct(ctx);
4494     return 0;
4495   }
4496 */
4497 
4498 /* offscreen rendering callback handling */
4499 
4500 void
cc_glglue_context_set_offscreen_cb_functions(cc_glglue_offscreen_cb_functions * p)4501 cc_glglue_context_set_offscreen_cb_functions(cc_glglue_offscreen_cb_functions* p)
4502 {
4503   offscreen_cb = p;
4504 }
4505 
4506 void *
cc_glglue_context_create_offscreen(unsigned int width,unsigned int height)4507 cc_glglue_context_create_offscreen(unsigned int width, unsigned int height)
4508 {
4509   if (offscreen_cb && offscreen_cb->create_offscreen) {
4510     return (*offscreen_cb->create_offscreen)(width, height);
4511   } else {
4512 #ifdef HAVE_NOGL
4513   assert(FALSE && "unimplemented");
4514   return NULL;
4515 #elif defined(HAVE_GLX)
4516   return glxglue_context_create_offscreen(width, height);
4517 #elif defined(HAVE_WGL)
4518   return wglglue_context_create_offscreen(width, height);
4519 #else
4520 #if defined(HAVE_AGL)
4521   check_force_agl();
4522   if (COIN_USE_AGL > 0) return aglglue_context_create_offscreen(width, height); else
4523 #endif
4524 #if defined(HAVE_CGL)
4525   return cglglue_context_create_offscreen(width, height);
4526 #else
4527 #endif
4528 #endif
4529   }
4530   assert(FALSE && "unimplemented");
4531   return NULL;
4532 }
4533 
4534 SbBool
cc_glglue_context_make_current(void * ctx)4535 cc_glglue_context_make_current(void * ctx)
4536 {
4537   if (offscreen_cb && offscreen_cb->make_current) {
4538     return (*offscreen_cb->make_current)(ctx);
4539   } else {
4540 #ifdef HAVE_NOGL
4541   assert(FALSE && "unimplemented");
4542   return FALSE;
4543 #elif defined(HAVE_GLX)
4544   return glxglue_context_make_current(ctx);
4545 #elif defined(HAVE_WGL)
4546   return wglglue_context_make_current(ctx);
4547 #else
4548 #if defined(HAVE_AGL)
4549   if (COIN_USE_AGL > 0) return aglglue_context_make_current(ctx); else
4550 #endif
4551 #if defined(HAVE_CGL)
4552   return cglglue_context_make_current(ctx);
4553 #else
4554   ;
4555 #endif
4556 #endif
4557   }
4558   assert(FALSE && "unimplemented");
4559   return FALSE;
4560 }
4561 
4562 void
cc_glglue_context_reinstate_previous(void * ctx)4563 cc_glglue_context_reinstate_previous(void * ctx)
4564 {
4565   /* FIXME: I believe two cc_glglue_context_make_current() invocations
4566      before invoking this function would make this function behave
4567      erroneously, as previous contexts are not stacked (at least not
4568      in the GLX implementation, which I have checked), but only the
4569      last context is kept track of.
4570 
4571      Probably needs to be fixed. Or at least we should detect and
4572      assert, if this is not allowed for some reason.
4573 
4574      20040621 mortene. */
4575 
4576   if (offscreen_cb && offscreen_cb->reinstate_previous) {
4577     (*offscreen_cb->reinstate_previous)(ctx);
4578   } else {
4579 #ifdef HAVE_NOGL
4580   assert(FALSE && "unimplemented");
4581 #elif defined(HAVE_GLX)
4582   glxglue_context_reinstate_previous(ctx);
4583 #elif defined(HAVE_WGL)
4584   wglglue_context_reinstate_previous(ctx);
4585 #else
4586 #if defined(HAVE_AGL)
4587   if (COIN_USE_AGL > 0) aglglue_context_reinstate_previous(ctx); else
4588 #endif
4589 #if defined(HAVE_CGL)
4590   cglglue_context_reinstate_previous(ctx);
4591 #else
4592   ;
4593 #endif
4594 #endif
4595   }
4596 }
4597 
4598 void
cc_glglue_context_destruct(void * ctx)4599 cc_glglue_context_destruct(void * ctx)
4600 {
4601   if (offscreen_cb && offscreen_cb->destruct) {
4602     (*offscreen_cb->destruct)(ctx);
4603   } else {
4604 #ifdef HAVE_NOGL
4605   assert(FALSE && "unimplemented");
4606 #elif defined(HAVE_GLX)
4607   glxglue_context_destruct(ctx);
4608 #elif defined(HAVE_WGL)
4609   wglglue_context_destruct(ctx);
4610 #else
4611 #if defined(HAVE_AGL)
4612   if (COIN_USE_AGL > 0) aglglue_context_destruct(ctx); else
4613 #endif
4614 #if defined(HAVE_CGL)
4615   cglglue_context_destruct(ctx);
4616 #else
4617   ;
4618 #endif
4619 #endif
4620   }
4621 }
4622 
4623 /*!
4624   Returns the \e theoretical maximum dimensions for an offscreen
4625   buffer.
4626 
4627   Note that we're still not guaranteed that allocation of this size
4628   will succeed, as that is also subject to e.g. memory constraints,
4629   which is something that will dynamically change during the running
4630   time of an application.
4631 
4632   So the values returned from this function should be taken as hints,
4633   and client code of cc_glglue_context_create_offscreen() and
4634   cc_glglue_context_make_current() should re-request offscreen
4635   contexts with lower dimensions if any of those fails.
4636 */
4637 void
cc_glglue_context_max_dimensions(unsigned int * width,unsigned int * height)4638 cc_glglue_context_max_dimensions(unsigned int * width, unsigned int * height)
4639 {
4640   void * ctx;
4641   SbBool ok;
4642   const char * vendor;
4643   GLint size[2];
4644   static SbBool cached = FALSE;
4645   static unsigned int dim[2] = { 0, 0 };
4646 
4647     *width = dim[0];
4648     *height = dim[1];
4649 
4650   if (cached) { /* value cached */ return; }
4651 
4652   if (coin_glglue_debug()) {
4653     cc_debugerror_postinfo("cc_glglue_context_max_dimensions",
4654                            "query by making a dummy offscreen context");
4655   }
4656 
4657   cached = TRUE; /* Flip flag on first run. Note: it doesn't matter
4658                     that the detection below might fail -- as we
4659                     should report <0,0> on consecutive runs. */
4660 
4661   /* The below calls *can* fail, due to e.g. lack of resources, or no
4662      usable visual for the GL context. We try to handle gracefully.
4663      This is straightforward to do here, simply returning dimensions
4664      of <0,0>, but note that we also need to handle the exception in
4665      the callers. */
4666 
4667   ctx = cc_glglue_context_create_offscreen(32, 32);
4668   if (!ctx) { return; }
4669   ok = cc_glglue_context_make_current(ctx);
4670   if (!ok) { cc_glglue_context_destruct(ctx); return; }
4671 
4672   glGetIntegerv(GL_MAX_VIEWPORT_DIMS, size);
4673   if (coin_glglue_debug()) {
4674     cc_debugerror_postinfo("cc_glglue_context_max_dimensions",
4675                            "GL_MAX_VIEWPORT_DIMS==<%d, %d>",
4676                            size[0], size[1]);
4677   }
4678 
4679   vendor = (const char *)glGetString(GL_VENDOR);
4680   if (strcmp(vendor, "NVIDIA Corporation") == 0) {
4681 
4682     /* NVIDIA seems to have a bug where max render size is limited
4683        by desktop resolution (at least for their Linux X11
4684        drivers), not the texture maxsize returned by OpenGL. So we
4685        use a workaround by limiting max size to the lowend
4686        resolution for desktop monitors.
4687 
4688        According to pederb, there are versions of the NVidia
4689        drivers where the offscreen buffer also has to have
4690        dimensions that are 2^x, so we limit further down to these
4691        dimension settings to be sure.
4692     */
4693 
4694     /* FIXME: should make a stand-alone test-case (not dependent
4695        on Coin, only GL, GLX & X11) that demonstrates this problem
4696        for a) submitting to <linux-bugs@nvidia.com>, and b) to
4697        test which versions of the NVidia drivers are affected --
4698        as it is now, we shrink the max to <512,512> on all
4699        versions (even if we're under MSWin). 20030812 mortene.
4700     */
4701 
4702     /* UPDATE 20050712 mortene: this clamping should no longer be
4703        necessary, as we now re-request a new, lower size for offscreen
4704        buffers from SoOffscreenRenderer (i.e. the values returned from
4705        this function is considered just a hint).
4706 
4707        I'm keeping the code comments and the commented out code below,
4708        in case there have been issues with NVidia drivers hidden by
4709        this clamping, which will surface now...
4710 
4711        Eventually, this special case check should be removed, though.
4712     */
4713 /*     size[0] = cc_min(size[0], 512); */
4714 /*     size[1] = cc_min(size[1], 512); */
4715   }
4716 
4717   *width = (unsigned int) size[0];
4718   *height = (unsigned int) size[1];
4719 
4720   /* Check additional limits from pbuffer capabilities: */
4721   {
4722     /* will be filled with max-width, max-height and max-pixels: */
4723     unsigned int pbufmax[3];
4724     /* query functions below should return TRUE if implemented, and
4725        the current offscreen buffer is a pbuffer: */
4726     SbBool ok = FALSE;
4727 #if defined(HAVE_WGL)
4728     ok = wglglue_context_pbuffer_max(ctx, pbufmax);
4729 #elif defined(HAVE_GLX)
4730     ok = glxglue_context_pbuffer_max(ctx, pbufmax);
4731 #elif defined(HAVE_AGL) || defined(HAVE_CGL)
4732     /* FIXME: implement check on max pbuffer width, height and number
4733        of pixels for AGL/CGL, if any such limits are imposed there.
4734        20040713 mortene. */
4735 #endif
4736     if (ok) {
4737       int modulo = 0;
4738 
4739       if (coin_glglue_debug()) {
4740         cc_debugerror_postinfo("cc_glglue_context_max_dimensions",
4741                                "pbuffer max dimensions, "
4742                                "width==%u, height==%u, pixels==%u",
4743                                pbufmax[0], pbufmax[1], pbufmax[2]);
4744       }
4745 
4746       *width = cc_min(*width, pbufmax[0]);
4747       *height = cc_min(*height, pbufmax[1]);
4748 
4749       while ((*width * *height) > pbufmax[2]) {
4750         if (modulo % 2) { *width /= 2; }
4751         else { *height /= 2; }
4752         modulo++;
4753       }
4754     }
4755   }
4756 
4757   cc_glglue_context_reinstate_previous(ctx);
4758   cc_glglue_context_destruct(ctx);
4759 
4760   /* Force an additional limit to the maximum tilesize to 4096x4096
4761      pixels.
4762 
4763      This is done to work around a problem with some OpenGL drivers: a
4764      huge value is returned for the maximum offscreen OpenGL canvas,
4765      where the driver obviously does not take into account the amount
4766      of memory needed to actually allocate such a large buffer.
4767 
4768      This problem has at least been observed with the MS Windows XP
4769      software OpenGL renderer, which reports a maximum viewport size
4770      of 16k x 16k pixels.
4771 
4772      FIXME: we really shouldn't f*ck around with this here, but rather
4773      make the client code of this more robust. That means
4774      SoOffscreenRenderer should try with successively smaller buffers
4775      of allocation if the maximum (or wanted) buffer size fails. For
4776      further discussion, see the FIXME at the top of the
4777      SoOffscreenRendererP::renderFromBase() method. 20040714 mortene.
4778 
4779      UPDATE 20050712 mortene: this has now been fixed in
4780      SoOffscreenRenderer -- it will try with sucessively smaller
4781      sizes. I'm still keeping the max clamping below, though, to avoid
4782      unexpected problems with external applications, as we're
4783      currently between patch-level releases with Coin-2, and I have
4784      only limited time right now for testing that removing this would
4785      not cause badness.
4786   */
4787   *width = cc_min(*width, 4096);
4788   *height = cc_min(*height, 4096);
4789 
4790   if (coin_glglue_debug()) {
4791     cc_debugerror_postinfo("cc_glglue_context_max_dimensions",
4792                            "clamped max dimensions==<%u, %u>",
4793                            *width, *height);
4794   }
4795 
4796   /* cache values for next invocation */
4797 
4798   dim[0] = *width;
4799   dim[1] = *height;
4800 }
4801 
4802 SbBool
cc_glglue_context_can_render_to_texture(void * COIN_UNUSED_ARG (ctx))4803 cc_glglue_context_can_render_to_texture(void * COIN_UNUSED_ARG(ctx))
4804 {
4805   /* No render-to-texture support in external offscreen rendering. */
4806   if (offscreen_cb) return FALSE;
4807 
4808 #if defined(HAVE_GLX) || defined(HAVE_NOGL)
4809   return FALSE;
4810 #elif defined(HAVE_WGL)
4811   return wglglue_context_can_render_to_texture(ctx);
4812 #else
4813 #if defined(HAVE_AGL)
4814   if (COIN_USE_AGL > 0) return aglglue_context_can_render_to_texture(ctx); else
4815 #endif
4816 #if defined(HAVE_CGL)
4817   return cglglue_context_can_render_to_texture(ctx);
4818 #else
4819   ;
4820 #endif
4821 #endif
4822 }
4823 
4824 
4825 void
cc_glglue_context_bind_pbuffer(void * COIN_UNUSED_ARG (ctx))4826 cc_glglue_context_bind_pbuffer(void * COIN_UNUSED_ARG(ctx))
4827 {
4828   /* No render-to-texture support in external offscreen rendering. */
4829   if (offscreen_cb) return;
4830 
4831 #if defined(HAVE_GLX) || defined(HAVE_NOGL)
4832   /* FIXME: Implement for GLX.  The problem is that in GLX, there is
4833      no way to bind a PBuffer as a texture (i.e. there is no
4834      equivalent to the aglTexImagePBuffer() and wglBindTexImageARB()
4835      calls).  kyrah 20031123. */
4836   assert(FALSE && "unimplemented");
4837 #elif defined(HAVE_WGL)
4838   wglglue_context_bind_pbuffer(ctx);
4839 #else
4840 #if defined(HAVE_AGL)
4841   if (COIN_USE_AGL > 0) aglglue_context_bind_pbuffer(ctx); else
4842 #endif
4843 #if defined(HAVE_CGL)
4844   cglglue_context_bind_pbuffer(ctx);
4845 #else
4846   ;
4847 #endif
4848 #endif
4849 }
4850 
4851 void
cc_glglue_context_release_pbuffer(void * COIN_UNUSED_ARG (ctx))4852 cc_glglue_context_release_pbuffer(void * COIN_UNUSED_ARG(ctx))
4853 {
4854   /* No render-to-texture support in external offscreen rendering. */
4855   if (offscreen_cb) return;
4856 
4857 #if defined(HAVE_GLX) || defined(HAVE_NOGL)
4858   /* FIXME: Implement for GLX. kyrah 20031123. */
4859   assert(FALSE && "unimplemented");
4860 #elif defined(HAVE_WGL)
4861   wglglue_context_release_pbuffer(ctx);
4862 #else
4863 #if defined(HAVE_AGL)
4864   if (COIN_USE_AGL > 0) aglglue_context_release_pbuffer(ctx); else
4865 #endif
4866 #if defined(HAVE_CGL)
4867   cglglue_context_release_pbuffer(ctx);
4868 #else
4869   ;
4870 #endif
4871 #endif
4872 }
4873 
4874 SbBool
cc_glglue_context_pbuffer_is_bound(void * COIN_UNUSED_ARG (ctx))4875 cc_glglue_context_pbuffer_is_bound(void * COIN_UNUSED_ARG(ctx))
4876 {
4877   /* No render-to-texture support in external offscreen rendering. */
4878   if (offscreen_cb) return FALSE;
4879 
4880 #if defined(HAVE_GLX) || defined(HAVE_NOGL)
4881   /* FIXME: Implement for GLX. kyrah 20031123. */
4882   assert(FALSE && "unimplemented");
4883   return FALSE;
4884 #elif defined(HAVE_WGL)
4885   return wglglue_context_pbuffer_is_bound(ctx);
4886 #else
4887 #if defined(HAVE_AGL)
4888   if (COIN_USE_AGL > 0) return aglglue_context_pbuffer_is_bound(ctx); else
4889 #endif
4890 #if defined(HAVE_CGL)
4891   return cglglue_context_pbuffer_is_bound(ctx);
4892 #else
4893   return false;
4894 #endif
4895 #endif
4896 }
4897 
4898 /* This abomination is needed to support SoOffscreenRenderer::getDC(). */
4899 const void *
cc_glglue_win32_HDC(void * COIN_UNUSED_ARG (ctx))4900 cc_glglue_win32_HDC(void * COIN_UNUSED_ARG(ctx))
4901 {
4902 #if defined(HAVE_WGL)
4903   return wglglue_context_win32_HDC(ctx);
4904 #else /* not WGL */
4905   return NULL;
4906 #endif /* not WGL */
4907 }
cc_glglue_win32_updateHDCBitmap(void * COIN_UNUSED_ARG (ctx))4908 void cc_glglue_win32_updateHDCBitmap(void * COIN_UNUSED_ARG(ctx))
4909 {
4910 #if defined(HAVE_WGL)
4911   wglglue_copy_to_bitmap_win32_HDC(ctx);
4912 #endif /* not WGL */
4913 }
4914 
4915 /*** </Offscreen buffer handling.> ******************************************/
4916 
4917 /*** <PROXY texture handling> ***********************************************/
4918 
4919 static int
compute_log(int value)4920 compute_log(int value)
4921 {
4922   int i = 0;
4923   while (value > 1) { value>>=1; i++; }
4924   return i;
4925 }
4926 
4927 /*  proxy mipmap creation */
4928 static SbBool
proxy_mipmap_2d(int width,int height,GLenum internalFormat,GLenum format,GLenum type,SbBool mipmap)4929 proxy_mipmap_2d(int width, int height,
4930                 GLenum internalFormat,
4931                 GLenum format,
4932                 GLenum type,
4933                 SbBool mipmap)
4934 {
4935   GLint w;
4936   int level;
4937   int levels = compute_log(cc_max(width, height));
4938 
4939   glTexImage2D(GL_PROXY_TEXTURE_2D, 0, internalFormat, width, height, 0,
4940                format, type, NULL);
4941   glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0,
4942                            GL_TEXTURE_WIDTH, &w);
4943 
4944   if (w == 0) return FALSE;
4945   if (!mipmap) return TRUE;
4946 
4947   for (level = 1; level <= levels; level++) {
4948     if (width > 1) width >>= 1;
4949     if (height > 1) height >>= 1;
4950     glTexImage2D(GL_PROXY_TEXTURE_2D, level, internalFormat, width,
4951                  height, 0, format, type,
4952                  NULL);
4953     glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0,
4954                              GL_TEXTURE_WIDTH, &w);
4955     if (w == 0) return FALSE;
4956   }
4957   return TRUE;
4958 }
4959 
4960 /* proxy mipmap creation. 3D version. */
4961 static SbBool
proxy_mipmap_3d(const cc_glglue * glw,int width,int height,int depth,GLenum internalFormat,GLenum format,GLenum type,SbBool mipmap)4962 proxy_mipmap_3d(const cc_glglue * glw, int width, int height, int depth,
4963                 GLenum internalFormat,
4964                 GLenum format,
4965                 GLenum type,
4966                 SbBool mipmap)
4967 {
4968   GLint w;
4969   int level;
4970   int levels = compute_log(cc_max(cc_max(width, height), depth));
4971 
4972   cc_glglue_glTexImage3D(glw, GL_PROXY_TEXTURE_3D, 0, internalFormat,
4973                          width, height, depth, 0, format, type,
4974                          NULL);
4975   glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0,
4976                            GL_TEXTURE_WIDTH, &w);
4977   if (w == 0) return FALSE;
4978   if (!mipmap) return TRUE;
4979 
4980   for (level = 1; level <= levels; level++) {
4981     if (width > 1) width >>= 1;
4982     if (height > 1) height >>= 1;
4983     if (depth > 1) depth >>= 1;
4984     cc_glglue_glTexImage3D(glw, GL_PROXY_TEXTURE_3D, level, internalFormat,
4985                            width, height, depth, 0, format, type,
4986                            NULL);
4987     glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0,
4988                              GL_TEXTURE_WIDTH, &w);
4989     if (w == 0) return FALSE;
4990   }
4991   return TRUE;
4992 }
4993 
4994 SbBool
cc_glglue_is_texture_size_legal(const cc_glglue * glw,int xsize,int ysize,int zsize,int bytespertexel,SbBool mipmap)4995 cc_glglue_is_texture_size_legal(const cc_glglue * glw,
4996                                 int xsize, int ysize, int zsize,
4997                                 int bytespertexel, SbBool mipmap)
4998 {
4999   GLenum internalformat;
5000   GLenum format;
5001   GLenum type = GL_UNSIGNED_BYTE;
5002 
5003   switch (bytespertexel) {
5004   default:
5005   case 1:
5006     format = internalformat = GL_LUMINANCE;
5007     break;
5008   case 2:
5009     format = internalformat = GL_LUMINANCE_ALPHA;
5010     break;
5011   case 3:
5012     format = internalformat = GL_RGB8;
5013     break;
5014   case 4:
5015     format = internalformat = GL_RGBA8;
5016     break;
5017   }
5018 
5019   return coin_glglue_is_texture_size_legal(glw, xsize, ysize, zsize,
5020                                            internalformat, format, type, mipmap);
5021 }
5022 
5023 /*!
5024   Note that the \e internalformat parameter corresponds to the \e
5025   internalFormat parameter to glTexImage2D; either the number of
5026   components per texel or a constant specifying the internal texture format.
5027  */
5028 SbBool
coin_glglue_is_texture_size_legal(const cc_glglue * glw,int xsize,int ysize,int zsize,GLenum internalformat,GLenum format,GLenum type,SbBool mipmap)5029 coin_glglue_is_texture_size_legal(const cc_glglue * glw,
5030                                   int xsize, int ysize, int zsize,
5031                                   GLenum internalformat,
5032                                   GLenum format,
5033                                   GLenum type,
5034                                   SbBool mipmap)
5035  {
5036   if (zsize == 0) { /* 2D textures */
5037     if (COIN_MAXIMUM_TEXTURE2_SIZE > 0) {
5038       if (xsize > COIN_MAXIMUM_TEXTURE2_SIZE) return FALSE;
5039       if (ysize > COIN_MAXIMUM_TEXTURE2_SIZE) return FALSE;
5040       return TRUE;
5041     }
5042     if (cc_glglue_has_2d_proxy_textures(glw)) {
5043       return proxy_mipmap_2d(xsize, ysize, internalformat, format, type, mipmap);
5044     }
5045     else {
5046       if (xsize > glw->max_texture_size) return FALSE;
5047       if (ysize > glw->max_texture_size) return FALSE;
5048       return TRUE;
5049     }
5050   }
5051   else { /*  3D textures */
5052     if (cc_glglue_has_3d_textures(glw)) {
5053       if (COIN_MAXIMUM_TEXTURE3_SIZE > 0) {
5054         if (xsize > COIN_MAXIMUM_TEXTURE3_SIZE) return FALSE;
5055         if (ysize > COIN_MAXIMUM_TEXTURE3_SIZE) return FALSE;
5056         if (zsize > COIN_MAXIMUM_TEXTURE3_SIZE) return FALSE;
5057         return TRUE;
5058       }
5059       return proxy_mipmap_3d(glw, xsize, ysize, zsize, internalformat, format, type, mipmap);
5060     }
5061     else {
5062 #if COIN_DEBUG
5063       static SbBool first = TRUE;
5064       if (first) {
5065         cc_debugerror_post("glglue_is_texture_size_legal",
5066                            "3D not supported with this OpenGL driver");
5067         first = FALSE;
5068       }
5069 #endif /*  COIN_DEBUG */
5070       return FALSE;
5071     }
5072   }
5073 }
5074 
5075 /*
5076   Convert from num components to internal texture format for use
5077   in glTexImage*D's internalFormat parameter.
5078 */
coin_glglue_get_internal_texture_format(const cc_glglue * glw,int numcomponents,SbBool compress)5079 GLint coin_glglue_get_internal_texture_format(const cc_glglue * glw,
5080                                               int numcomponents,
5081                                               SbBool compress)
5082 {
5083   GLenum format;
5084   if (compress) {
5085     switch (numcomponents) {
5086     case 1:
5087       format = GL_COMPRESSED_LUMINANCE_ARB;
5088       break;
5089     case 2:
5090       format = GL_COMPRESSED_LUMINANCE_ALPHA_ARB;
5091       break;
5092     case 3:
5093       format = GL_COMPRESSED_RGB_ARB;
5094       break;
5095     case 4:
5096     default:
5097       format = GL_COMPRESSED_RGBA_ARB;
5098       break;
5099     }
5100   }
5101   else {
5102     SbBool usenewenums = glglue_allow_newer_opengl(glw) && cc_glglue_glversion_matches_at_least(glw,1,1,0);
5103     switch (numcomponents) {
5104     case 1:
5105       format = usenewenums ? GL_LUMINANCE8 : GL_LUMINANCE;
5106       break;
5107     case 2:
5108       format = usenewenums ? GL_LUMINANCE8_ALPHA8 : GL_LUMINANCE_ALPHA;
5109       break;
5110     case 3:
5111       format = usenewenums ? GL_RGB8 : GL_RGB;
5112       break;
5113     case 4:
5114     default:
5115       format = usenewenums ? GL_RGBA8 : GL_RGBA;
5116       break;
5117     }
5118   }
5119   return format;
5120 }
5121 
5122 /*
5123   Convert from num components to client texture format for use
5124   in glTexImage*D's format parameter.
5125 */
coin_glglue_get_texture_format(const cc_glglue * COIN_UNUSED_ARG (glw),int numcomponents)5126 GLenum coin_glglue_get_texture_format(const cc_glglue * COIN_UNUSED_ARG(glw), int numcomponents)
5127 {
5128   GLenum format;
5129   switch (numcomponents) {
5130   case 1:
5131     format = GL_LUMINANCE;
5132     break;
5133   case 2:
5134     format = GL_LUMINANCE_ALPHA;
5135     break;
5136   case 3:
5137     format = GL_RGB;
5138     break;
5139   case 4:
5140   default:
5141     format = GL_RGBA;
5142     break;
5143   }
5144   return format;
5145 }
5146 
5147 /*** </PROXY texture handling> ***********************************************/
5148 
5149 /*** <Anisotropic filtering> *************************************************/
5150 
cc_glglue_get_max_anisotropy(const cc_glglue * glue)5151 float cc_glglue_get_max_anisotropy(const cc_glglue * glue)
5152 {
5153   return glue->max_anisotropy;
5154 }
5155 
5156 SbBool
cc_glglue_can_do_anisotropic_filtering(const cc_glglue * glue)5157 cc_glglue_can_do_anisotropic_filtering(const cc_glglue * glue)
5158 {
5159   if (!glglue_allow_newer_opengl(glue)) return FALSE;
5160   return glue->can_do_anisotropic_filtering;
5161 }
5162 
5163 /*** </Anisotropic filtering> *************************************************/
5164 
5165 /* Convert an OpenGL enum error code to a textual representation. */
5166 const char *
coin_glerror_string(GLenum errorcode)5167 coin_glerror_string(GLenum errorcode)
5168 {
5169   static const char INVALID_VALUE[] = "GL_INVALID_VALUE";
5170   static const char INVALID_ENUM[] = "GL_INVALID_ENUM";
5171   static const char INVALID_OPERATION[] = "GL_INVALID_OPERATION";
5172   static const char STACK_OVERFLOW[] = "GL_STACK_OVERFLOW";
5173   static const char STACK_UNDERFLOW[] = "GL_STACK_UNDERFLOW";
5174   static const char OUT_OF_MEMORY[] = "GL_OUT_OF_MEMORY";
5175   static const char unknown[] = "Unknown OpenGL error";
5176 
5177   switch (errorcode) {
5178   case GL_INVALID_VALUE:
5179     return INVALID_VALUE;
5180   case GL_INVALID_ENUM:
5181     return INVALID_ENUM;
5182   case GL_INVALID_OPERATION:
5183     return INVALID_OPERATION;
5184   case GL_STACK_OVERFLOW:
5185     return STACK_OVERFLOW;
5186   case GL_STACK_UNDERFLOW:
5187     return STACK_UNDERFLOW;
5188   case GL_OUT_OF_MEMORY:
5189     return OUT_OF_MEMORY;
5190   default:
5191     return unknown;
5192   }
5193   return NULL; /* avoid compiler warning */
5194 }
5195 
5196 /* Simple utility function for dumping the current set of error codes
5197    returned from glGetError(). Returns number of errors reported by
5198    OpenGL. */
5199 
5200 unsigned int
coin_catch_gl_errors(cc_string * str)5201 coin_catch_gl_errors(cc_string * str)
5202 {
5203   unsigned int errs = 0;
5204   GLenum glerr = glGetError();
5205   while (glerr != GL_NO_ERROR) {
5206     if (errs < 10) {
5207       if (errs > 0) {
5208         cc_string_append_char(str, ' ');
5209       }
5210       cc_string_append_text(str, coin_glerror_string(glerr));
5211     }
5212     /* ignore > 10, so we don't run into a situation were we end up
5213        practically locking up the app due to vast amounts of errors */
5214     else if (errs == 10) {
5215       cc_string_append_text(str, "... and more");
5216     }
5217 
5218     errs++;
5219     glerr = glGetError();
5220   }
5221   return errs;
5222 }
5223 
5224 /* ********************************************************************** */
5225 
5226 void *
coin_gl_current_context(void)5227 coin_gl_current_context(void)
5228 {
5229   void * ctx = NULL;
5230 
5231 #ifdef HAVE_GLX
5232   ctx = glXGetCurrentContext();
5233 #endif /* HAVE_GLX */
5234 
5235 #ifdef HAVE_WGL
5236   ctx = wglGetCurrentContext();
5237 #endif /* HAVE_WGL */
5238 
5239 #if defined(HAVE_AGL) || defined(HAVE_CGL)
5240   /* Note: We cannot use aglGetCurrentContext() here, since that only
5241      returns a value != NULL if the context has been set using
5242      aglSetCurrentContext(). */
5243   ctx = CGLGetCurrentContext();
5244 #endif
5245 
5246   return ctx;
5247 }
5248 
5249 /* ********************************************************************** */
5250 
5251 SbBool
coin_glglue_vbo_in_displaylist_supported(const cc_glglue * glw)5252 coin_glglue_vbo_in_displaylist_supported(const cc_glglue * glw)
5253 {
5254   return glw->vbo_in_displaylist_ok;
5255 }
5256 
5257 /* ********************************************************************** */
5258 
5259 SbBool
coin_glglue_non_power_of_two_textures(const cc_glglue * glue)5260 coin_glglue_non_power_of_two_textures(const cc_glglue * glue)
5261 {
5262   if (!glglue_allow_newer_opengl(glue)) return FALSE;
5263 
5264   // ATi and Intel both seem to have problems with this feature,
5265   // especially on old drivers. Disable for everything except nVidia
5266   // until we can build a better driver database
5267   if (!glue->vendor_is_nvidia) return FALSE;
5268   return glue->non_power_of_two_textures;
5269 }
5270 
5271 /* ********************************************************************** */
5272 
5273 uint32_t
coin_glglue_get_contextid(const cc_glglue * glue)5274 coin_glglue_get_contextid(const cc_glglue * glue)
5275 {
5276   return glue->contextid;
5277 }
5278 
5279 /* ********************************************************************** */
5280 
cleanup_instance_created_list(void)5281 static void cleanup_instance_created_list(void)
5282 {
5283   cc_list_destruct(gl_instance_created_cblist);
5284   gl_instance_created_cblist = NULL;
5285 }
5286 
5287 void
coin_glglue_add_instance_created_callback(coin_glglue_instance_created_cb * cb,void * closure)5288 coin_glglue_add_instance_created_callback(coin_glglue_instance_created_cb * cb,
5289                                           void * closure)
5290 {
5291   if (gl_instance_created_cblist == NULL) {
5292     gl_instance_created_cblist = cc_list_construct();
5293     coin_atexit((coin_atexit_f *)cleanup_instance_created_list, CC_ATEXIT_NORMAL);
5294   }
5295   cc_list_append(gl_instance_created_cblist, (void*)cb);
5296   cc_list_append(gl_instance_created_cblist, (void*)closure);
5297 }
5298 
5299 /* ********************************************************************** */
5300 
5301 void
cc_glglue_glIsRenderbuffer(const cc_glglue * glue,GLuint renderbuffer)5302 cc_glglue_glIsRenderbuffer(const cc_glglue * glue, GLuint renderbuffer)
5303 {
5304   assert(glue->has_fbo);
5305   glue->glIsRenderbuffer(renderbuffer);
5306 }
5307 
5308 void
cc_glglue_glBindRenderbuffer(const cc_glglue * glue,GLenum target,GLuint renderbuffer)5309 cc_glglue_glBindRenderbuffer(const cc_glglue * glue, GLenum target, GLuint renderbuffer)
5310 {
5311   assert(glue->has_fbo);
5312   glue->glBindRenderbuffer(target, renderbuffer);
5313 }
5314 
5315 void
cc_glglue_glDeleteRenderbuffers(const cc_glglue * glue,GLsizei n,const GLuint * renderbuffers)5316 cc_glglue_glDeleteRenderbuffers(const cc_glglue * glue, GLsizei n, const GLuint *renderbuffers)
5317 {
5318   assert(glue->has_fbo);
5319   glue->glDeleteRenderbuffers(n, renderbuffers);
5320 }
5321 
5322 void
cc_glglue_glGenRenderbuffers(const cc_glglue * glue,GLsizei n,GLuint * renderbuffers)5323 cc_glglue_glGenRenderbuffers(const cc_glglue * glue, GLsizei n, GLuint *renderbuffers)
5324 {
5325   assert(glue->has_fbo);
5326   glue->glGenRenderbuffers(n, renderbuffers);
5327 }
5328 
5329 void
cc_glglue_glRenderbufferStorage(const cc_glglue * glue,GLenum target,GLenum internalformat,GLsizei width,GLsizei height)5330 cc_glglue_glRenderbufferStorage(const cc_glglue * glue, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
5331 {
5332   assert(glue->has_fbo);
5333   glue->glRenderbufferStorage(target, internalformat, width, height);
5334 }
5335 
5336 void
cc_glglue_glGetRenderbufferParameteriv(const cc_glglue * glue,GLenum target,GLenum pname,GLint * params)5337 cc_glglue_glGetRenderbufferParameteriv(const cc_glglue * glue, GLenum target, GLenum pname, GLint * params)
5338 {
5339   assert(glue->has_fbo);
5340   glue->glGetRenderbufferParameteriv(target, pname, params);
5341 }
5342 
5343 GLboolean
cc_glglue_glIsFramebuffer(const cc_glglue * glue,GLuint framebuffer)5344 cc_glglue_glIsFramebuffer(const cc_glglue * glue, GLuint framebuffer)
5345 {
5346   assert(glue->has_fbo);
5347   return glue->glIsFramebuffer(framebuffer);
5348 }
5349 
5350 void
cc_glglue_glBindFramebuffer(const cc_glglue * glue,GLenum target,GLuint framebuffer)5351 cc_glglue_glBindFramebuffer(const cc_glglue * glue, GLenum target, GLuint framebuffer)
5352 {
5353   assert(glue->has_fbo);
5354   glue->glBindFramebuffer(target, framebuffer);
5355 }
5356 
5357 void
cc_glglue_glDeleteFramebuffers(const cc_glglue * glue,GLsizei n,const GLuint * framebuffers)5358 cc_glglue_glDeleteFramebuffers(const cc_glglue * glue, GLsizei n, const GLuint * framebuffers)
5359 {
5360   assert(glue->has_fbo);
5361   glue->glDeleteFramebuffers(n, framebuffers);
5362 }
5363 
5364 void
cc_glglue_glGenFramebuffers(const cc_glglue * glue,GLsizei n,GLuint * framebuffers)5365 cc_glglue_glGenFramebuffers(const cc_glglue * glue, GLsizei n, GLuint * framebuffers)
5366 {
5367   assert(glue->has_fbo);
5368   glue->glGenFramebuffers(n, framebuffers);
5369 }
5370 
5371 GLenum
cc_glglue_glCheckFramebufferStatus(const cc_glglue * glue,GLenum target)5372 cc_glglue_glCheckFramebufferStatus(const cc_glglue * glue, GLenum target)
5373 {
5374   assert(glue->has_fbo);
5375   return glue->glCheckFramebufferStatus(target);
5376 }
5377 
5378 void
cc_glglue_glFramebufferTexture1D(const cc_glglue * glue,GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level)5379 cc_glglue_glFramebufferTexture1D(const cc_glglue * glue, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
5380 {
5381   assert(glue->has_fbo);
5382   glue->glFramebufferTexture1D(target, attachment, textarget, texture, level);
5383 }
5384 
5385 void
cc_glglue_glFramebufferTexture2D(const cc_glglue * glue,GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level)5386 cc_glglue_glFramebufferTexture2D(const cc_glglue * glue, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
5387 {
5388   assert(glue->has_fbo);
5389   glue->glFramebufferTexture2D(target, attachment, textarget, texture, level);
5390 }
5391 
5392 void
cc_glglue_glFramebufferTexture3D(const cc_glglue * glue,GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level,GLint zoffset)5393 cc_glglue_glFramebufferTexture3D(const cc_glglue * glue, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
5394 {
5395   assert(glue->has_fbo);
5396   glue->glFramebufferTexture3D(target, attachment, textarget, texture, level,zoffset);
5397 }
5398 
5399 void
cc_glglue_glFramebufferRenderbuffer(const cc_glglue * glue,GLenum target,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer)5400 cc_glglue_glFramebufferRenderbuffer(const cc_glglue * glue, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
5401 {
5402   assert(glue->has_fbo);
5403   glue->glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
5404 }
5405 
5406 void
cc_glglue_glGetFramebufferAttachmentParameteriv(const cc_glglue * glue,GLenum target,GLenum attachment,GLenum pname,GLint * params)5407 cc_glglue_glGetFramebufferAttachmentParameteriv(const cc_glglue * glue, GLenum target, GLenum attachment, GLenum pname, GLint * params)
5408 {
5409   assert(glue->has_fbo);
5410   glue->glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);
5411 }
5412 
5413 SbBool
coin_glglue_has_generate_mipmap(const cc_glglue * glue)5414 coin_glglue_has_generate_mipmap(const cc_glglue * glue)
5415 {
5416   if (!glglue_allow_newer_opengl(glue)) return FALSE;
5417   // ATi's handling of this function is very buggy. It's possible to
5418   // work around these quirks, but we just disable it for now since we
5419   // have other ways to generate mipmaps. Only disable on Windows. The
5420   // OS X and Linux drivers are probably ok.
5421   if ((coin_runtime_os() == COIN_MSWINDOWS) && glue->vendor_is_ati) {
5422     return FALSE;
5423   }
5424   return (glue->glGenerateMipmap != NULL);
5425 }
5426 
5427 void
cc_glglue_glGenerateMipmap(const cc_glglue * glue,GLenum target)5428 cc_glglue_glGenerateMipmap(const cc_glglue * glue, GLenum target)
5429 {
5430   glue->glGenerateMipmap(target);
5431 }
5432 
5433 SbBool
cc_glglue_has_framebuffer_objects(const cc_glglue * glue)5434 cc_glglue_has_framebuffer_objects(const cc_glglue * glue)
5435 {
5436   if (!glglue_allow_newer_opengl(glue)) return FALSE;
5437   return glue->has_fbo;
5438 }
5439 
5440 /* ********************************************************************** */
5441 
5442 #ifdef __cplusplus
5443 } /* extern "C" */
5444 #endif /* __cplusplus */
5445