glxapi.c revision 5605798e56ca6e9f968623f33b58ee7ca90594af
1/* $Id: glxapi.c,v 1.16 2000/04/10 21:13:19 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  3.3
6 *
7 * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28/*
29 * This is the GLX API dispatcher.  Calls to the glX* functions are
30 * either routed to real (SGI / Utah) GLX encoders or to Mesa's
31 * pseudo-GLX module.
32 */
33
34
35#include <assert.h>
36#include <stdlib.h>
37#include "glapi.h"
38#include "glxapi.h"
39
40
41/*
42 * XXX - this really shouldn't be here.
43 * Instead, add -DUSE_MESA_GLX to the compiler flags when needed.
44 */
45#define USE_MESA_GLX 1
46
47
48/* Rather than include possibly non-existant headers... */
49#ifdef USE_SGI_GLX
50extern struct _glxapi_table *_sgi_GetGLXDispatchtable(void);
51#endif
52#ifdef USE_UTAH_GLX
53extern struct _glxapi_table *_utah_GetGLXDispatchTable(void);
54#endif
55#ifdef USE_MESA_GLX
56extern struct _glxapi_table *_mesa_GetGLXDispatchTable(void);
57#endif
58
59
60
61struct display_dispatch {
62   Display *Dpy;
63   struct _glxapi_table *Table;
64   struct display_dispatch *Next;
65};
66
67static struct display_dispatch *DispatchList = NULL;
68
69
70static struct _glxapi_table *
71get_dispatch(Display *dpy)
72{
73   static Display *prevDisplay = NULL;
74   static struct _glxapi_table *prevTable = NULL;
75
76   if (!dpy)
77      return NULL;
78
79   /* try cached display */
80   if (dpy == prevDisplay) {
81      return prevTable;
82   }
83
84   /* search list of display/dispatch pairs for this display */
85   {
86      const struct display_dispatch *d = DispatchList;
87      while (d) {
88         if (d->Dpy == dpy) {
89            prevDisplay = dpy;
90            prevTable = d->Table;
91            return d->Table;  /* done! */
92         }
93         d = d->Next;
94      }
95   }
96
97   /* A new display, determine if we should use real GLX (SGI / Utah)
98    * or Mesa's pseudo-GLX.
99    */
100   {
101      struct _glxapi_table *t = NULL;
102
103#if defined(USE_SGI_GLX) || defined(USE_UTAH_GLX)
104      if (!getenv("MESA_FORCE_SOFTX")) {
105         int ignore;
106         if (XQueryExtension( dpy, "GLX", &ignore, &ignore, &ignore )) {
107            /* the X server has the GLX extension */
108#if defined(USE_SGI_GLX)
109            t = _sgi_GetGLXDispatchtable();
110#elif defined(USE_UTAH_GLX)
111            t = _utah_GetGLXDispatchTable();
112#endif
113         }
114      }
115#endif
116
117#if defined(USE_MESA_GLX)
118      if (!t) {
119         t = _mesa_GetGLXDispatchTable();
120         assert(t);  /* this has to work */
121      }
122#endif
123
124      if (t) {
125         struct display_dispatch *d;
126         d = (struct display_dispatch *) malloc(sizeof(struct display_dispatch));
127         if (d) {
128            d->Dpy = dpy;
129            d->Table = t;
130            /* insert at head of list */
131            d->Next = DispatchList;
132            DispatchList = d;
133            /* update cache */
134            prevDisplay = dpy;
135            prevTable = t;
136            return t;
137         }
138      }
139   }
140
141   /* If we get here that means we can't use real GLX on this display
142    * and the Mesa pseudo-GLX software renderer wasn't compiled in.
143    * Or, we ran out of memory!
144    */
145   return NULL;
146}
147
148
149
150/* Set by glXMakeCurrent() and glXMakeContextCurrent() only */
151static Display *CurrentDisplay = NULL;
152static GLXContext CurrentContext = 0;
153static GLXDrawable CurrentDrawable = 0;
154static GLXDrawable CurrentReadDrawable = 0;
155
156
157
158/*
159 * GLX API entrypoints
160 */
161
162
163XVisualInfo *glXChooseVisual(Display *dpy, int screen, int *list)
164{
165   struct _glxapi_table *t = get_dispatch(dpy);
166   if (!t)
167      return NULL;
168   return (t->ChooseVisual)(dpy, screen, list);
169}
170
171
172void glXCopyContext(Display *dpy, GLXContext src, GLXContext dst, unsigned long mask)
173{
174   struct _glxapi_table *t = get_dispatch(dpy);
175   if (!t)
176      return;
177   (t->CopyContext)(dpy, src, dst, mask);
178}
179
180
181GLXContext glXCreateContext(Display *dpy, XVisualInfo *visinfo, GLXContext shareList, Bool direct)
182{
183   struct _glxapi_table *t = get_dispatch(dpy);
184   if (!t)
185      return 0;
186   return (t->CreateContext)(dpy, visinfo, shareList, direct);
187}
188
189
190GLXPixmap glXCreateGLXPixmap(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap)
191{
192   struct _glxapi_table *t = get_dispatch(dpy);
193   if (!t)
194      return 0;
195   return (t->CreateGLXPixmap)(dpy, visinfo, pixmap);
196}
197
198
199void glXDestroyContext(Display *dpy, GLXContext ctx)
200{
201   struct _glxapi_table *t = get_dispatch(dpy);
202   if (!t)
203      return;
204   (t->DestroyContext)(dpy, ctx);
205}
206
207
208void glXDestroyGLXPixmap(Display *dpy, GLXPixmap pixmap)
209{
210   struct _glxapi_table *t = get_dispatch(dpy);
211   if (!t)
212      return;
213   (t->DestroyGLXPixmap)(dpy, pixmap);
214}
215
216
217int glXGetConfig(Display *dpy, XVisualInfo *visinfo, int attrib, int *value)
218{
219   struct _glxapi_table *t = get_dispatch(dpy);
220   if (!t)
221      return GLX_NO_EXTENSION;
222   return (t->GetConfig)(dpy, visinfo, attrib, value);
223}
224
225
226GLXContext glXGetCurrentContext(void)
227{
228   return CurrentContext;
229}
230
231
232GLXDrawable glXGetCurrentDrawable(void)
233{
234   return CurrentDrawable;
235}
236
237
238Bool glXIsDirect(Display *dpy, GLXContext ctx)
239{
240   struct _glxapi_table *t = get_dispatch(dpy);
241   if (!t)
242      return False;
243   return (t->IsDirect)(dpy, ctx);
244}
245
246
247Bool glXMakeCurrent(Display *dpy, GLXDrawable drawable, GLXContext ctx)
248{
249   Bool b;
250   struct _glxapi_table *t = get_dispatch(dpy);
251   if (!t)
252      return False;
253   b = (*t->MakeCurrent)(dpy, drawable, ctx);
254   if (b) {
255      CurrentDisplay = dpy;
256      CurrentContext = ctx;
257      CurrentDrawable = drawable;
258      CurrentReadDrawable = drawable;
259   }
260   return b;
261}
262
263
264Bool glXQueryExtension(Display *dpy, int *errorb, int *event)
265{
266   struct _glxapi_table *t = get_dispatch(dpy);
267   if (!t)
268      return False;
269   return (t->QueryExtension)(dpy, errorb, event);
270}
271
272
273Bool glXQueryVersion(Display *dpy, int *maj, int *min)
274{
275   struct _glxapi_table *t = get_dispatch(dpy);
276   if (!t)
277      return False;
278   return (t->QueryVersion)(dpy, maj, min);
279}
280
281
282void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
283{
284   struct _glxapi_table *t = get_dispatch(dpy);
285   if (!t)
286      return;
287   (t->SwapBuffers)(dpy, drawable);
288}
289
290
291void glXUseXFont(Font font, int first, int count, int listBase)
292{
293   struct _glxapi_table *t = get_dispatch(CurrentDisplay);
294   if (!t)
295      return;
296   (t->UseXFont)(font, first, count, listBase);
297}
298
299
300void glXWaitGL(void)
301{
302   struct _glxapi_table *t = get_dispatch(CurrentDisplay);
303   if (!t)
304      return;
305   (t->WaitGL)();
306}
307
308
309void glXWaitX(void)
310{
311   struct _glxapi_table *t = get_dispatch(CurrentDisplay);
312   if (!t)
313      return;
314   (t->WaitX)();
315}
316
317
318
319#ifdef _GLXAPI_VERSION_1_1
320
321const char *glXGetClientString(Display *dpy, int name)
322{
323   struct _glxapi_table *t = get_dispatch(dpy);
324   if (!t)
325      return NULL;
326   return (t->GetClientString)(dpy, name);
327}
328
329
330const char *glXQueryExtensionsString(Display *dpy, int screen)
331{
332   struct _glxapi_table *t = get_dispatch(dpy);
333   if (!t)
334      return NULL;
335   return (t->QueryExtensionsString)(dpy, screen);
336}
337
338
339const char *glXQueryServerString(Display *dpy, int screen, int name)
340{
341   struct _glxapi_table *t = get_dispatch(dpy);
342   if (!t)
343      return NULL;
344   return (t->QueryServerString)(dpy, screen, name);
345}
346
347#endif
348
349
350
351#ifdef _GLXAPI_VERSION_1_2
352Display *glXGetCurrentDisplay(void)
353{
354   return CurrentDisplay;
355}
356#endif
357
358
359
360#ifdef _GLXAPI_VERSION_1_3
361
362GLXFBConfig *glXChooseFBConfig(Display *dpy, int screen, const int *attribList, int *nitems)
363{
364   struct _glxapi_table *t = get_dispatch(dpy);
365   if (!t)
366      return 0;
367   return (t->ChooseFBConfig)(dpy, screen, attribList, nitems);
368}
369
370
371GLXContext glXCreateNewContext(Display *dpy, GLXFBConfig config, int renderType, GLXContext shareList, Bool direct)
372{
373   struct _glxapi_table *t = get_dispatch(dpy);
374   if (!t)
375      return 0;
376   return (t->CreateNewContext)(dpy, config, renderType, shareList, direct);
377}
378
379
380GLXPbuffer glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attribList)
381{
382   struct _glxapi_table *t = get_dispatch(dpy);
383   if (!t)
384      return 0;
385   return (t->CreatePbuffer)(dpy, config, attribList);
386}
387
388
389GLXPixmap glXCreatePixmap(Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attribList)
390{
391   struct _glxapi_table *t = get_dispatch(dpy);
392   if (!t)
393      return 0;
394   return (t->CreatePixmap)(dpy, config, pixmap, attribList);
395}
396
397
398GLXWindow glXCreateWindow(Display *dpy, GLXFBConfig config, Window win, const int *attribList)
399{
400   struct _glxapi_table *t = get_dispatch(dpy);
401   if (!t)
402      return 0;
403   return (t->CreateWindow)(dpy, config, win, attribList);
404}
405
406
407void glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf)
408{
409   struct _glxapi_table *t = get_dispatch(dpy);
410   if (!t)
411      return;
412   (t->DestroyPbuffer)(dpy, pbuf);
413}
414
415
416void glXDestroyPixmap(Display *dpy, GLXPixmap pixmap)
417{
418   struct _glxapi_table *t = get_dispatch(dpy);
419   if (!t)
420      return;
421   (t->DestroyPixmap)(dpy, pixmap);
422}
423
424
425void glXDestroyWindow(Display *dpy, GLXWindow window)
426{
427   struct _glxapi_table *t = get_dispatch(dpy);
428   if (!t)
429      return;
430   (t->DestroyWindow)(dpy, window);
431}
432
433
434GLXDrawable glXGetCurrentReadDrawable(void)
435{
436   return CurrentReadDrawable;
437}
438
439
440int glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config, int attribute, int *value)
441{
442   struct _glxapi_table *t = get_dispatch(dpy);
443   if (!t)
444      return GLX_NO_EXTENSION;
445   return (t->GetFBConfigAttrib)(dpy, config, attribute, value);
446}
447
448
449GLXFBConfig *glXGetFBConfigs(Display *dpy, int screen, int *nelements)
450{
451   struct _glxapi_table *t = get_dispatch(dpy);
452   if (!t)
453      return 0;
454   return (t->GetFBConfigs)(dpy, screen, nelements);
455}
456
457void glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, unsigned long *mask)
458{
459   struct _glxapi_table *t = get_dispatch(dpy);
460   if (!t)
461      return;
462   (t->GetSelectedEvent)(dpy, drawable, mask);
463}
464
465
466XVisualInfo *glXGetVisualFromFBConfig(Display *dpy, GLXFBConfig config)
467{
468   struct _glxapi_table *t = get_dispatch(dpy);
469   if (!t)
470      return NULL;
471   return (t->GetVisualFromFBConfig)(dpy, config);
472}
473
474
475Bool glXMakeContextCurrent(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
476{
477   struct _glxapi_table *t = get_dispatch(dpy);
478   Bool b;
479   if (!t)
480      return False;
481   b = (t->MakeContextCurrent)(dpy, draw, read, ctx);
482   if (b) {
483      CurrentDisplay = dpy;
484      CurrentContext = ctx;
485      CurrentDrawable = draw;
486      CurrentReadDrawable = read;
487   }
488   return b;
489}
490
491
492int glXQueryContext(Display *dpy, GLXContext ctx, int attribute, int *value)
493{
494   struct _glxapi_table *t = get_dispatch(dpy);
495   assert(t);
496   if (!t)
497      return 0; /* XXX correct? */
498   return (t->QueryContext)(dpy, ctx, attribute, value);
499}
500
501
502void glXQueryDrawable(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value)
503{
504   struct _glxapi_table *t = get_dispatch(dpy);
505   if (!t)
506      return;
507   (t->QueryDrawable)(dpy, draw, attribute, value);
508}
509
510
511void glXSelectEvent(Display *dpy, GLXDrawable drawable, unsigned long mask)
512{
513   struct _glxapi_table *t = get_dispatch(dpy);
514   if (!t)
515      return;
516   (t->SelectEvent)(dpy, drawable, mask);
517}
518
519#endif /* _GLXAPI_VERSION_1_3 */
520
521
522#ifdef _GLXAPI_EXT_import_context
523
524void glXFreeContextEXT(Display *dpy, GLXContext context)
525{
526   struct _glxapi_table *t = get_dispatch(dpy);
527   if (!t)
528      return;
529   (t->FreeContextEXT)(dpy, context);
530}
531
532
533GLXContextID glXGetContextIDEXT(const GLXContext context)
534{
535   /* XXX is this function right? */
536   struct _glxapi_table *t = get_dispatch(CurrentDisplay);
537   if (!t)
538      return 0;
539   return (t->GetContextIDEXT)(context);
540}
541
542
543Display *glXGetCurrentDisplayEXT(void)
544{
545   return CurrentDisplay;
546}
547
548
549GLXContext glXImportContextEXT(Display *dpy, GLXContextID contextID)
550{
551   struct _glxapi_table *t = get_dispatch(dpy);
552   if (!t)
553      return 0;
554   return (t->ImportContextEXT)(dpy, contextID);
555}
556
557int glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute,int *value)
558{
559   struct _glxapi_table *t = get_dispatch(dpy);
560   if (!t)
561      return 0;  /* XXX ok? */
562   return (t->QueryContextInfoEXT)(dpy, context, attribute, value);
563}
564
565#endif
566
567
568#ifdef _GLXAPI_SGI_video_sync
569
570int glXGetVideoSyncSGI(unsigned int *count)
571{
572   struct _glxapi_table *t = get_dispatch(CurrentDisplay);
573   if (!t)
574      return 0;
575   return (t->GetVideoSyncSGI)(count);
576}
577
578
579int glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
580{
581   struct _glxapi_table *t = get_dispatch(CurrentDisplay);
582   if (!t)
583      return 0;
584   return (t->WaitVideoSyncSGI)(divisor, remainder, count);
585}
586
587#endif
588
589
590#ifdef _GLXAPI_MESA_copy_sub_buffer
591
592void glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable, int x, int y, int width, int height)
593{
594   struct _glxapi_table *t = get_dispatch(dpy);
595   if (!t)
596      return;
597   (t->CopySubBufferMESA)(dpy, drawable, x, y, width, height);
598}
599
600#endif
601
602
603#ifdef _GLXAPI_MESA_release_buffers
604
605Bool glXReleaseBuffersMESA(Display *dpy, Window w)
606{
607   struct _glxapi_table *t = get_dispatch(dpy);
608   if (!t)
609      return False;
610   return (t->ReleaseBuffersMESA)(dpy, w);
611}
612
613#endif
614
615
616#ifdef _GLXAPI_MESA_pixmap_colormap
617
618GLXPixmap glXCreateGLXPixmapMESA(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap, Colormap cmap)
619{
620   struct _glxapi_table *t = get_dispatch(dpy);
621   if (!t)
622      return 0;
623   return (t->CreateGLXPixmapMESA)(dpy, visinfo, pixmap, cmap);
624}
625
626#endif
627
628
629#ifdef _GLXAPI_MESA_set_3dfx_mode
630
631GLboolean glXSet3DfxModeMESA(GLint mode)
632{
633   struct _glxapi_table *t = get_dispatch(CurrentDisplay);
634   if (!t)
635      return False;
636   return (t->Set3DfxModeMESA)(mode);
637}
638
639#endif
640
641
642
643/**********************************************************************/
644/* GLX API management functions                                       */
645/**********************************************************************/
646
647
648const char *
649_glxapi_get_version(void)
650{
651   return "1.3";
652}
653
654
655/*
656 * Return array of extension strings.
657 */
658const char **
659_glxapi_get_extensions(void)
660{
661   static const char *extensions[] = {
662#ifdef _GLXAPI_EXT_import_context
663      "GLX_EXT_import_context",
664#endif
665#ifdef _GLXAPI_SGI_video_sync
666      "GLX_SGI_video_sync",
667#endif
668#ifdef _GLXAPI_MESA_copy_sub_buffer
669      "GLX_MESA_copy_sub_buffer",
670#endif
671#ifdef _GLXAPI_MESA_release_buffers
672      "GLX_MESA_release_buffers",
673#endif
674#ifdef _GLXAPI_MESA_pixmap_colormap
675      "GLX_MESA_pixmap_colormap",
676#endif
677#ifdef _GLXAPI_MESA_set_3dfx_mode
678      "GLX_MESA_set_3dfx_mode",
679#endif
680      NULL
681   };
682   return extensions;
683}
684
685
686/*
687 * Return size of the GLX dispatch table, in entries, not bytes.
688 */
689GLuint
690_glxapi_get_dispatch_table_size(void)
691{
692   return sizeof(struct _glxapi_table) / sizeof(void *);
693}
694
695
696static int
697generic_no_op_func(void)
698{
699   return 0;
700}
701
702
703/*
704 * Initialize all functions in given dispatch table to be no-ops
705 */
706void
707_glxapi_set_no_op_table(struct _glxapi_table *t)
708{
709   GLuint n = _glxapi_get_dispatch_table_size();
710   GLuint i;
711   void **dispatch = (void **) t;
712   for (i = 0; i < n; i++) {
713      dispatch[i] = (void *) generic_no_op_func;
714   }
715}
716
717
718
719struct name_address_pair {
720   const char *Name;
721   GLvoid *Address;
722};
723
724static struct name_address_pair GLX_functions[] = {
725   { "glXChooseVisual", (GLvoid *) glXChooseVisual },
726   { "glXCopyContext", (GLvoid *) glXCopyContext },
727   { "glXCreateContext", (GLvoid *) glXCreateContext },
728   { "glXCreateGLXPixmap", (GLvoid *) glXCreateGLXPixmap },
729   { "glXDestroyContext", (GLvoid *) glXDestroyContext },
730   { "glXDestroyGLXPixmap", (GLvoid *) glXDestroyGLXPixmap },
731   { "glXGetConfig", (GLvoid *) glXGetConfig },
732   { "glXGetCurrentContext", (GLvoid *) glXGetCurrentContext },
733   { "glXGetCurrentDrawable", (GLvoid *) glXGetCurrentDrawable },
734   { "glXIsDirect", (GLvoid *) glXIsDirect },
735   { "glXMakeCurrent", (GLvoid *) glXMakeCurrent },
736   { "glXQueryExtension", (GLvoid *) glXQueryExtension },
737   { "glXQueryVersion", (GLvoid *) glXQueryVersion },
738   { "glXSwapBuffers", (GLvoid *) glXSwapBuffers },
739   { "glXUseXFont", (GLvoid *) glXUseXFont },
740   { "glXWaitGL", (GLvoid *) glXWaitGL },
741   { "glXWaitX", (GLvoid *) glXWaitX },
742
743#ifdef _GLXAPI_VERSION_1_1
744   { "glXGetClientString", (GLvoid *) glXGetClientString },
745   { "glXQueryExtensionsString", (GLvoid *) glXQueryExtensionsString },
746   { "glXQueryServerString", (GLvoid *) glXQueryServerString },
747#endif
748
749#ifdef _GLXAPI_VERSION_1_2
750   { "glXGetCurrentDisplay", (GLvoid *) glXGetCurrentDisplay },
751#endif
752
753#ifdef _GLXAPI_VERSION_1_3
754   { "glXChooseFBConfig", (GLvoid *) glXChooseFBConfig },
755   { "glXCreateNewContext", (GLvoid *) glXCreateNewContext },
756   { "glXCreatePbuffer", (GLvoid *) glXCreatePbuffer },
757   { "glXCreatePixmap", (GLvoid *) glXCreatePixmap },
758   { "glXCreateWindow", (GLvoid *) glXCreateWindow },
759   { "glXDestroyPbuffer", (GLvoid *) glXDestroyPbuffer },
760   { "glXDestroyPixmap", (GLvoid *) glXDestroyPixmap },
761   { "glXDestroyWindow", (GLvoid *) glXDestroyWindow },
762   { "glXGetCurrentReadDrawable", (GLvoid *) glXGetCurrentReadDrawable },
763   { "glXGetFBConfigAttrib", (GLvoid *) glXGetFBConfigAttrib },
764   { "glXGetSelectedEvent", (GLvoid *) glXGetSelectedEvent },
765   { "glXGetVisualFromFBConfig", (GLvoid *) glXGetVisualFromFBConfig },
766   { "glXMakeContextCurrent", (GLvoid *) glXMakeContextCurrent },
767   { "glXQueryContext", (GLvoid *) glXQueryContext },
768   { "glXQueryDrawable", (GLvoid *) glXQueryDrawable },
769   { "glXSelectEvent", (GLvoid *) glXSelectEvent },
770#endif
771
772#ifdef _GLXAPI_SGI_video_sync
773   { "glXGetVideoSyncSGI", (GLvoid *) glXGetVideoSyncSGI },
774   { "glXWaitVideoSyncSGI", (GLvoid *) glXWaitVideoSyncSGI },
775#endif
776
777#ifdef _GLXAPI_MESA_copy_sub_buffer
778   { "glXCopySubBufferMESA", (GLvoid *) glXCopySubBufferMESA },
779#endif
780
781#ifdef _GLXAPI_MESA_release_buffers
782   { "glXReleaseBuffersMESA", (GLvoid *) glXReleaseBuffersMESA },
783#endif
784
785#ifdef _GLXAPI_MESA_pixmap_colormap
786   { "glXCreateGLXPixmapMESA", (GLvoid *) glXCreateGLXPixmapMESA },
787#endif
788
789#ifdef _GLXAPI_MESA_set_3dfx_mode
790   { "glXSet3DfxModeMESA", (GLvoid *) glXSet3DfxModeMESA },
791#endif
792
793   { "glXGetProcAddressARB", (GLvoid *) glXGetProcAddressARB },
794
795   { NULL, NULL }   /* end of list */
796};
797
798
799
800/*
801 * Return address of named glX function, or NULL if not found.
802 */
803const GLvoid *
804_glxapi_get_proc_address(const char *funcName)
805{
806   GLuint i;
807   for (i = 0; GLX_functions[i].Name; i++) {
808      if (strcmp(GLX_functions[i].Name, funcName) == 0)
809         return GLX_functions[i].Address;
810   }
811   return NULL;
812}
813
814
815
816/*
817 * This function does not get dispatched through the dispatch table
818 * since it's really a "meta" function.
819 */
820void (*glXGetProcAddressARB(const GLubyte *procName))()
821{
822   typedef void (*gl_function)();
823   gl_function f;
824
825   f = (gl_function) _glxapi_get_proc_address((const char *) procName);
826   if (f) {
827      return f;
828   }
829
830   f = (gl_function) _glapi_get_proc_address((const char *) procName);
831   return f;
832}
833