1/*
2 * Mesa 3-D graphics library
3 * Version:  7.1
4 *
5 * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26/*
27 * This is the GLX API dispatcher.  Calls to the glX* functions are
28 * either routed to the real GLX encoders or to Mesa's pseudo-GLX functions.
29 * See the glxapi.h file for more details.
30 */
31
32
33#include <assert.h>
34#include <stdlib.h>
35#include <stdio.h>
36#include <string.h>
37#include "main/glheader.h"
38#include "main/compiler.h"
39#include "glapi/glapi.h"
40#include "glxapi.h"
41
42
43extern struct _glxapi_table *_real_GetGLXDispatchTable(void);
44extern struct _glxapi_table *_mesa_GetGLXDispatchTable(void);
45
46
47struct display_dispatch {
48   Display *Dpy;
49   struct _glxapi_table *Table;
50   struct display_dispatch *Next;
51};
52
53
54/**
55 * When GLX_INDIRECT_RENDERING is defined, some symbols are missing in
56 * libglapi.a.  We need to define them here.
57 */
58#ifdef GLX_INDIRECT_RENDERING
59
60#include "glapi/glapitable.h"
61
62#define KEYWORD1 PUBLIC
63
64#if defined(USE_MGL_NAMESPACE)
65#define NAME(func)  mgl##func
66#else
67#define NAME(func)  gl##func
68#endif
69
70#define DISPATCH(FUNC, ARGS, MESSAGE)		\
71   GET_DISPATCH()->FUNC ARGS
72
73#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) 	\
74   return GET_DISPATCH()->FUNC ARGS
75
76/* skip normal ones */
77#define _GLAPI_SKIP_NORMAL_ENTRY_POINTS
78#include "glapi/glapitemp.h"
79
80#endif /* GLX_INDIRECT_RENDERING */
81
82
83static struct display_dispatch *DispatchList = NULL;
84
85
86/* Display -> Dispatch caching */
87static Display *prevDisplay = NULL;
88static struct _glxapi_table *prevTable = NULL;
89
90
91static struct _glxapi_table *
92get_dispatch(Display *dpy)
93{
94   if (!dpy)
95      return NULL;
96
97   /* search list of display/dispatch pairs for this display */
98   {
99      const struct display_dispatch *d = DispatchList;
100      while (d) {
101         if (d->Dpy == dpy) {
102            prevDisplay = dpy;
103            prevTable = d->Table;
104            return d->Table;  /* done! */
105         }
106         d = d->Next;
107      }
108   }
109
110   /* A new display, determine if we should use real GLX
111    * or Mesa's pseudo-GLX.
112    */
113   {
114      struct _glxapi_table *t = _mesa_GetGLXDispatchTable();
115
116      if (t) {
117         struct display_dispatch *d;
118         d = (struct display_dispatch *) malloc(sizeof(struct display_dispatch));
119         if (d) {
120            d->Dpy = dpy;
121            d->Table = t;
122            /* insert at head of list */
123            d->Next = DispatchList;
124            DispatchList = d;
125            /* update cache */
126            prevDisplay = dpy;
127            prevTable = t;
128            return t;
129         }
130      }
131   }
132
133   /* If we get here that means we can't use real GLX on this display
134    * and the Mesa pseudo-GLX software renderer wasn't compiled in.
135    * Or, we ran out of memory!
136    */
137   return NULL;
138}
139
140
141/* Don't use the GET_DISPATCH defined in glthread.h */
142#undef GET_DISPATCH
143
144#define GET_DISPATCH(DPY, TABLE)	\
145   if (DPY == prevDisplay) {		\
146      TABLE = prevTable;		\
147   }					\
148   else if (!DPY) {			\
149      TABLE = NULL;			\
150   }					\
151   else {				\
152      TABLE = get_dispatch(DPY);	\
153   }
154
155
156
157
158/**
159 * GLX API current context.
160 */
161#if defined(GLX_USE_TLS)
162PUBLIC __thread void * CurrentContext
163    __attribute__((tls_model("initial-exec")));
164#elif defined(THREADS)
165static _glthread_TSD ContextTSD;         /**< Per-thread context pointer */
166#else
167static GLXContext CurrentContext = 0;
168#endif
169
170
171static void
172SetCurrentContext(GLXContext c)
173{
174#if defined(GLX_USE_TLS)
175   CurrentContext = c;
176#elif defined(THREADS)
177   _glthread_SetTSD(&ContextTSD, c);
178#else
179   CurrentContext = c;
180#endif
181}
182
183
184/*
185 * GLX API entrypoints
186 */
187
188/*** GLX_VERSION_1_0 ***/
189
190XVisualInfo PUBLIC *
191glXChooseVisual(Display *dpy, int screen, int *list)
192{
193   struct _glxapi_table *t;
194   GET_DISPATCH(dpy, t);
195   if (!t)
196      return NULL;
197   return (t->ChooseVisual)(dpy, screen, list);
198}
199
200
201void PUBLIC
202glXCopyContext(Display *dpy, GLXContext src, GLXContext dst, unsigned long mask)
203{
204   struct _glxapi_table *t;
205   GET_DISPATCH(dpy, t);
206   if (!t)
207      return;
208   (t->CopyContext)(dpy, src, dst, mask);
209}
210
211
212GLXContext PUBLIC
213glXCreateContext(Display *dpy, XVisualInfo *visinfo, GLXContext shareList, Bool direct)
214{
215   struct _glxapi_table *t;
216   GET_DISPATCH(dpy, t);
217   if (!t)
218      return 0;
219   return (t->CreateContext)(dpy, visinfo, shareList, direct);
220}
221
222
223GLXPixmap PUBLIC
224glXCreateGLXPixmap(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap)
225{
226   struct _glxapi_table *t;
227   GET_DISPATCH(dpy, t);
228   if (!t)
229      return 0;
230   return (t->CreateGLXPixmap)(dpy, visinfo, pixmap);
231}
232
233
234void PUBLIC
235glXDestroyContext(Display *dpy, GLXContext ctx)
236{
237   struct _glxapi_table *t;
238   GET_DISPATCH(dpy, t);
239   if (!t)
240      return;
241   if (glXGetCurrentContext() == ctx)
242      SetCurrentContext(NULL);
243   (t->DestroyContext)(dpy, ctx);
244}
245
246
247void PUBLIC
248glXDestroyGLXPixmap(Display *dpy, GLXPixmap pixmap)
249{
250   struct _glxapi_table *t;
251   GET_DISPATCH(dpy, t);
252   if (!t)
253      return;
254   (t->DestroyGLXPixmap)(dpy, pixmap);
255}
256
257
258int PUBLIC
259glXGetConfig(Display *dpy, XVisualInfo *visinfo, int attrib, int *value)
260{
261   struct _glxapi_table *t;
262   GET_DISPATCH(dpy, t);
263   if (!t)
264      return GLX_NO_EXTENSION;
265   return (t->GetConfig)(dpy, visinfo, attrib, value);
266}
267
268
269GLXContext PUBLIC
270glXGetCurrentContext(void)
271{
272#if defined(GLX_USE_TLS)
273   return CurrentContext;
274#elif defined(THREADS)
275   return (GLXContext) _glthread_GetTSD(&ContextTSD);
276#else
277   return CurrentContext;
278#endif
279}
280
281
282GLXDrawable PUBLIC
283glXGetCurrentDrawable(void)
284{
285   __GLXcontext *gc = (__GLXcontext *) glXGetCurrentContext();
286   return gc ? gc->currentDrawable : 0;
287}
288
289
290Bool PUBLIC
291glXIsDirect(Display *dpy, GLXContext ctx)
292{
293   struct _glxapi_table *t;
294   GET_DISPATCH(dpy, t);
295   if (!t)
296      return False;
297   return (t->IsDirect)(dpy, ctx);
298}
299
300
301Bool PUBLIC
302glXMakeCurrent(Display *dpy, GLXDrawable drawable, GLXContext ctx)
303{
304   Bool b;
305   struct _glxapi_table *t;
306   GET_DISPATCH(dpy, t);
307   if (!t) {
308      return False;
309   }
310   b = (*t->MakeCurrent)(dpy, drawable, ctx);
311   if (b) {
312      SetCurrentContext(ctx);
313   }
314   return b;
315}
316
317
318Bool PUBLIC
319glXQueryExtension(Display *dpy, int *errorb, int *event)
320{
321   struct _glxapi_table *t;
322   GET_DISPATCH(dpy, t);
323   if (!t)
324      return False;
325   return (t->QueryExtension)(dpy, errorb, event);
326}
327
328
329Bool PUBLIC
330glXQueryVersion(Display *dpy, int *maj, int *min)
331{
332   struct _glxapi_table *t;
333   GET_DISPATCH(dpy, t);
334   if (!t)
335      return False;
336   return (t->QueryVersion)(dpy, maj, min);
337}
338
339
340void PUBLIC
341glXSwapBuffers(Display *dpy, GLXDrawable drawable)
342{
343   struct _glxapi_table *t;
344   GET_DISPATCH(dpy, t);
345   if (!t)
346      return;
347   (t->SwapBuffers)(dpy, drawable);
348}
349
350
351void PUBLIC
352glXUseXFont(Font font, int first, int count, int listBase)
353{
354   struct _glxapi_table *t;
355   Display *dpy = glXGetCurrentDisplay();
356   GET_DISPATCH(dpy, t);
357   if (!t)
358      return;
359   (t->UseXFont)(font, first, count, listBase);
360}
361
362
363void PUBLIC
364glXWaitGL(void)
365{
366   struct _glxapi_table *t;
367   Display *dpy = glXGetCurrentDisplay();
368   GET_DISPATCH(dpy, t);
369   if (!t)
370      return;
371   (t->WaitGL)();
372}
373
374
375void PUBLIC
376glXWaitX(void)
377{
378   struct _glxapi_table *t;
379   Display *dpy = glXGetCurrentDisplay();
380   GET_DISPATCH(dpy, t);
381   if (!t)
382      return;
383   (t->WaitX)();
384}
385
386
387
388/*** GLX_VERSION_1_1 ***/
389
390const char PUBLIC *
391glXGetClientString(Display *dpy, int name)
392{
393   struct _glxapi_table *t;
394   GET_DISPATCH(dpy, t);
395   if (!t)
396      return NULL;
397   return (t->GetClientString)(dpy, name);
398}
399
400
401const char PUBLIC *
402glXQueryExtensionsString(Display *dpy, int screen)
403{
404   struct _glxapi_table *t;
405   GET_DISPATCH(dpy, t);
406   if (!t)
407      return NULL;
408   return (t->QueryExtensionsString)(dpy, screen);
409}
410
411
412const char PUBLIC *
413glXQueryServerString(Display *dpy, int screen, int name)
414{
415   struct _glxapi_table *t;
416   GET_DISPATCH(dpy, t);
417   if (!t)
418      return NULL;
419   return (t->QueryServerString)(dpy, screen, name);
420}
421
422
423/*** GLX_VERSION_1_2 ***/
424
425Display PUBLIC *
426glXGetCurrentDisplay(void)
427{
428   /* Same code as in libGL's glxext.c */
429   __GLXcontext *gc = (__GLXcontext *) glXGetCurrentContext();
430   if (NULL == gc) return NULL;
431   return gc->currentDpy;
432}
433
434
435
436/*** GLX_VERSION_1_3 ***/
437
438GLXFBConfig PUBLIC *
439glXChooseFBConfig(Display *dpy, int screen, const int *attribList, int *nitems)
440{
441   struct _glxapi_table *t;
442   GET_DISPATCH(dpy, t);
443   if (!t)
444      return 0;
445   return (t->ChooseFBConfig)(dpy, screen, attribList, nitems);
446}
447
448
449GLXContext PUBLIC
450glXCreateNewContext(Display *dpy, GLXFBConfig config, int renderType, GLXContext shareList, Bool direct)
451{
452   struct _glxapi_table *t;
453   GET_DISPATCH(dpy, t);
454   if (!t)
455      return 0;
456   return (t->CreateNewContext)(dpy, config, renderType, shareList, direct);
457}
458
459
460GLXPbuffer PUBLIC
461glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attribList)
462{
463   struct _glxapi_table *t;
464   GET_DISPATCH(dpy, t);
465   if (!t)
466      return 0;
467   return (t->CreatePbuffer)(dpy, config, attribList);
468}
469
470
471GLXPixmap PUBLIC
472glXCreatePixmap(Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attribList)
473{
474   struct _glxapi_table *t;
475   GET_DISPATCH(dpy, t);
476   if (!t)
477      return 0;
478   return (t->CreatePixmap)(dpy, config, pixmap, attribList);
479}
480
481
482GLXWindow PUBLIC
483glXCreateWindow(Display *dpy, GLXFBConfig config, Window win, const int *attribList)
484{
485   struct _glxapi_table *t;
486   GET_DISPATCH(dpy, t);
487   if (!t)
488      return 0;
489   return (t->CreateWindow)(dpy, config, win, attribList);
490}
491
492
493void PUBLIC
494glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf)
495{
496   struct _glxapi_table *t;
497   GET_DISPATCH(dpy, t);
498   if (!t)
499      return;
500   (t->DestroyPbuffer)(dpy, pbuf);
501}
502
503
504void PUBLIC
505glXDestroyPixmap(Display *dpy, GLXPixmap pixmap)
506{
507   struct _glxapi_table *t;
508   GET_DISPATCH(dpy, t);
509   if (!t)
510      return;
511   (t->DestroyPixmap)(dpy, pixmap);
512}
513
514
515void PUBLIC
516glXDestroyWindow(Display *dpy, GLXWindow window)
517{
518   struct _glxapi_table *t;
519   GET_DISPATCH(dpy, t);
520   if (!t)
521      return;
522   (t->DestroyWindow)(dpy, window);
523}
524
525
526GLXDrawable PUBLIC
527glXGetCurrentReadDrawable(void)
528{
529   __GLXcontext *gc = (__GLXcontext *) glXGetCurrentContext();
530   return gc ? gc->currentReadable : 0;
531}
532
533
534int PUBLIC
535glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config, int attribute, int *value)
536{
537   struct _glxapi_table *t;
538   GET_DISPATCH(dpy, t);
539   if (!t)
540      return GLX_NO_EXTENSION;
541   return (t->GetFBConfigAttrib)(dpy, config, attribute, value);
542}
543
544
545GLXFBConfig PUBLIC *
546glXGetFBConfigs(Display *dpy, int screen, int *nelements)
547{
548   struct _glxapi_table *t;
549   GET_DISPATCH(dpy, t);
550   if (!t)
551      return 0;
552   return (t->GetFBConfigs)(dpy, screen, nelements);
553}
554
555void PUBLIC
556glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, unsigned long *mask)
557{
558   struct _glxapi_table *t;
559   GET_DISPATCH(dpy, t);
560   if (!t)
561      return;
562   (t->GetSelectedEvent)(dpy, drawable, mask);
563}
564
565
566XVisualInfo PUBLIC *
567glXGetVisualFromFBConfig(Display *dpy, GLXFBConfig config)
568{
569   struct _glxapi_table *t;
570   GET_DISPATCH(dpy, t);
571   if (!t)
572      return NULL;
573   return (t->GetVisualFromFBConfig)(dpy, config);
574}
575
576
577Bool PUBLIC
578glXMakeContextCurrent(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
579{
580   Bool b;
581   struct _glxapi_table *t;
582   GET_DISPATCH(dpy, t);
583   if (!t)
584      return False;
585   b = (t->MakeContextCurrent)(dpy, draw, read, ctx);
586   if (b) {
587      SetCurrentContext(ctx);
588   }
589   return b;
590}
591
592
593int PUBLIC
594glXQueryContext(Display *dpy, GLXContext ctx, int attribute, int *value)
595{
596   struct _glxapi_table *t;
597   GET_DISPATCH(dpy, t);
598   assert(t);
599   if (!t)
600      return 0; /* XXX correct? */
601   return (t->QueryContext)(dpy, ctx, attribute, value);
602}
603
604
605void PUBLIC
606glXQueryDrawable(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value)
607{
608   struct _glxapi_table *t;
609   GET_DISPATCH(dpy, t);
610   if (!t)
611      return;
612   (t->QueryDrawable)(dpy, draw, attribute, value);
613}
614
615
616void PUBLIC
617glXSelectEvent(Display *dpy, GLXDrawable drawable, unsigned long mask)
618{
619   struct _glxapi_table *t;
620   GET_DISPATCH(dpy, t);
621   if (!t)
622      return;
623   (t->SelectEvent)(dpy, drawable, mask);
624}
625
626
627
628/*** GLX_SGI_swap_control ***/
629
630int PUBLIC
631glXSwapIntervalSGI(int interval)
632{
633   struct _glxapi_table *t;
634   Display *dpy = glXGetCurrentDisplay();
635   GET_DISPATCH(dpy, t);
636   if (!t)
637      return 0;
638   return (t->SwapIntervalSGI)(interval);
639}
640
641
642
643/*** GLX_SGI_video_sync ***/
644
645int PUBLIC
646glXGetVideoSyncSGI(unsigned int *count)
647{
648   struct _glxapi_table *t;
649   Display *dpy = glXGetCurrentDisplay();
650   GET_DISPATCH(dpy, t);
651   if (!t || !glXGetCurrentContext())
652      return GLX_BAD_CONTEXT;
653   return (t->GetVideoSyncSGI)(count);
654}
655
656int PUBLIC
657glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
658{
659   struct _glxapi_table *t;
660   Display *dpy = glXGetCurrentDisplay();
661   GET_DISPATCH(dpy, t);
662   if (!t || !glXGetCurrentContext())
663      return GLX_BAD_CONTEXT;
664   return (t->WaitVideoSyncSGI)(divisor, remainder, count);
665}
666
667
668
669/*** GLX_SGI_make_current_read ***/
670
671Bool PUBLIC
672glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
673{
674   struct _glxapi_table *t;
675   GET_DISPATCH(dpy, t);
676   if (!t)
677      return False;
678   return (t->MakeCurrentReadSGI)(dpy, draw, read, ctx);
679}
680
681GLXDrawable PUBLIC
682glXGetCurrentReadDrawableSGI(void)
683{
684   return glXGetCurrentReadDrawable();
685}
686
687
688#if defined(_VL_H)
689
690GLXVideoSourceSGIX PUBLIC
691glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode)
692{
693   struct _glxapi_table *t;
694   GET_DISPATCH(dpy, t);
695   if (!t)
696      return 0;
697   return (t->CreateGLXVideoSourceSGIX)(dpy, screen, server, path, nodeClass, drainNode);
698}
699
700void PUBLIC
701glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src)
702{
703   struct _glxapi_table *t;
704   GET_DISPATCH(dpy, t);
705   if (!t)
706      return 0;
707   return (t->DestroyGLXVideoSourceSGIX)(dpy, src);
708}
709
710#endif
711
712
713/*** GLX_EXT_import_context ***/
714
715void PUBLIC
716glXFreeContextEXT(Display *dpy, GLXContext context)
717{
718   struct _glxapi_table *t;
719   GET_DISPATCH(dpy, t);
720   if (!t)
721      return;
722   (t->FreeContextEXT)(dpy, context);
723}
724
725GLXContextID PUBLIC
726glXGetContextIDEXT(const GLXContext context)
727{
728   return ((__GLXcontext *) context)->xid;
729}
730
731Display PUBLIC *
732glXGetCurrentDisplayEXT(void)
733{
734   return glXGetCurrentDisplay();
735}
736
737GLXContext PUBLIC
738glXImportContextEXT(Display *dpy, GLXContextID contextID)
739{
740   struct _glxapi_table *t;
741   GET_DISPATCH(dpy, t);
742   if (!t)
743      return 0;
744   return (t->ImportContextEXT)(dpy, contextID);
745}
746
747int PUBLIC
748glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute,int *value)
749{
750   struct _glxapi_table *t;
751   GET_DISPATCH(dpy, t);
752   if (!t)
753      return 0;  /* XXX ok? */
754   return (t->QueryContextInfoEXT)(dpy, context, attribute, value);
755}
756
757
758
759/*** GLX_SGIX_fbconfig ***/
760
761int PUBLIC
762glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value)
763{
764   struct _glxapi_table *t;
765   GET_DISPATCH(dpy, t);
766   if (!t)
767      return 0;
768   return (t->GetFBConfigAttribSGIX)(dpy, config, attribute, value);
769}
770
771GLXFBConfigSGIX PUBLIC *
772glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements)
773{
774   struct _glxapi_table *t;
775   GET_DISPATCH(dpy, t);
776   if (!t)
777      return 0;
778   return (t->ChooseFBConfigSGIX)(dpy, screen, attrib_list, nelements);
779}
780
781GLXPixmap PUBLIC
782glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap)
783{
784   struct _glxapi_table *t;
785   GET_DISPATCH(dpy, t);
786   if (!t)
787      return 0;
788   return (t->CreateGLXPixmapWithConfigSGIX)(dpy, config, pixmap);
789}
790
791GLXContext PUBLIC
792glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct)
793{
794   struct _glxapi_table *t;
795   GET_DISPATCH(dpy, t);
796   if (!t)
797      return 0;
798   return (t->CreateContextWithConfigSGIX)(dpy, config, render_type, share_list, direct);
799}
800
801XVisualInfo PUBLIC *
802glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config)
803{
804   struct _glxapi_table *t;
805   GET_DISPATCH(dpy, t);
806   if (!t)
807      return 0;
808   return (t->GetVisualFromFBConfigSGIX)(dpy, config);
809}
810
811GLXFBConfigSGIX PUBLIC
812glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis)
813{
814   struct _glxapi_table *t;
815   GET_DISPATCH(dpy, t);
816   if (!t)
817      return 0;
818   return (t->GetFBConfigFromVisualSGIX)(dpy, vis);
819}
820
821
822
823/*** GLX_SGIX_pbuffer ***/
824
825GLXPbufferSGIX PUBLIC
826glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list)
827{
828   struct _glxapi_table *t;
829   GET_DISPATCH(dpy, t);
830   if (!t)
831      return 0;
832   return (t->CreateGLXPbufferSGIX)(dpy, config, width, height, attrib_list);
833}
834
835void PUBLIC
836glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf)
837{
838   struct _glxapi_table *t;
839   GET_DISPATCH(dpy, t);
840   if (!t)
841      return;
842   (t->DestroyGLXPbufferSGIX)(dpy, pbuf);
843}
844
845int PUBLIC
846glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value)
847{
848   struct _glxapi_table *t;
849   GET_DISPATCH(dpy, t);
850   if (!t)
851      return 0;
852   return (t->QueryGLXPbufferSGIX)(dpy, pbuf, attribute, value);
853}
854
855void PUBLIC
856glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask)
857{
858   struct _glxapi_table *t;
859   GET_DISPATCH(dpy, t);
860   if (!t)
861      return;
862   (t->SelectEventSGIX)(dpy, drawable, mask);
863}
864
865void PUBLIC
866glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask)
867{
868   struct _glxapi_table *t;
869   GET_DISPATCH(dpy, t);
870   if (!t)
871      return;
872   (t->GetSelectedEventSGIX)(dpy, drawable, mask);
873}
874
875
876
877/*** GLX_SGI_cushion ***/
878
879void PUBLIC
880glXCushionSGI(Display *dpy, Window win, float cushion)
881{
882   struct _glxapi_table *t;
883   GET_DISPATCH(dpy, t);
884   if (!t)
885      return;
886   (t->CushionSGI)(dpy, win, cushion);
887}
888
889
890
891/*** GLX_SGIX_video_resize ***/
892
893int PUBLIC
894glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window)
895{
896   struct _glxapi_table *t;
897   GET_DISPATCH(dpy, t);
898   if (!t)
899      return 0;
900   return (t->BindChannelToWindowSGIX)(dpy, screen, channel, window);
901}
902
903int PUBLIC
904glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, int h)
905{
906   struct _glxapi_table *t;
907   GET_DISPATCH(dpy, t);
908   if (!t)
909      return 0;
910   return (t->ChannelRectSGIX)(dpy, screen, channel, x, y, w, h);
911}
912
913int PUBLIC
914glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, int *w, int *h)
915{
916   struct _glxapi_table *t;
917   GET_DISPATCH(dpy, t);
918   if (!t)
919      return 0;
920   return (t->QueryChannelRectSGIX)(dpy, screen, channel, x, y, w, h);
921}
922
923int PUBLIC
924glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *dy, int *dw, int *dh)
925{
926   struct _glxapi_table *t;
927   GET_DISPATCH(dpy, t);
928   if (!t)
929      return 0;
930   return (t->QueryChannelDeltasSGIX)(dpy, screen, channel, dx, dy, dw, dh);
931}
932
933int PUBLIC
934glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype)
935{
936   struct _glxapi_table *t;
937   GET_DISPATCH(dpy, t);
938   if (!t)
939      return 0;
940   return (t->ChannelRectSyncSGIX)(dpy, screen, channel, synctype);
941}
942
943
944
945#if defined(_DM_BUFFER_H_)
946
947Bool PUBLIC
948glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer)
949{
950   struct _glxapi_table *t;
951   GET_DISPATCH(dpy, t);
952   if (!t)
953      return False;
954   return (t->AssociateDMPbufferSGIX)(dpy, pbuffer, params, dmbuffer);
955}
956
957#endif
958
959
960/*** GLX_SGIX_swap_group ***/
961
962void PUBLIC
963glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member)
964{
965   struct _glxapi_table *t;
966   GET_DISPATCH(dpy, t);
967   if (!t)
968      return;
969   (*t->JoinSwapGroupSGIX)(dpy, drawable, member);
970}
971
972
973/*** GLX_SGIX_swap_barrier ***/
974
975void PUBLIC
976glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier)
977{
978   struct _glxapi_table *t;
979   GET_DISPATCH(dpy, t);
980   if (!t)
981      return;
982   (*t->BindSwapBarrierSGIX)(dpy, drawable, barrier);
983}
984
985Bool PUBLIC
986glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max)
987{
988   struct _glxapi_table *t;
989   GET_DISPATCH(dpy, t);
990   if (!t)
991      return False;
992   return (*t->QueryMaxSwapBarriersSGIX)(dpy, screen, max);
993}
994
995
996
997/*** GLX_SUN_get_transparent_index ***/
998
999Status PUBLIC
1000glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent)
1001{
1002   struct _glxapi_table *t;
1003   GET_DISPATCH(dpy, t);
1004   if (!t)
1005      return False;
1006   return (*t->GetTransparentIndexSUN)(dpy, overlay, underlay, pTransparent);
1007}
1008
1009
1010
1011/*** GLX_MESA_copy_sub_buffer ***/
1012
1013void PUBLIC
1014glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable, int x, int y, int width, int height)
1015{
1016   struct _glxapi_table *t;
1017   GET_DISPATCH(dpy, t);
1018   if (!t)
1019      return;
1020   (t->CopySubBufferMESA)(dpy, drawable, x, y, width, height);
1021}
1022
1023
1024
1025/*** GLX_MESA_release_buffers ***/
1026
1027Bool PUBLIC
1028glXReleaseBuffersMESA(Display *dpy, Window w)
1029{
1030   struct _glxapi_table *t;
1031   GET_DISPATCH(dpy, t);
1032   if (!t)
1033      return False;
1034   return (t->ReleaseBuffersMESA)(dpy, w);
1035}
1036
1037
1038
1039/*** GLX_MESA_pixmap_colormap ***/
1040
1041GLXPixmap PUBLIC
1042glXCreateGLXPixmapMESA(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap, Colormap cmap)
1043{
1044   struct _glxapi_table *t;
1045   GET_DISPATCH(dpy, t);
1046   if (!t)
1047      return 0;
1048   return (t->CreateGLXPixmapMESA)(dpy, visinfo, pixmap, cmap);
1049}
1050
1051
1052
1053/*** GLX_MESA_set_3dfx_mode ***/
1054
1055Bool PUBLIC
1056glXSet3DfxModeMESA(int mode)
1057{
1058   struct _glxapi_table *t;
1059   Display *dpy = glXGetCurrentDisplay();
1060   GET_DISPATCH(dpy, t);
1061   if (!t)
1062      return False;
1063   return (t->Set3DfxModeMESA)(mode);
1064}
1065
1066
1067
1068/*** GLX_NV_vertex_array_range ***/
1069
1070void PUBLIC *
1071glXAllocateMemoryNV( GLsizei size,
1072                     GLfloat readFrequency,
1073                     GLfloat writeFrequency,
1074                     GLfloat priority )
1075{
1076   struct _glxapi_table *t;
1077   Display *dpy = glXGetCurrentDisplay();
1078   GET_DISPATCH(dpy, t);
1079   if (!t)
1080      return NULL;
1081   return (t->AllocateMemoryNV)(size, readFrequency, writeFrequency, priority);
1082}
1083
1084
1085void PUBLIC
1086glXFreeMemoryNV( GLvoid *pointer )
1087{
1088   struct _glxapi_table *t;
1089   Display *dpy = glXGetCurrentDisplay();
1090   GET_DISPATCH(dpy, t);
1091   if (!t)
1092      return;
1093   (t->FreeMemoryNV)(pointer);
1094}
1095
1096
1097
1098
1099/*** GLX_MESA_agp_offset */
1100
1101GLuint PUBLIC
1102glXGetAGPOffsetMESA( const GLvoid *pointer )
1103{
1104   struct _glxapi_table *t;
1105   Display *dpy = glXGetCurrentDisplay();
1106   GET_DISPATCH(dpy, t);
1107   if (!t)
1108      return ~0;
1109   return (t->GetAGPOffsetMESA)(pointer);
1110}
1111
1112
1113/*** GLX_EXT_texture_from_pixmap */
1114
1115void PUBLIC
1116glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer,
1117                   const int *attrib_list)
1118{
1119   struct _glxapi_table *t;
1120   GET_DISPATCH(dpy, t);
1121   if (t)
1122      t->BindTexImageEXT(dpy, drawable, buffer, attrib_list);
1123}
1124
1125void PUBLIC
1126glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer)
1127{
1128   struct _glxapi_table *t;
1129   GET_DISPATCH(dpy, t);
1130   if (t)
1131      t->ReleaseTexImageEXT(dpy, drawable, buffer);
1132}
1133
1134
1135/**********************************************************************/
1136/* GLX API management functions                                       */
1137/**********************************************************************/
1138
1139
1140const char *
1141_glxapi_get_version(void)
1142{
1143   return "1.3";
1144}
1145
1146
1147/*
1148 * Return array of extension strings.
1149 */
1150const char **
1151_glxapi_get_extensions(void)
1152{
1153   static const char *extensions[] = {
1154#ifdef GLX_EXT_import_context
1155      "GLX_EXT_import_context",
1156#endif
1157#ifdef GLX_SGI_video_sync
1158      "GLX_SGI_video_sync",
1159#endif
1160#ifdef GLX_MESA_copy_sub_buffer
1161      "GLX_MESA_copy_sub_buffer",
1162#endif
1163#ifdef GLX_MESA_release_buffers
1164      "GLX_MESA_release_buffers",
1165#endif
1166#ifdef GLX_MESA_pixmap_colormap
1167      "GLX_MESA_pixmap_colormap",
1168#endif
1169#ifdef GLX_MESA_set_3dfx_mode
1170      "GLX_MESA_set_3dfx_mode",
1171#endif
1172#ifdef GLX_SGIX_fbconfig
1173      "GLX_SGIX_fbconfig",
1174#endif
1175#ifdef GLX_SGIX_pbuffer
1176      "GLX_SGIX_pbuffer",
1177#endif
1178#ifdef GLX_EXT_texture_from_pixmap
1179      "GLX_EXT_texture_from_pixmap",
1180#endif
1181#ifdef GLX_INTEL_swap_event
1182      "GLX_INTEL_swap_event",
1183#endif
1184      NULL
1185   };
1186   return extensions;
1187}
1188
1189
1190/*
1191 * Return size of the GLX dispatch table, in entries, not bytes.
1192 */
1193GLuint
1194_glxapi_get_dispatch_table_size(void)
1195{
1196   return sizeof(struct _glxapi_table) / sizeof(void *);
1197}
1198
1199
1200static int
1201generic_no_op_func(void)
1202{
1203   return 0;
1204}
1205
1206
1207/*
1208 * Initialize all functions in given dispatch table to be no-ops
1209 */
1210void
1211_glxapi_set_no_op_table(struct _glxapi_table *t)
1212{
1213   typedef int (*nop_func)(void);
1214   nop_func *dispatch = (nop_func *) t;
1215   GLuint n = _glxapi_get_dispatch_table_size();
1216   GLuint i;
1217   for (i = 0; i < n; i++) {
1218      dispatch[i] = generic_no_op_func;
1219   }
1220}
1221
1222
1223struct name_address_pair {
1224   const char *Name;
1225   __GLXextFuncPtr Address;
1226};
1227
1228static struct name_address_pair GLX_functions[] = {
1229   /*** GLX_VERSION_1_0 ***/
1230   { "glXChooseVisual", (__GLXextFuncPtr) glXChooseVisual },
1231   { "glXCopyContext", (__GLXextFuncPtr) glXCopyContext },
1232   { "glXCreateContext", (__GLXextFuncPtr) glXCreateContext },
1233   { "glXCreateGLXPixmap", (__GLXextFuncPtr) glXCreateGLXPixmap },
1234   { "glXDestroyContext", (__GLXextFuncPtr) glXDestroyContext },
1235   { "glXDestroyGLXPixmap", (__GLXextFuncPtr) glXDestroyGLXPixmap },
1236   { "glXGetConfig", (__GLXextFuncPtr) glXGetConfig },
1237   { "glXGetCurrentContext", (__GLXextFuncPtr) glXGetCurrentContext },
1238   { "glXGetCurrentDrawable", (__GLXextFuncPtr) glXGetCurrentDrawable },
1239   { "glXIsDirect", (__GLXextFuncPtr) glXIsDirect },
1240   { "glXMakeCurrent", (__GLXextFuncPtr) glXMakeCurrent },
1241   { "glXQueryExtension", (__GLXextFuncPtr) glXQueryExtension },
1242   { "glXQueryVersion", (__GLXextFuncPtr) glXQueryVersion },
1243   { "glXSwapBuffers", (__GLXextFuncPtr) glXSwapBuffers },
1244   { "glXUseXFont", (__GLXextFuncPtr) glXUseXFont },
1245   { "glXWaitGL", (__GLXextFuncPtr) glXWaitGL },
1246   { "glXWaitX", (__GLXextFuncPtr) glXWaitX },
1247
1248   /*** GLX_VERSION_1_1 ***/
1249   { "glXGetClientString", (__GLXextFuncPtr) glXGetClientString },
1250   { "glXQueryExtensionsString", (__GLXextFuncPtr) glXQueryExtensionsString },
1251   { "glXQueryServerString", (__GLXextFuncPtr) glXQueryServerString },
1252
1253   /*** GLX_VERSION_1_2 ***/
1254   { "glXGetCurrentDisplay", (__GLXextFuncPtr) glXGetCurrentDisplay },
1255
1256   /*** GLX_VERSION_1_3 ***/
1257   { "glXChooseFBConfig", (__GLXextFuncPtr) glXChooseFBConfig },
1258   { "glXCreateNewContext", (__GLXextFuncPtr) glXCreateNewContext },
1259   { "glXCreatePbuffer", (__GLXextFuncPtr) glXCreatePbuffer },
1260   { "glXCreatePixmap", (__GLXextFuncPtr) glXCreatePixmap },
1261   { "glXCreateWindow", (__GLXextFuncPtr) glXCreateWindow },
1262   { "glXDestroyPbuffer", (__GLXextFuncPtr) glXDestroyPbuffer },
1263   { "glXDestroyPixmap", (__GLXextFuncPtr) glXDestroyPixmap },
1264   { "glXDestroyWindow", (__GLXextFuncPtr) glXDestroyWindow },
1265   { "glXGetCurrentReadDrawable", (__GLXextFuncPtr) glXGetCurrentReadDrawable },
1266   { "glXGetFBConfigAttrib", (__GLXextFuncPtr) glXGetFBConfigAttrib },
1267   { "glXGetFBConfigs", (__GLXextFuncPtr) glXGetFBConfigs },
1268   { "glXGetSelectedEvent", (__GLXextFuncPtr) glXGetSelectedEvent },
1269   { "glXGetVisualFromFBConfig", (__GLXextFuncPtr) glXGetVisualFromFBConfig },
1270   { "glXMakeContextCurrent", (__GLXextFuncPtr) glXMakeContextCurrent },
1271   { "glXQueryContext", (__GLXextFuncPtr) glXQueryContext },
1272   { "glXQueryDrawable", (__GLXextFuncPtr) glXQueryDrawable },
1273   { "glXSelectEvent", (__GLXextFuncPtr) glXSelectEvent },
1274
1275   /*** GLX_VERSION_1_4 ***/
1276   { "glXGetProcAddress", (__GLXextFuncPtr) glXGetProcAddress },
1277
1278   /*** GLX_SGI_swap_control ***/
1279   { "glXSwapIntervalSGI", (__GLXextFuncPtr) glXSwapIntervalSGI },
1280
1281   /*** GLX_SGI_video_sync ***/
1282   { "glXGetVideoSyncSGI", (__GLXextFuncPtr) glXGetVideoSyncSGI },
1283   { "glXWaitVideoSyncSGI", (__GLXextFuncPtr) glXWaitVideoSyncSGI },
1284
1285   /*** GLX_SGI_make_current_read ***/
1286   { "glXMakeCurrentReadSGI", (__GLXextFuncPtr) glXMakeCurrentReadSGI },
1287   { "glXGetCurrentReadDrawableSGI", (__GLXextFuncPtr) glXGetCurrentReadDrawableSGI },
1288
1289   /*** GLX_SGIX_video_source ***/
1290#if defined(_VL_H)
1291   { "glXCreateGLXVideoSourceSGIX", (__GLXextFuncPtr) glXCreateGLXVideoSourceSGIX },
1292   { "glXDestroyGLXVideoSourceSGIX", (__GLXextFuncPtr) glXDestroyGLXVideoSourceSGIX },
1293#endif
1294
1295   /*** GLX_EXT_import_context ***/
1296   { "glXFreeContextEXT", (__GLXextFuncPtr) glXFreeContextEXT },
1297   { "glXGetContextIDEXT", (__GLXextFuncPtr) glXGetContextIDEXT },
1298   { "glXGetCurrentDisplayEXT", (__GLXextFuncPtr) glXGetCurrentDisplayEXT },
1299   { "glXImportContextEXT", (__GLXextFuncPtr) glXImportContextEXT },
1300   { "glXQueryContextInfoEXT", (__GLXextFuncPtr) glXQueryContextInfoEXT },
1301
1302   /*** GLX_SGIX_fbconfig ***/
1303   { "glXGetFBConfigAttribSGIX", (__GLXextFuncPtr) glXGetFBConfigAttribSGIX },
1304   { "glXChooseFBConfigSGIX", (__GLXextFuncPtr) glXChooseFBConfigSGIX },
1305   { "glXCreateGLXPixmapWithConfigSGIX", (__GLXextFuncPtr) glXCreateGLXPixmapWithConfigSGIX },
1306   { "glXCreateContextWithConfigSGIX", (__GLXextFuncPtr) glXCreateContextWithConfigSGIX },
1307   { "glXGetVisualFromFBConfigSGIX", (__GLXextFuncPtr) glXGetVisualFromFBConfigSGIX },
1308   { "glXGetFBConfigFromVisualSGIX", (__GLXextFuncPtr) glXGetFBConfigFromVisualSGIX },
1309
1310   /*** GLX_SGIX_pbuffer ***/
1311   { "glXCreateGLXPbufferSGIX", (__GLXextFuncPtr) glXCreateGLXPbufferSGIX },
1312   { "glXDestroyGLXPbufferSGIX", (__GLXextFuncPtr) glXDestroyGLXPbufferSGIX },
1313   { "glXQueryGLXPbufferSGIX", (__GLXextFuncPtr) glXQueryGLXPbufferSGIX },
1314   { "glXSelectEventSGIX", (__GLXextFuncPtr) glXSelectEventSGIX },
1315   { "glXGetSelectedEventSGIX", (__GLXextFuncPtr) glXGetSelectedEventSGIX },
1316
1317   /*** GLX_SGI_cushion ***/
1318   { "glXCushionSGI", (__GLXextFuncPtr) glXCushionSGI },
1319
1320   /*** GLX_SGIX_video_resize ***/
1321   { "glXBindChannelToWindowSGIX", (__GLXextFuncPtr) glXBindChannelToWindowSGIX },
1322   { "glXChannelRectSGIX", (__GLXextFuncPtr) glXChannelRectSGIX },
1323   { "glXQueryChannelRectSGIX", (__GLXextFuncPtr) glXQueryChannelRectSGIX },
1324   { "glXQueryChannelDeltasSGIX", (__GLXextFuncPtr) glXQueryChannelDeltasSGIX },
1325   { "glXChannelRectSyncSGIX", (__GLXextFuncPtr) glXChannelRectSyncSGIX },
1326
1327   /*** GLX_SGIX_dmbuffer **/
1328#if defined(_DM_BUFFER_H_)
1329   { "glXAssociateDMPbufferSGIX", (__GLXextFuncPtr) glXAssociateDMPbufferSGIX },
1330#endif
1331
1332   /*** GLX_SGIX_swap_group ***/
1333   { "glXJoinSwapGroupSGIX", (__GLXextFuncPtr) glXJoinSwapGroupSGIX },
1334
1335   /*** GLX_SGIX_swap_barrier ***/
1336   { "glXBindSwapBarrierSGIX", (__GLXextFuncPtr) glXBindSwapBarrierSGIX },
1337   { "glXQueryMaxSwapBarriersSGIX", (__GLXextFuncPtr) glXQueryMaxSwapBarriersSGIX },
1338
1339   /*** GLX_SUN_get_transparent_index ***/
1340   { "glXGetTransparentIndexSUN", (__GLXextFuncPtr) glXGetTransparentIndexSUN },
1341
1342   /*** GLX_MESA_copy_sub_buffer ***/
1343   { "glXCopySubBufferMESA", (__GLXextFuncPtr) glXCopySubBufferMESA },
1344
1345   /*** GLX_MESA_pixmap_colormap ***/
1346   { "glXCreateGLXPixmapMESA", (__GLXextFuncPtr) glXCreateGLXPixmapMESA },
1347
1348   /*** GLX_MESA_release_buffers ***/
1349   { "glXReleaseBuffersMESA", (__GLXextFuncPtr) glXReleaseBuffersMESA },
1350
1351   /*** GLX_MESA_set_3dfx_mode ***/
1352   { "glXSet3DfxModeMESA", (__GLXextFuncPtr) glXSet3DfxModeMESA },
1353
1354   /*** GLX_ARB_get_proc_address ***/
1355   { "glXGetProcAddressARB", (__GLXextFuncPtr) glXGetProcAddressARB },
1356
1357   /*** GLX_NV_vertex_array_range ***/
1358   { "glXAllocateMemoryNV", (__GLXextFuncPtr) glXAllocateMemoryNV },
1359   { "glXFreeMemoryNV", (__GLXextFuncPtr) glXFreeMemoryNV },
1360
1361   /*** GLX_MESA_agp_offset ***/
1362   { "glXGetAGPOffsetMESA", (__GLXextFuncPtr) glXGetAGPOffsetMESA },
1363
1364   /*** GLX_EXT_texture_from_pixmap ***/
1365   { "glXBindTexImageEXT", (__GLXextFuncPtr) glXBindTexImageEXT },
1366   { "glXReleaseTexImageEXT", (__GLXextFuncPtr) glXReleaseTexImageEXT },
1367
1368   { NULL, NULL }   /* end of list */
1369};
1370
1371
1372
1373/*
1374 * Return address of named glX function, or NULL if not found.
1375 */
1376__GLXextFuncPtr
1377_glxapi_get_proc_address(const char *funcName)
1378{
1379   GLuint i;
1380   for (i = 0; GLX_functions[i].Name; i++) {
1381#ifdef MANGLE
1382      /* skip the "m" prefix on the name */
1383      if (strcmp(GLX_functions[i].Name, funcName+1) == 0)
1384#else
1385      if (strcmp(GLX_functions[i].Name, funcName) == 0)
1386#endif
1387         return GLX_functions[i].Address;
1388   }
1389   return NULL;
1390}
1391
1392
1393
1394/*
1395 * This function does not get dispatched through the dispatch table
1396 * since it's really a "meta" function.
1397 */
1398__GLXextFuncPtr PUBLIC
1399glXGetProcAddressARB(const GLubyte *procName)
1400{
1401   __GLXextFuncPtr f;
1402
1403   f = _glxapi_get_proc_address((const char *) procName);
1404   if (f) {
1405      return f;
1406   }
1407
1408   f = (__GLXextFuncPtr) _glapi_get_proc_address((const char *) procName);
1409   return f;
1410}
1411
1412
1413/* GLX 1.4 */
1414void PUBLIC
1415(*glXGetProcAddress(const GLubyte *procName))()
1416{
1417   return glXGetProcAddressARB(procName);
1418}
1419