Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
  4.  * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
  5.  * Copyright 2010-2011 LunarG, Inc.
  6.  * All Rights Reserved.
  7.  *
  8.  * Permission is hereby granted, free of charge, to any person obtaining a
  9.  * copy of this software and associated documentation files (the
  10.  * "Software"), to deal in the Software without restriction, including
  11.  * without limitation the rights to use, copy, modify, merge, publish,
  12.  * distribute, sub license, and/or sell copies of the Software, and to
  13.  * permit persons to whom the Software is furnished to do so, subject to
  14.  * the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice (including the
  17.  * next paragraph) shall be included in all copies or substantial portions
  18.  * of the Software.
  19.  *
  20.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  21.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  22.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  23.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  24.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  25.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  26.  * DEALINGS IN THE SOFTWARE.
  27.  *
  28.  **************************************************************************/
  29.  
  30.  
  31. /**
  32.  * This is an EGL driver that wraps GLX. This gives the benefit of being
  33.  * completely agnostic of the direct rendering implementation.
  34.  *
  35.  * Authors: Alan Hourihane <alanh@tungstengraphics.com>
  36.  */
  37.  
  38. #include <stdlib.h>
  39. #include <string.h>
  40. #include <X11/Xlib.h>
  41. #include <dlfcn.h>
  42. #include "GL/glx.h"
  43.  
  44. #include "eglconfig.h"
  45. #include "eglcontext.h"
  46. #include "egldefines.h"
  47. #include "egldisplay.h"
  48. #include "egldriver.h"
  49. #include "eglcurrent.h"
  50. #include "egllog.h"
  51. #include "eglsurface.h"
  52.  
  53. #define CALLOC_STRUCT(T)   (struct T *) calloc(1, sizeof(struct T))
  54.  
  55. #ifndef GLX_VERSION_1_4
  56. #error "GL/glx.h must be equal to or greater than GLX 1.4"
  57. #endif
  58.  
  59. /* GLX 1.0 */
  60. typedef GLXContext (*GLXCREATECONTEXTPROC)( Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct );
  61. typedef void (*GLXDESTROYCONTEXTPROC)( Display *dpy, GLXContext ctx );
  62. typedef Bool (*GLXMAKECURRENTPROC)( Display *dpy, GLXDrawable drawable, GLXContext ctx);
  63. typedef void (*GLXSWAPBUFFERSPROC)( Display *dpy, GLXDrawable drawable );
  64. typedef GLXPixmap (*GLXCREATEGLXPIXMAPPROC)( Display *dpy, XVisualInfo *visual, Pixmap pixmap );
  65. typedef void (*GLXDESTROYGLXPIXMAPPROC)( Display *dpy, GLXPixmap pixmap );
  66. typedef Bool (*GLXQUERYVERSIONPROC)( Display *dpy, int *maj, int *min );
  67. typedef int (*GLXGETCONFIGPROC)( Display *dpy, XVisualInfo *visual, int attrib, int *value );
  68. typedef void (*GLXWAITGLPROC)( void );
  69. typedef void (*GLXWAITXPROC)( void );
  70.  
  71. /* GLX 1.1 */
  72. typedef const char *(*GLXQUERYEXTENSIONSSTRINGPROC)( Display *dpy, int screen );
  73. typedef const char *(*GLXQUERYSERVERSTRINGPROC)( Display *dpy, int screen, int name );
  74. typedef const char *(*GLXGETCLIENTSTRINGPROC)( Display *dpy, int name );
  75.  
  76. /** subclass of _EGLDriver */
  77. struct GLX_egl_driver
  78. {
  79.    _EGLDriver Base;   /**< base class */
  80.  
  81.    void *handle;
  82.  
  83.    /* GLX 1.0 */
  84.    GLXCREATECONTEXTPROC glXCreateContext;
  85.    GLXDESTROYCONTEXTPROC glXDestroyContext;
  86.    GLXMAKECURRENTPROC glXMakeCurrent;
  87.    GLXSWAPBUFFERSPROC glXSwapBuffers;
  88.    GLXCREATEGLXPIXMAPPROC glXCreateGLXPixmap;
  89.    GLXDESTROYGLXPIXMAPPROC glXDestroyGLXPixmap;
  90.    GLXQUERYVERSIONPROC glXQueryVersion;
  91.    GLXGETCONFIGPROC glXGetConfig;
  92.    GLXWAITGLPROC glXWaitGL;
  93.    GLXWAITXPROC glXWaitX;
  94.  
  95.    /* GLX 1.1 */
  96.    GLXQUERYEXTENSIONSSTRINGPROC glXQueryExtensionsString;
  97.    GLXQUERYSERVERSTRINGPROC glXQueryServerString;
  98.    GLXGETCLIENTSTRINGPROC glXGetClientString;
  99.  
  100.    /* GLX 1.3 or (GLX_SGI_make_current_read and GLX_SGIX_fbconfig) */
  101.    PFNGLXGETFBCONFIGSPROC glXGetFBConfigs;
  102.    PFNGLXGETFBCONFIGATTRIBPROC glXGetFBConfigAttrib;
  103.    PFNGLXGETVISUALFROMFBCONFIGPROC glXGetVisualFromFBConfig;
  104.    PFNGLXCREATEWINDOWPROC glXCreateWindow;
  105.    PFNGLXDESTROYWINDOWPROC glXDestroyWindow;
  106.    PFNGLXCREATEPIXMAPPROC glXCreatePixmap;
  107.    PFNGLXDESTROYPIXMAPPROC glXDestroyPixmap;
  108.    PFNGLXCREATEPBUFFERPROC glXCreatePbuffer;
  109.    PFNGLXDESTROYPBUFFERPROC glXDestroyPbuffer;
  110.    PFNGLXCREATENEWCONTEXTPROC glXCreateNewContext;
  111.    PFNGLXMAKECONTEXTCURRENTPROC glXMakeContextCurrent;
  112.  
  113.    /* GLX 1.4 or GLX_ARB_get_proc_address */
  114.    PFNGLXGETPROCADDRESSPROC glXGetProcAddress;
  115.  
  116.    /* GLX_SGIX_pbuffer */
  117.    PFNGLXCREATEGLXPBUFFERSGIXPROC glXCreateGLXPbufferSGIX;
  118.    PFNGLXDESTROYGLXPBUFFERSGIXPROC glXDestroyGLXPbufferSGIX;
  119. };
  120.  
  121.  
  122. /** driver data of _EGLDisplay */
  123. struct GLX_egl_display
  124. {
  125.    Display *dpy;
  126.    XVisualInfo *visuals;
  127.    GLXFBConfig *fbconfigs;
  128.  
  129.    int glx_maj, glx_min;
  130.  
  131.    const char *extensions;
  132.    EGLBoolean have_1_3;
  133.    EGLBoolean have_make_current_read;
  134.    EGLBoolean have_fbconfig;
  135.    EGLBoolean have_pbuffer;
  136.  
  137.    /* workaround quirks of different GLX implementations */
  138.    EGLBoolean single_buffered_quirk;
  139.    EGLBoolean glx_window_quirk;
  140. };
  141.  
  142.  
  143. /** subclass of _EGLContext */
  144. struct GLX_egl_context
  145. {
  146.    _EGLContext Base;   /**< base class */
  147.  
  148.    GLXContext context;
  149. };
  150.  
  151.  
  152. /** subclass of _EGLSurface */
  153. struct GLX_egl_surface
  154. {
  155.    _EGLSurface Base;   /**< base class */
  156.  
  157.    Drawable drawable;
  158.    GLXDrawable glx_drawable;
  159.  
  160.    void (*destroy)(Display *, GLXDrawable);
  161. };
  162.  
  163.  
  164. /** subclass of _EGLConfig */
  165. struct GLX_egl_config
  166. {
  167.    _EGLConfig Base;   /**< base class */
  168.    EGLBoolean double_buffered;
  169.    int index;
  170. };
  171.  
  172. /* standard typecasts */
  173. _EGL_DRIVER_STANDARD_TYPECASTS(GLX_egl)
  174.  
  175. static int
  176. GLX_egl_config_index(_EGLConfig *conf)
  177. {
  178.    struct GLX_egl_config *GLX_conf = GLX_egl_config(conf);
  179.    return GLX_conf->index;
  180. }
  181.  
  182.  
  183. static const struct {
  184.    int attr;
  185.    int egl_attr;
  186. } fbconfig_attributes[] = {
  187.    /* table 3.1 of GLX 1.4 */
  188.    { GLX_FBCONFIG_ID,                  0 },
  189.    { GLX_BUFFER_SIZE,                  EGL_BUFFER_SIZE },
  190.    { GLX_LEVEL,                        EGL_LEVEL },
  191.    { GLX_DOUBLEBUFFER,                 0 },
  192.    { GLX_STEREO,                       0 },
  193.    { GLX_AUX_BUFFERS,                  0 },
  194.    { GLX_RED_SIZE,                     EGL_RED_SIZE },
  195.    { GLX_GREEN_SIZE,                   EGL_GREEN_SIZE },
  196.    { GLX_BLUE_SIZE,                    EGL_BLUE_SIZE },
  197.    { GLX_ALPHA_SIZE,                   EGL_ALPHA_SIZE },
  198.    { GLX_DEPTH_SIZE,                   EGL_DEPTH_SIZE },
  199.    { GLX_STENCIL_SIZE,                 EGL_STENCIL_SIZE },
  200.    { GLX_ACCUM_RED_SIZE,               0 },
  201.    { GLX_ACCUM_GREEN_SIZE,             0 },
  202.    { GLX_ACCUM_BLUE_SIZE,              0 },
  203.    { GLX_ACCUM_ALPHA_SIZE,             0 },
  204.    { GLX_SAMPLE_BUFFERS,               EGL_SAMPLE_BUFFERS },
  205.    { GLX_SAMPLES,                      EGL_SAMPLES },
  206.    { GLX_RENDER_TYPE,                  0 },
  207.    { GLX_DRAWABLE_TYPE,                EGL_SURFACE_TYPE },
  208.    { GLX_X_RENDERABLE,                 EGL_NATIVE_RENDERABLE },
  209.    { GLX_X_VISUAL_TYPE,                EGL_NATIVE_VISUAL_TYPE },
  210.    { GLX_CONFIG_CAVEAT,                EGL_CONFIG_CAVEAT },
  211.    { GLX_TRANSPARENT_TYPE,             EGL_TRANSPARENT_TYPE },
  212.    { GLX_TRANSPARENT_INDEX_VALUE,      0 },
  213.    { GLX_TRANSPARENT_RED_VALUE,        EGL_TRANSPARENT_RED_VALUE },
  214.    { GLX_TRANSPARENT_GREEN_VALUE,      EGL_TRANSPARENT_GREEN_VALUE },
  215.    { GLX_TRANSPARENT_BLUE_VALUE,       EGL_TRANSPARENT_BLUE_VALUE },
  216.    { GLX_MAX_PBUFFER_WIDTH,            EGL_MAX_PBUFFER_WIDTH },
  217.    { GLX_MAX_PBUFFER_HEIGHT,           EGL_MAX_PBUFFER_HEIGHT },
  218.    { GLX_MAX_PBUFFER_PIXELS,           EGL_MAX_PBUFFER_PIXELS },
  219.    { GLX_VISUAL_ID,                    EGL_NATIVE_VISUAL_ID }
  220. };
  221.  
  222.  
  223. static EGLBoolean
  224. convert_fbconfig(struct GLX_egl_driver *GLX_drv,
  225.                  struct GLX_egl_display *GLX_dpy, GLXFBConfig fbconfig,
  226.                  struct GLX_egl_config *GLX_conf)
  227. {
  228.    Display *dpy = GLX_dpy->dpy;
  229.    int err, attr, val;
  230.    unsigned i;
  231.  
  232.    /* must have rgba bit */
  233.    err = GLX_drv->glXGetFBConfigAttrib(dpy, fbconfig, GLX_RENDER_TYPE, &val);
  234.    if (err || !(val & GLX_RGBA_BIT))
  235.       return EGL_FALSE;
  236.  
  237.    /* must know whether it is double-buffered */
  238.    err = GLX_drv->glXGetFBConfigAttrib(dpy, fbconfig, GLX_DOUBLEBUFFER, &val);
  239.    if (err)
  240.       return EGL_FALSE;
  241.    GLX_conf->double_buffered = val;
  242.  
  243.    GLX_conf->Base.RenderableType = EGL_OPENGL_BIT;
  244.    GLX_conf->Base.Conformant = EGL_OPENGL_BIT;
  245.  
  246.    for (i = 0; i < ARRAY_SIZE(fbconfig_attributes); i++) {
  247.       EGLint egl_attr, egl_val;
  248.  
  249.       attr = fbconfig_attributes[i].attr;
  250.       egl_attr = fbconfig_attributes[i].egl_attr;
  251.       if (!egl_attr)
  252.          continue;
  253.  
  254.       err = GLX_drv->glXGetFBConfigAttrib(dpy, fbconfig, attr, &val);
  255.       if (err) {
  256.          if (err == GLX_BAD_ATTRIBUTE) {
  257.             err = 0;
  258.             continue;
  259.          }
  260.          break;
  261.       }
  262.  
  263.       switch (egl_attr) {
  264.       case EGL_SURFACE_TYPE:
  265.          egl_val = 0;
  266.          if (val & GLX_WINDOW_BIT)
  267.             egl_val |= EGL_WINDOW_BIT;
  268.          /* pixmap and pbuffer surfaces must be single-buffered in EGL */
  269.          if (!GLX_conf->double_buffered) {
  270.             if (val & GLX_PIXMAP_BIT)
  271.                egl_val |= EGL_PIXMAP_BIT;
  272.             if (val & GLX_PBUFFER_BIT)
  273.                egl_val |= EGL_PBUFFER_BIT;
  274.          }
  275.          break;
  276.       case EGL_NATIVE_VISUAL_TYPE:
  277.          switch (val) {
  278.          case GLX_TRUE_COLOR:
  279.             egl_val = TrueColor;
  280.             break;
  281.          case GLX_DIRECT_COLOR:
  282.             egl_val = DirectColor;
  283.             break;
  284.          case GLX_PSEUDO_COLOR:
  285.             egl_val = PseudoColor;
  286.             break;
  287.          case GLX_STATIC_COLOR:
  288.             egl_val = StaticColor;
  289.             break;
  290.          case GLX_GRAY_SCALE:
  291.             egl_val = GrayScale;
  292.             break;
  293.          case GLX_STATIC_GRAY:
  294.             egl_val = StaticGray;
  295.             break;
  296.          default:
  297.             egl_val = EGL_NONE;
  298.             break;
  299.          }
  300.          break;
  301.       case EGL_CONFIG_CAVEAT:
  302.          egl_val = EGL_NONE;
  303.          if (val == GLX_SLOW_CONFIG) {
  304.             egl_val = EGL_SLOW_CONFIG;
  305.          }
  306.          else if (val == GLX_NON_CONFORMANT_CONFIG) {
  307.             GLX_conf->Base.Conformant &= ~EGL_OPENGL_BIT;
  308.             egl_val = EGL_NONE;
  309.          }
  310.          break;
  311.       case EGL_TRANSPARENT_TYPE:
  312.          egl_val = (val == GLX_TRANSPARENT_RGB) ?
  313.             EGL_TRANSPARENT_RGB : EGL_NONE;
  314.          break;
  315.       default:
  316.          egl_val = val;
  317.          break;
  318.       }
  319.  
  320.       _eglSetConfigKey(&GLX_conf->Base, egl_attr, egl_val);
  321.    }
  322.    if (err)
  323.       return EGL_FALSE;
  324.  
  325.    if (!GLX_conf->Base.SurfaceType)
  326.       return EGL_FALSE;
  327.  
  328.    return EGL_TRUE;
  329. }
  330.  
  331. static const struct {
  332.    int attr;
  333.    int egl_attr;
  334. } visual_attributes[] = {
  335.    /* table 3.7 of GLX 1.4 */
  336.    { GLX_USE_GL,              0 },
  337.    { GLX_BUFFER_SIZE,         EGL_BUFFER_SIZE },
  338.    { GLX_LEVEL,               EGL_LEVEL },
  339.    { GLX_RGBA,                0 },
  340.    { GLX_DOUBLEBUFFER,        0 },
  341.    { GLX_STEREO,              0 },
  342.    { GLX_AUX_BUFFERS,         0 },
  343.    { GLX_RED_SIZE,            EGL_RED_SIZE },
  344.    { GLX_GREEN_SIZE,          EGL_GREEN_SIZE },
  345.    { GLX_BLUE_SIZE,           EGL_BLUE_SIZE },
  346.    { GLX_ALPHA_SIZE,          EGL_ALPHA_SIZE },
  347.    { GLX_DEPTH_SIZE,          EGL_DEPTH_SIZE },
  348.    { GLX_STENCIL_SIZE,        EGL_STENCIL_SIZE },
  349.    { GLX_ACCUM_RED_SIZE,      0 },
  350.    { GLX_ACCUM_GREEN_SIZE,    0 },
  351.    { GLX_ACCUM_BLUE_SIZE,     0 },
  352.    { GLX_ACCUM_ALPHA_SIZE,    0 },
  353.    { GLX_SAMPLE_BUFFERS,      EGL_SAMPLE_BUFFERS },
  354.    { GLX_SAMPLES,             EGL_SAMPLES },
  355.    { GLX_FBCONFIG_ID,         0 },
  356.    /* GLX_EXT_visual_rating */
  357.    { GLX_VISUAL_CAVEAT_EXT,   EGL_CONFIG_CAVEAT }
  358. };
  359.  
  360. static EGLBoolean
  361. convert_visual(struct GLX_egl_driver *GLX_drv,
  362.                struct GLX_egl_display *GLX_dpy, XVisualInfo *vinfo,
  363.                struct GLX_egl_config *GLX_conf)
  364. {
  365.    Display *dpy = GLX_dpy->dpy;
  366.    int err, attr, val;
  367.    unsigned i;
  368.  
  369.    /* the visual must support OpenGL and RGBA buffer */
  370.    err = GLX_drv->glXGetConfig(dpy, vinfo, GLX_USE_GL, &val);
  371.    if (!err && val)
  372.       err = GLX_drv->glXGetConfig(dpy, vinfo, GLX_RGBA, &val);
  373.    if (err || !val)
  374.       return EGL_FALSE;
  375.  
  376.    /* must know whether it is double-buffered */
  377.    err = GLX_drv->glXGetConfig(dpy, vinfo, GLX_DOUBLEBUFFER, &val);
  378.    if (err)
  379.       return EGL_FALSE;
  380.    GLX_conf->double_buffered = val;
  381.  
  382.    GLX_conf->Base.RenderableType = EGL_OPENGL_BIT;
  383.    GLX_conf->Base.Conformant = EGL_OPENGL_BIT;
  384.    GLX_conf->Base.SurfaceType = EGL_WINDOW_BIT;
  385.    /* pixmap surfaces must be single-buffered in EGL */
  386.    if (!GLX_conf->double_buffered)
  387.       GLX_conf->Base.SurfaceType |= EGL_PIXMAP_BIT;
  388.  
  389.    GLX_conf->Base.NativeVisualID = vinfo->visualid;
  390.    GLX_conf->Base.NativeVisualType = vinfo->class;
  391.    GLX_conf->Base.NativeRenderable = EGL_TRUE;
  392.  
  393.    for (i = 0; i < ARRAY_SIZE(visual_attributes); i++) {
  394.       EGLint egl_attr, egl_val;
  395.  
  396.       attr = visual_attributes[i].attr;
  397.       egl_attr = visual_attributes[i].egl_attr;
  398.       if (!egl_attr)
  399.          continue;
  400.  
  401.       err = GLX_drv->glXGetConfig(dpy, vinfo, attr, &val);
  402.       if (err) {
  403.          if (err == GLX_BAD_ATTRIBUTE) {
  404.             err = 0;
  405.             continue;
  406.          }
  407.          break;
  408.       }
  409.  
  410.       switch (egl_attr) {
  411.       case EGL_CONFIG_CAVEAT:
  412.          egl_val = EGL_NONE;
  413.          if (val == GLX_SLOW_VISUAL_EXT) {
  414.             egl_val = EGL_SLOW_CONFIG;
  415.          }
  416.          else if (val == GLX_NON_CONFORMANT_VISUAL_EXT) {
  417.             GLX_conf->Base.Conformant &= ~EGL_OPENGL_BIT;
  418.             egl_val = EGL_NONE;
  419.          }
  420.          break;
  421.          break;
  422.       default:
  423.          egl_val = val;
  424.          break;
  425.       }
  426.       _eglSetConfigKey(&GLX_conf->Base, egl_attr, egl_val);
  427.    }
  428.  
  429.    return (err) ? EGL_FALSE : EGL_TRUE;
  430. }
  431.  
  432.  
  433. static void
  434. fix_config(struct GLX_egl_display *GLX_dpy, struct GLX_egl_config *GLX_conf)
  435. {
  436.    _EGLConfig *conf = &GLX_conf->Base;
  437.  
  438.    if (!GLX_conf->double_buffered && GLX_dpy->single_buffered_quirk) {
  439.       /* some GLX impls do not like single-buffered window surface */
  440.       conf->SurfaceType &= ~EGL_WINDOW_BIT;
  441.       /* pbuffer bit is usually not set */
  442.       if (GLX_dpy->have_pbuffer)
  443.          conf->SurfaceType |= EGL_PBUFFER_BIT;
  444.    }
  445.  
  446.    /* no visual attribs unless window bit is set */
  447.    if (!(conf->SurfaceType & EGL_WINDOW_BIT)) {
  448.       conf->NativeVisualID = 0;
  449.       conf->NativeVisualType = EGL_NONE;
  450.    }
  451.  
  452.    if (conf->TransparentType != EGL_TRANSPARENT_RGB) {
  453.       /* some impls set them to -1 (GLX_DONT_CARE) */
  454.       conf->TransparentRedValue = 0;
  455.       conf->TransparentGreenValue = 0;
  456.       conf->TransparentBlueValue = 0;
  457.    }
  458.  
  459.    /* make sure buffer size is set correctly */
  460.    conf->BufferSize =
  461.       conf->RedSize + conf->GreenSize + conf->BlueSize + conf->AlphaSize;
  462. }
  463.  
  464.  
  465. static EGLBoolean
  466. create_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint screen)
  467. {
  468.    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
  469.    struct GLX_egl_display *GLX_dpy = GLX_egl_display(dpy);
  470.    EGLint num_configs = 0, i;
  471.    EGLint id = 1;
  472.  
  473.    if (GLX_dpy->have_fbconfig) {
  474.       GLX_dpy->fbconfigs =
  475.          GLX_drv->glXGetFBConfigs(GLX_dpy->dpy, screen, &num_configs);
  476.    }
  477.    else {
  478.       XVisualInfo vinfo_template;
  479.       long mask;
  480.  
  481.       vinfo_template.screen = screen;
  482.       mask = VisualScreenMask;
  483.       GLX_dpy->visuals = XGetVisualInfo(GLX_dpy->dpy, mask, &vinfo_template,
  484.                                         &num_configs);
  485.    }
  486.  
  487.    if (!num_configs)
  488.       return EGL_FALSE;
  489.  
  490.    for (i = 0; i < num_configs; i++) {
  491.       struct GLX_egl_config *GLX_conf, template;
  492.       EGLBoolean ok;
  493.  
  494.       memset(&template, 0, sizeof(template));
  495.       _eglInitConfig(&template.Base, dpy, id);
  496.       if (GLX_dpy->have_fbconfig) {
  497.          ok = convert_fbconfig(GLX_drv, GLX_dpy,
  498.                GLX_dpy->fbconfigs[i], &template);
  499.       }
  500.       else {
  501.          ok = convert_visual(GLX_drv, GLX_dpy,
  502.                &GLX_dpy->visuals[i], &template);
  503.       }
  504.       if (!ok)
  505.         continue;
  506.  
  507.       fix_config(GLX_dpy, &template);
  508.       if (!_eglValidateConfig(&template.Base, EGL_FALSE)) {
  509.          _eglLog(_EGL_DEBUG, "GLX: failed to validate config %d", i);
  510.          continue;
  511.       }
  512.  
  513.       GLX_conf = CALLOC_STRUCT(GLX_egl_config);
  514.       if (GLX_conf) {
  515.          memcpy(GLX_conf, &template, sizeof(template));
  516.          GLX_conf->index = i;
  517.  
  518.          _eglLinkConfig(&GLX_conf->Base);
  519.          id++;
  520.       }
  521.    }
  522.  
  523.    return EGL_TRUE;
  524. }
  525.  
  526.  
  527. static void
  528. check_extensions(struct GLX_egl_driver *GLX_drv,
  529.                  struct GLX_egl_display *GLX_dpy, EGLint screen)
  530. {
  531.    GLX_dpy->extensions =
  532.       GLX_drv->glXQueryExtensionsString(GLX_dpy->dpy, screen);
  533.    if (GLX_dpy->extensions) {
  534.       if (strstr(GLX_dpy->extensions, "GLX_SGI_make_current_read")) {
  535.          /* GLX 1.3 entry points are used */
  536.          GLX_dpy->have_make_current_read = EGL_TRUE;
  537.       }
  538.  
  539.       if (strstr(GLX_dpy->extensions, "GLX_SGIX_fbconfig")) {
  540.          /* GLX 1.3 entry points are used */
  541.          GLX_dpy->have_fbconfig = EGL_TRUE;
  542.       }
  543.  
  544.       if (strstr(GLX_dpy->extensions, "GLX_SGIX_pbuffer")) {
  545.          if (GLX_drv->glXCreateGLXPbufferSGIX &&
  546.              GLX_drv->glXDestroyGLXPbufferSGIX &&
  547.              GLX_dpy->have_fbconfig)
  548.             GLX_dpy->have_pbuffer = EGL_TRUE;
  549.       }
  550.    }
  551.  
  552.    if (GLX_dpy->glx_maj == 1 && GLX_dpy->glx_min >= 3) {
  553.       GLX_dpy->have_1_3 = EGL_TRUE;
  554.       GLX_dpy->have_make_current_read = EGL_TRUE;
  555.       GLX_dpy->have_fbconfig = EGL_TRUE;
  556.       GLX_dpy->have_pbuffer = EGL_TRUE;
  557.    }
  558. }
  559.  
  560.  
  561. static void
  562. check_quirks(struct GLX_egl_driver *GLX_drv,
  563.              struct GLX_egl_display *GLX_dpy, EGLint screen)
  564. {
  565.    const char *vendor;
  566.  
  567.    GLX_dpy->single_buffered_quirk = EGL_TRUE;
  568.    GLX_dpy->glx_window_quirk = EGL_TRUE;
  569.  
  570.    vendor = GLX_drv->glXGetClientString(GLX_dpy->dpy, GLX_VENDOR);
  571.    if (vendor && strstr(vendor, "NVIDIA")) {
  572.       vendor = GLX_drv->glXQueryServerString(GLX_dpy->dpy, screen, GLX_VENDOR);
  573.       if (vendor && strstr(vendor, "NVIDIA")) {
  574.          _eglLog(_EGL_DEBUG, "disable quirks");
  575.          GLX_dpy->single_buffered_quirk = EGL_FALSE;
  576.          GLX_dpy->glx_window_quirk = EGL_FALSE;
  577.       }
  578.    }
  579. }
  580.  
  581.  
  582. /**
  583.  * Called via eglInitialize(), GLX_drv->API.Initialize().
  584.  */
  585. static EGLBoolean
  586. GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp)
  587. {
  588.    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
  589.    struct GLX_egl_display *GLX_dpy;
  590.  
  591.    if (disp->Platform != _EGL_PLATFORM_X11)
  592.       return EGL_FALSE;
  593.  
  594.    /* this is a fallback driver */
  595.    if (!disp->Options.UseFallback)
  596.       return EGL_FALSE;
  597.  
  598.    if (disp->Options.TestOnly)
  599.       return EGL_TRUE;
  600.  
  601.    GLX_dpy = CALLOC_STRUCT(GLX_egl_display);
  602.    if (!GLX_dpy)
  603.       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
  604.  
  605.    GLX_dpy->dpy = (Display *) disp->PlatformDisplay;
  606.    if (!GLX_dpy->dpy) {
  607.       GLX_dpy->dpy = XOpenDisplay(NULL);
  608.       if (!GLX_dpy->dpy) {
  609.          _eglLog(_EGL_WARNING, "GLX: XOpenDisplay failed");
  610.          free(GLX_dpy);
  611.          return EGL_FALSE;
  612.       }
  613.    }
  614.  
  615.    if (!GLX_drv->glXQueryVersion(GLX_dpy->dpy,
  616.             &GLX_dpy->glx_maj, &GLX_dpy->glx_min)) {
  617.       _eglLog(_EGL_WARNING, "GLX: glXQueryVersion failed");
  618.       if (!disp->PlatformDisplay)
  619.          XCloseDisplay(GLX_dpy->dpy);
  620.       free(GLX_dpy);
  621.       return EGL_FALSE;
  622.    }
  623.  
  624.    disp->DriverData = (void *) GLX_dpy;
  625.    disp->ClientAPIs = EGL_OPENGL_BIT;
  626.  
  627.    check_extensions(GLX_drv, GLX_dpy, DefaultScreen(GLX_dpy->dpy));
  628.    check_quirks(GLX_drv, GLX_dpy, DefaultScreen(GLX_dpy->dpy));
  629.  
  630.    create_configs(drv, disp, DefaultScreen(GLX_dpy->dpy));
  631.    if (!_eglGetArraySize(disp->Configs)) {
  632.       _eglLog(_EGL_WARNING, "GLX: failed to create any config");
  633.       if (!disp->PlatformDisplay)
  634.          XCloseDisplay(GLX_dpy->dpy);
  635.       free(GLX_dpy);
  636.       return EGL_FALSE;
  637.    }
  638.  
  639.    /* we're supporting EGL 1.4 */
  640.    disp->VersionMajor = 1;
  641.    disp->VersionMinor = 4;
  642.  
  643.    return EGL_TRUE;
  644. }
  645.  
  646.  
  647. /**
  648.  * Called via eglTerminate(), drv->API.Terminate().
  649.  */
  650. static EGLBoolean
  651. GLX_eglTerminate(_EGLDriver *drv, _EGLDisplay *disp)
  652. {
  653.    struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
  654.  
  655.    _eglReleaseDisplayResources(drv, disp);
  656.    _eglCleanupDisplay(disp);
  657.  
  658.    free(GLX_dpy->visuals);
  659.    free(GLX_dpy->fbconfigs);
  660.  
  661.    if (!disp->PlatformDisplay)
  662.       XCloseDisplay(GLX_dpy->dpy);
  663.    free(GLX_dpy);
  664.  
  665.    disp->DriverData = NULL;
  666.  
  667.    return EGL_TRUE;
  668. }
  669.  
  670.  
  671. /**
  672.  * Called via eglCreateContext(), drv->API.CreateContext().
  673.  */
  674. static _EGLContext *
  675. GLX_eglCreateContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
  676.                       _EGLContext *share_list, const EGLint *attrib_list)
  677. {
  678.    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
  679.    struct GLX_egl_context *GLX_ctx = CALLOC_STRUCT(GLX_egl_context);
  680.    struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
  681.    struct GLX_egl_context *GLX_ctx_shared = GLX_egl_context(share_list);
  682.  
  683.    if (!GLX_ctx) {
  684.       _eglError(EGL_BAD_ALLOC, "eglCreateContext");
  685.       return NULL;
  686.    }
  687.  
  688.    if (!_eglInitContext(&GLX_ctx->Base, disp, conf, attrib_list)) {
  689.       free(GLX_ctx);
  690.       return NULL;
  691.    }
  692.  
  693.    if (GLX_dpy->have_fbconfig) {
  694.       GLX_ctx->context = GLX_drv->glXCreateNewContext(GLX_dpy->dpy,
  695.             GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
  696.             GLX_RGBA_TYPE,
  697.             GLX_ctx_shared ? GLX_ctx_shared->context : NULL,
  698.             GL_TRUE);
  699.    }
  700.    else {
  701.       GLX_ctx->context = GLX_drv->glXCreateContext(GLX_dpy->dpy,
  702.             &GLX_dpy->visuals[GLX_egl_config_index(conf)],
  703.             GLX_ctx_shared ? GLX_ctx_shared->context : NULL,
  704.             GL_TRUE);
  705.    }
  706.    if (!GLX_ctx->context) {
  707.       free(GLX_ctx);
  708.       return NULL;
  709.    }
  710.  
  711.    return &GLX_ctx->Base;
  712. }
  713.  
  714. /**
  715.  * Called via eglDestroyContext(), drv->API.DestroyContext().
  716.  */
  717. static EGLBoolean
  718. GLX_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
  719. {
  720.    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
  721.    struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
  722.    struct GLX_egl_context *GLX_ctx = GLX_egl_context(ctx);
  723.  
  724.    if (_eglPutContext(ctx)) {
  725.       assert(GLX_ctx);
  726.       GLX_drv->glXDestroyContext(GLX_dpy->dpy, GLX_ctx->context);
  727.  
  728.       free(GLX_ctx);
  729.    }
  730.  
  731.    return EGL_TRUE;
  732. }
  733.  
  734. /**
  735.  * Destroy a surface.  The display is allowed to be uninitialized.
  736.  */
  737. static void
  738. destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
  739. {
  740.    struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
  741.    struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
  742.  
  743.    if (GLX_surf->destroy)
  744.       GLX_surf->destroy(GLX_dpy->dpy, GLX_surf->glx_drawable);
  745.  
  746.    free(GLX_surf);
  747. }
  748.  
  749.  
  750. /**
  751.  * Called via eglMakeCurrent(), drv->API.MakeCurrent().
  752.  */
  753. static EGLBoolean
  754. GLX_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
  755.                    _EGLSurface *rsurf, _EGLContext *ctx)
  756. {
  757.    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
  758.    struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
  759.    struct GLX_egl_surface *GLX_dsurf = GLX_egl_surface(dsurf);
  760.    struct GLX_egl_surface *GLX_rsurf = GLX_egl_surface(rsurf);
  761.    struct GLX_egl_context *GLX_ctx = GLX_egl_context(ctx);
  762.    _EGLContext *old_ctx;
  763.    _EGLSurface *old_dsurf, *old_rsurf;
  764.    GLXDrawable ddraw, rdraw;
  765.    GLXContext cctx;
  766.    EGLBoolean ret = EGL_FALSE;
  767.  
  768.    /* make new bindings */
  769.    if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
  770.       return EGL_FALSE;
  771.  
  772.    ddraw = (GLX_dsurf) ? GLX_dsurf->glx_drawable : None;
  773.    rdraw = (GLX_rsurf) ? GLX_rsurf->glx_drawable : None;
  774.    cctx = (GLX_ctx) ? GLX_ctx->context : NULL;
  775.  
  776.    if (GLX_dpy->have_make_current_read)
  777.       ret = GLX_drv->glXMakeContextCurrent(GLX_dpy->dpy, ddraw, rdraw, cctx);
  778.    else if (ddraw == rdraw)
  779.       ret = GLX_drv->glXMakeCurrent(GLX_dpy->dpy, ddraw, cctx);
  780.  
  781.    if (ret) {
  782.       if (_eglPutSurface(old_dsurf))
  783.          destroy_surface(disp, old_dsurf);
  784.       if (_eglPutSurface(old_rsurf))
  785.          destroy_surface(disp, old_rsurf);
  786.       /* no destroy? */
  787.       _eglPutContext(old_ctx);
  788.    }
  789.    else {
  790.       /* undo the previous _eglBindContext */
  791.       _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf);
  792.       assert(&GLX_ctx->Base == ctx &&
  793.              &GLX_dsurf->Base == dsurf &&
  794.              &GLX_rsurf->Base == rsurf);
  795.  
  796.       _eglPutSurface(dsurf);
  797.       _eglPutSurface(rsurf);
  798.       _eglPutContext(ctx);
  799.  
  800.       _eglPutSurface(old_dsurf);
  801.       _eglPutSurface(old_rsurf);
  802.       _eglPutContext(old_ctx);
  803.    }
  804.  
  805.    return ret;
  806. }
  807.  
  808. /** Get size of given window */
  809. static Status
  810. get_drawable_size(Display *dpy, Drawable d, unsigned *width, unsigned *height)
  811. {
  812.    Window root;
  813.    Status stat;
  814.    int xpos, ypos;
  815.    unsigned int w, h, bw, depth;
  816.    stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
  817.    *width = w;
  818.    *height = h;
  819.    return stat;
  820. }
  821.  
  822. /**
  823.  * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
  824.  */
  825. static _EGLSurface *
  826. GLX_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp,
  827.                            _EGLConfig *conf, EGLNativeWindowType window,
  828.                            const EGLint *attrib_list)
  829. {
  830.    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
  831.    struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
  832.    struct GLX_egl_surface *GLX_surf;
  833.    unsigned width, height;
  834.  
  835.    GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
  836.    if (!GLX_surf) {
  837.       _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
  838.       return NULL;
  839.    }
  840.  
  841.    if (!_eglInitSurface(&GLX_surf->Base, disp, EGL_WINDOW_BIT,
  842.                         conf, attrib_list)) {
  843.       free(GLX_surf);
  844.       return NULL;
  845.    }
  846.  
  847.    GLX_surf->drawable = window;
  848.  
  849.    if (GLX_dpy->have_1_3 && !GLX_dpy->glx_window_quirk) {
  850.       GLX_surf->glx_drawable = GLX_drv->glXCreateWindow(GLX_dpy->dpy,
  851.             GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
  852.             GLX_surf->drawable, NULL);
  853.    }
  854.    else {
  855.       GLX_surf->glx_drawable = GLX_surf->drawable;
  856.    }
  857.  
  858.    if (!GLX_surf->glx_drawable) {
  859.       free(GLX_surf);
  860.       return NULL;
  861.    }
  862.  
  863.    if (GLX_dpy->have_1_3 && !GLX_dpy->glx_window_quirk)
  864.       GLX_surf->destroy = GLX_drv->glXDestroyWindow;
  865.  
  866.    get_drawable_size(GLX_dpy->dpy, window, &width, &height);
  867.    GLX_surf->Base.Width = width;
  868.    GLX_surf->Base.Height = height;
  869.  
  870.    return &GLX_surf->Base;
  871. }
  872.  
  873. static _EGLSurface *
  874. GLX_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *disp,
  875.                            _EGLConfig *conf, EGLNativePixmapType pixmap,
  876.                            const EGLint *attrib_list)
  877. {
  878.    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
  879.    struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
  880.    struct GLX_egl_surface *GLX_surf;
  881.    unsigned width, height;
  882.  
  883.    GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
  884.    if (!GLX_surf) {
  885.       _eglError(EGL_BAD_ALLOC, "eglCreatePixmapSurface");
  886.       return NULL;
  887.    }
  888.  
  889.    if (!_eglInitSurface(&GLX_surf->Base, disp, EGL_PIXMAP_BIT,
  890.                         conf, attrib_list)) {
  891.       free(GLX_surf);
  892.       return NULL;
  893.    }
  894.  
  895.    GLX_surf->drawable = pixmap;
  896.  
  897.    if (GLX_dpy->have_1_3) {
  898.       GLX_surf->glx_drawable = GLX_drv->glXCreatePixmap(GLX_dpy->dpy,
  899.             GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
  900.             GLX_surf->drawable, NULL);
  901.    }
  902.    else if (GLX_dpy->have_fbconfig) {
  903.       GLXFBConfig fbconfig = GLX_dpy->fbconfigs[GLX_egl_config_index(conf)];
  904.       XVisualInfo *vinfo;
  905.  
  906.       vinfo = GLX_drv->glXGetVisualFromFBConfig(GLX_dpy->dpy, fbconfig);
  907.       if (vinfo) {
  908.          GLX_surf->glx_drawable = GLX_drv->glXCreateGLXPixmap(GLX_dpy->dpy,
  909.                vinfo, GLX_surf->drawable);
  910.          free(vinfo);
  911.       }
  912.    }
  913.    else {
  914.       GLX_surf->glx_drawable = GLX_drv->glXCreateGLXPixmap(GLX_dpy->dpy,
  915.             &GLX_dpy->visuals[GLX_egl_config_index(conf)],
  916.             GLX_surf->drawable);
  917.    }
  918.  
  919.    if (!GLX_surf->glx_drawable) {
  920.       free(GLX_surf);
  921.       return NULL;
  922.    }
  923.  
  924.    GLX_surf->destroy = (GLX_dpy->have_1_3) ?
  925.       GLX_drv->glXDestroyPixmap : GLX_drv->glXDestroyGLXPixmap;
  926.  
  927.    get_drawable_size(GLX_dpy->dpy, pixmap, &width, &height);
  928.    GLX_surf->Base.Width = width;
  929.    GLX_surf->Base.Height = height;
  930.  
  931.    return &GLX_surf->Base;
  932. }
  933.  
  934. static _EGLSurface *
  935. GLX_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp,
  936.                             _EGLConfig *conf, const EGLint *attrib_list)
  937. {
  938.    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
  939.    struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
  940.    struct GLX_egl_surface *GLX_surf;
  941.    int attribs[5];
  942.    int i;
  943.  
  944.    GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
  945.    if (!GLX_surf) {
  946.       _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
  947.       return NULL;
  948.    }
  949.  
  950.    if (!_eglInitSurface(&GLX_surf->Base, disp, EGL_PBUFFER_BIT,
  951.                         conf, attrib_list)) {
  952.       free(GLX_surf);
  953.       return NULL;
  954.    }
  955.  
  956.    i = 0;
  957.    attribs[i] = None;
  958.  
  959.    GLX_surf->drawable = None;
  960.  
  961.    if (GLX_dpy->have_1_3) {
  962.       /* put geometry in attribs */
  963.       if (GLX_surf->Base.Width) {
  964.          attribs[i++] = GLX_PBUFFER_WIDTH;
  965.          attribs[i++] = GLX_surf->Base.Width;
  966.       }
  967.       if (GLX_surf->Base.Height) {
  968.          attribs[i++] = GLX_PBUFFER_HEIGHT;
  969.          attribs[i++] = GLX_surf->Base.Height;
  970.       }
  971.       attribs[i] = None;
  972.  
  973.       GLX_surf->glx_drawable = GLX_drv->glXCreatePbuffer(GLX_dpy->dpy,
  974.             GLX_dpy->fbconfigs[GLX_egl_config_index(conf)], attribs);
  975.    }
  976.    else if (GLX_dpy->have_pbuffer) {
  977.       GLX_surf->glx_drawable = GLX_drv->glXCreateGLXPbufferSGIX(GLX_dpy->dpy,
  978.             GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
  979.             GLX_surf->Base.Width,
  980.             GLX_surf->Base.Height,
  981.             attribs);
  982.    }
  983.  
  984.    if (!GLX_surf->glx_drawable) {
  985.       free(GLX_surf);
  986.       return NULL;
  987.    }
  988.  
  989.    GLX_surf->destroy = (GLX_dpy->have_1_3) ?
  990.       GLX_drv->glXDestroyPbuffer : GLX_drv->glXDestroyGLXPbufferSGIX;
  991.  
  992.    return &GLX_surf->Base;
  993. }
  994.  
  995.  
  996. static EGLBoolean
  997. GLX_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
  998. {
  999.    (void) drv;
  1000.  
  1001.    if (_eglPutSurface(surf))
  1002.       destroy_surface(disp, surf);
  1003.  
  1004.    return EGL_TRUE;
  1005. }
  1006.  
  1007.  
  1008. static EGLBoolean
  1009. GLX_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
  1010. {
  1011.    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
  1012.    struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
  1013.    struct GLX_egl_surface *GLX_surf = GLX_egl_surface(draw);
  1014.  
  1015.    GLX_drv->glXSwapBuffers(GLX_dpy->dpy, GLX_surf->glx_drawable);
  1016.  
  1017.    return EGL_TRUE;
  1018. }
  1019.  
  1020. /*
  1021.  * Called from eglGetProcAddress() via drv->API.GetProcAddress().
  1022.  */
  1023. static _EGLProc
  1024. GLX_eglGetProcAddress(_EGLDriver *drv, const char *procname)
  1025. {
  1026.    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
  1027.  
  1028.    return (_EGLProc) GLX_drv->glXGetProcAddress((const GLubyte *) procname);
  1029. }
  1030.  
  1031. static EGLBoolean
  1032. GLX_eglWaitClient(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
  1033. {
  1034.    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
  1035.  
  1036.    (void) dpy;
  1037.    (void) ctx;
  1038.  
  1039.    GLX_drv->glXWaitGL();
  1040.    return EGL_TRUE;
  1041. }
  1042.  
  1043. static EGLBoolean
  1044. GLX_eglWaitNative(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine)
  1045. {
  1046.    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
  1047.  
  1048.    (void) dpy;
  1049.  
  1050.    if (engine != EGL_CORE_NATIVE_ENGINE)
  1051.       return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
  1052.    GLX_drv->glXWaitX();
  1053.    return EGL_TRUE;
  1054. }
  1055.  
  1056. static void
  1057. GLX_Unload(_EGLDriver *drv)
  1058. {
  1059.    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
  1060.  
  1061.    if (GLX_drv->handle)
  1062.       dlclose(GLX_drv->handle);
  1063.    free(GLX_drv);
  1064. }
  1065.  
  1066.  
  1067. static EGLBoolean
  1068. GLX_Load(_EGLDriver *drv)
  1069. {
  1070.    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
  1071.    void *handle = NULL;
  1072.  
  1073.    GLX_drv->glXGetProcAddress = dlsym(RTLD_DEFAULT, "glXGetProcAddress");
  1074.    if (!GLX_drv->glXGetProcAddress)
  1075.       GLX_drv->glXGetProcAddress = dlsym(RTLD_DEFAULT, "glXGetProcAddressARB");
  1076.    if (!GLX_drv->glXGetProcAddress) {
  1077.       handle = dlopen("libGL.so", RTLD_LAZY | RTLD_LOCAL);
  1078.       if (!handle)
  1079.          goto fail;
  1080.  
  1081.       GLX_drv->glXGetProcAddress = dlsym(handle, "glXGetProcAddress");
  1082.       if (!GLX_drv->glXGetProcAddress)
  1083.          GLX_drv->glXGetProcAddress = dlsym(handle, "glXGetProcAddressARB");
  1084.       if (!GLX_drv->glXGetProcAddress)
  1085.          goto fail;
  1086.    }
  1087.  
  1088. #define GET_PROC(proc_type, proc_name, check)                        \
  1089.    do {                                                              \
  1090.       GLX_drv->proc_name = (proc_type)                               \
  1091.          GLX_drv->glXGetProcAddress((const GLubyte *) #proc_name);   \
  1092.       if (check && !GLX_drv->proc_name) goto fail;                   \
  1093.    } while (0)
  1094.  
  1095.    /* GLX 1.0 */
  1096.    GET_PROC(GLXCREATECONTEXTPROC, glXCreateContext, EGL_TRUE);
  1097.    GET_PROC(GLXDESTROYCONTEXTPROC, glXDestroyContext, EGL_TRUE);
  1098.    GET_PROC(GLXMAKECURRENTPROC, glXMakeCurrent, EGL_TRUE);
  1099.    GET_PROC(GLXSWAPBUFFERSPROC, glXSwapBuffers, EGL_TRUE);
  1100.    GET_PROC(GLXCREATEGLXPIXMAPPROC, glXCreateGLXPixmap, EGL_TRUE);
  1101.    GET_PROC(GLXDESTROYGLXPIXMAPPROC, glXDestroyGLXPixmap, EGL_TRUE);
  1102.    GET_PROC(GLXQUERYVERSIONPROC, glXQueryVersion, EGL_TRUE);
  1103.    GET_PROC(GLXGETCONFIGPROC, glXGetConfig, EGL_TRUE);
  1104.    GET_PROC(GLXWAITGLPROC, glXWaitGL, EGL_TRUE);
  1105.    GET_PROC(GLXWAITXPROC, glXWaitX, EGL_TRUE);
  1106.  
  1107.    /* GLX 1.1 */
  1108.    GET_PROC(GLXQUERYEXTENSIONSSTRINGPROC, glXQueryExtensionsString, EGL_TRUE);
  1109.    GET_PROC(GLXQUERYSERVERSTRINGPROC, glXQueryServerString, EGL_TRUE);
  1110.    GET_PROC(GLXGETCLIENTSTRINGPROC, glXGetClientString, EGL_TRUE);
  1111.  
  1112.    /* GLX 1.3 */
  1113.    GET_PROC(PFNGLXGETFBCONFIGSPROC, glXGetFBConfigs, EGL_FALSE);
  1114.    GET_PROC(PFNGLXGETFBCONFIGATTRIBPROC, glXGetFBConfigAttrib, EGL_FALSE);
  1115.    GET_PROC(PFNGLXGETVISUALFROMFBCONFIGPROC, glXGetVisualFromFBConfig, EGL_FALSE);
  1116.    GET_PROC(PFNGLXCREATEWINDOWPROC, glXCreateWindow, EGL_FALSE);
  1117.    GET_PROC(PFNGLXDESTROYWINDOWPROC, glXDestroyWindow, EGL_FALSE);
  1118.    GET_PROC(PFNGLXCREATEPIXMAPPROC, glXCreatePixmap, EGL_FALSE);
  1119.    GET_PROC(PFNGLXDESTROYPIXMAPPROC, glXDestroyPixmap, EGL_FALSE);
  1120.    GET_PROC(PFNGLXCREATEPBUFFERPROC, glXCreatePbuffer, EGL_FALSE);
  1121.    GET_PROC(PFNGLXDESTROYPBUFFERPROC, glXDestroyPbuffer, EGL_FALSE);
  1122.    GET_PROC(PFNGLXCREATENEWCONTEXTPROC, glXCreateNewContext, EGL_FALSE);
  1123.    GET_PROC(PFNGLXMAKECONTEXTCURRENTPROC, glXMakeContextCurrent, EGL_FALSE);
  1124.  
  1125.    /* GLX_SGIX_pbuffer */
  1126.    GET_PROC(PFNGLXCREATEGLXPBUFFERSGIXPROC,
  1127.          glXCreateGLXPbufferSGIX, EGL_FALSE);
  1128.    GET_PROC(PFNGLXDESTROYGLXPBUFFERSGIXPROC,
  1129.          glXDestroyGLXPbufferSGIX, EGL_FALSE);
  1130. #undef GET_PROC
  1131.  
  1132.    GLX_drv->handle = handle;
  1133.  
  1134.    return EGL_TRUE;
  1135.  
  1136. fail:
  1137.    if (handle)
  1138.       dlclose(handle);
  1139.    return EGL_FALSE;
  1140. }
  1141.  
  1142.  
  1143. /**
  1144.  * This is the main entrypoint into the driver, called by libEGL.
  1145.  * Create a new _EGLDriver object and init its dispatch table.
  1146.  */
  1147. _EGLDriver *
  1148. _eglBuiltInDriverGLX(const char *args)
  1149. {
  1150.    struct GLX_egl_driver *GLX_drv = CALLOC_STRUCT(GLX_egl_driver);
  1151.  
  1152.    (void) args;
  1153.  
  1154.    if (!GLX_drv)
  1155.       return NULL;
  1156.  
  1157.    if (!GLX_Load(&GLX_drv->Base)) {
  1158.       _eglLog(_EGL_WARNING, "GLX: failed to load GLX");
  1159.       free(GLX_drv);
  1160.       return NULL;
  1161.    }
  1162.  
  1163.    _eglInitDriverFallbacks(&GLX_drv->Base);
  1164.    GLX_drv->Base.API.Initialize = GLX_eglInitialize;
  1165.    GLX_drv->Base.API.Terminate = GLX_eglTerminate;
  1166.    GLX_drv->Base.API.CreateContext = GLX_eglCreateContext;
  1167.    GLX_drv->Base.API.DestroyContext = GLX_eglDestroyContext;
  1168.    GLX_drv->Base.API.MakeCurrent = GLX_eglMakeCurrent;
  1169.    GLX_drv->Base.API.CreateWindowSurface = GLX_eglCreateWindowSurface;
  1170.    GLX_drv->Base.API.CreatePixmapSurface = GLX_eglCreatePixmapSurface;
  1171.    GLX_drv->Base.API.CreatePbufferSurface = GLX_eglCreatePbufferSurface;
  1172.    GLX_drv->Base.API.DestroySurface = GLX_eglDestroySurface;
  1173.    GLX_drv->Base.API.SwapBuffers = GLX_eglSwapBuffers;
  1174.    GLX_drv->Base.API.GetProcAddress = GLX_eglGetProcAddress;
  1175.    GLX_drv->Base.API.WaitClient = GLX_eglWaitClient;
  1176.    GLX_drv->Base.API.WaitNative = GLX_eglWaitNative;
  1177.  
  1178.    GLX_drv->Base.Name = "GLX";
  1179.    GLX_drv->Base.Unload = GLX_Unload;
  1180.  
  1181.    return &GLX_drv->Base;
  1182. }
  1183.