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