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