1 /************************************************************************** 2 * 3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * Copyright 2009-2010 Chia-I Wu <olvaffe (at) 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 (at) 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 if (GLX_dpy->visuals) 659 XFree(GLX_dpy->visuals); 660 if (GLX_dpy->fbconfigs) 661 XFree(GLX_dpy->fbconfigs); 662 663 if (!disp->PlatformDisplay) 664 XCloseDisplay(GLX_dpy->dpy); 665 free(GLX_dpy); 666 667 disp->DriverData = NULL; 668 669 return EGL_TRUE; 670 } 671 672 673 /** 674 * Called via eglCreateContext(), drv->API.CreateContext(). 675 */ 676 static _EGLContext * 677 GLX_eglCreateContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, 678 _EGLContext *share_list, const EGLint *attrib_list) 679 { 680 struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv); 681 struct GLX_egl_context *GLX_ctx = CALLOC_STRUCT(GLX_egl_context); 682 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); 683 struct GLX_egl_context *GLX_ctx_shared = GLX_egl_context(share_list); 684 685 if (!GLX_ctx) { 686 _eglError(EGL_BAD_ALLOC, "eglCreateContext"); 687 return NULL; 688 } 689 690 if (!_eglInitContext(&GLX_ctx->Base, disp, conf, attrib_list)) { 691 free(GLX_ctx); 692 return NULL; 693 } 694 695 if (GLX_dpy->have_fbconfig) { 696 GLX_ctx->context = GLX_drv->glXCreateNewContext(GLX_dpy->dpy, 697 GLX_dpy->fbconfigs[GLX_egl_config_index(conf)], 698 GLX_RGBA_TYPE, 699 GLX_ctx_shared ? GLX_ctx_shared->context : NULL, 700 GL_TRUE); 701 } 702 else { 703 GLX_ctx->context = GLX_drv->glXCreateContext(GLX_dpy->dpy, 704 &GLX_dpy->visuals[GLX_egl_config_index(conf)], 705 GLX_ctx_shared ? GLX_ctx_shared->context : NULL, 706 GL_TRUE); 707 } 708 if (!GLX_ctx->context) { 709 free(GLX_ctx); 710 return NULL; 711 } 712 713 return &GLX_ctx->Base; 714 } 715 716 /** 717 * Called via eglDestroyContext(), drv->API.DestroyContext(). 718 */ 719 static EGLBoolean 720 GLX_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx) 721 { 722 struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv); 723 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); 724 struct GLX_egl_context *GLX_ctx = GLX_egl_context(ctx); 725 726 if (_eglPutContext(ctx)) { 727 assert(GLX_ctx); 728 GLX_drv->glXDestroyContext(GLX_dpy->dpy, GLX_ctx->context); 729 730 free(GLX_ctx); 731 } 732 733 return EGL_TRUE; 734 } 735 736 /** 737 * Destroy a surface. The display is allowed to be uninitialized. 738 */ 739 static void 740 destroy_surface(_EGLDisplay *disp, _EGLSurface *surf) 741 { 742 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); 743 struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf); 744 745 if (GLX_surf->destroy) 746 GLX_surf->destroy(GLX_dpy->dpy, GLX_surf->glx_drawable); 747 748 free(GLX_surf); 749 } 750 751 752 /** 753 * Called via eglMakeCurrent(), drv->API.MakeCurrent(). 754 */ 755 static EGLBoolean 756 GLX_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, 757 _EGLSurface *rsurf, _EGLContext *ctx) 758 { 759 struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv); 760 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); 761 struct GLX_egl_surface *GLX_dsurf = GLX_egl_surface(dsurf); 762 struct GLX_egl_surface *GLX_rsurf = GLX_egl_surface(rsurf); 763 struct GLX_egl_context *GLX_ctx = GLX_egl_context(ctx); 764 _EGLContext *old_ctx; 765 _EGLSurface *old_dsurf, *old_rsurf; 766 GLXDrawable ddraw, rdraw; 767 GLXContext cctx; 768 EGLBoolean ret = EGL_FALSE; 769 770 /* make new bindings */ 771 if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf)) 772 return EGL_FALSE; 773 774 ddraw = (GLX_dsurf) ? GLX_dsurf->glx_drawable : None; 775 rdraw = (GLX_rsurf) ? GLX_rsurf->glx_drawable : None; 776 cctx = (GLX_ctx) ? GLX_ctx->context : NULL; 777 778 if (GLX_dpy->have_make_current_read) 779 ret = GLX_drv->glXMakeContextCurrent(GLX_dpy->dpy, ddraw, rdraw, cctx); 780 else if (ddraw == rdraw) 781 ret = GLX_drv->glXMakeCurrent(GLX_dpy->dpy, ddraw, cctx); 782 783 if (ret) { 784 if (_eglPutSurface(old_dsurf)) 785 destroy_surface(disp, old_dsurf); 786 if (_eglPutSurface(old_rsurf)) 787 destroy_surface(disp, old_rsurf); 788 /* no destroy? */ 789 _eglPutContext(old_ctx); 790 } 791 else { 792 /* undo the previous _eglBindContext */ 793 _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf); 794 assert(&GLX_ctx->Base == ctx && 795 &GLX_dsurf->Base == dsurf && 796 &GLX_rsurf->Base == rsurf); 797 798 _eglPutSurface(dsurf); 799 _eglPutSurface(rsurf); 800 _eglPutContext(ctx); 801 802 _eglPutSurface(old_dsurf); 803 _eglPutSurface(old_rsurf); 804 _eglPutContext(old_ctx); 805 } 806 807 return ret; 808 } 809 810 /** Get size of given window */ 811 static Status 812 get_drawable_size(Display *dpy, Drawable d, unsigned *width, unsigned *height) 813 { 814 Window root; 815 Status stat; 816 int xpos, ypos; 817 unsigned int w, h, bw, depth; 818 stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth); 819 *width = w; 820 *height = h; 821 return stat; 822 } 823 824 /** 825 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). 826 */ 827 static _EGLSurface * 828 GLX_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp, 829 _EGLConfig *conf, EGLNativeWindowType window, 830 const EGLint *attrib_list) 831 { 832 struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv); 833 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); 834 struct GLX_egl_surface *GLX_surf; 835 unsigned width, height; 836 837 GLX_surf = CALLOC_STRUCT(GLX_egl_surface); 838 if (!GLX_surf) { 839 _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface"); 840 return NULL; 841 } 842 843 if (!_eglInitSurface(&GLX_surf->Base, disp, EGL_WINDOW_BIT, 844 conf, attrib_list)) { 845 free(GLX_surf); 846 return NULL; 847 } 848 849 GLX_surf->drawable = window; 850 851 if (GLX_dpy->have_1_3 && !GLX_dpy->glx_window_quirk) { 852 GLX_surf->glx_drawable = GLX_drv->glXCreateWindow(GLX_dpy->dpy, 853 GLX_dpy->fbconfigs[GLX_egl_config_index(conf)], 854 GLX_surf->drawable, NULL); 855 } 856 else { 857 GLX_surf->glx_drawable = GLX_surf->drawable; 858 } 859 860 if (!GLX_surf->glx_drawable) { 861 free(GLX_surf); 862 return NULL; 863 } 864 865 if (GLX_dpy->have_1_3 && !GLX_dpy->glx_window_quirk) 866 GLX_surf->destroy = GLX_drv->glXDestroyWindow; 867 868 get_drawable_size(GLX_dpy->dpy, window, &width, &height); 869 GLX_surf->Base.Width = width; 870 GLX_surf->Base.Height = height; 871 872 return &GLX_surf->Base; 873 } 874 875 static _EGLSurface * 876 GLX_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *disp, 877 _EGLConfig *conf, EGLNativePixmapType pixmap, 878 const EGLint *attrib_list) 879 { 880 struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv); 881 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); 882 struct GLX_egl_surface *GLX_surf; 883 unsigned width, height; 884 885 GLX_surf = CALLOC_STRUCT(GLX_egl_surface); 886 if (!GLX_surf) { 887 _eglError(EGL_BAD_ALLOC, "eglCreatePixmapSurface"); 888 return NULL; 889 } 890 891 if (!_eglInitSurface(&GLX_surf->Base, disp, EGL_PIXMAP_BIT, 892 conf, attrib_list)) { 893 free(GLX_surf); 894 return NULL; 895 } 896 897 GLX_surf->drawable = pixmap; 898 899 if (GLX_dpy->have_1_3) { 900 GLX_surf->glx_drawable = GLX_drv->glXCreatePixmap(GLX_dpy->dpy, 901 GLX_dpy->fbconfigs[GLX_egl_config_index(conf)], 902 GLX_surf->drawable, NULL); 903 } 904 else if (GLX_dpy->have_fbconfig) { 905 GLXFBConfig fbconfig = GLX_dpy->fbconfigs[GLX_egl_config_index(conf)]; 906 XVisualInfo *vinfo; 907 908 vinfo = GLX_drv->glXGetVisualFromFBConfig(GLX_dpy->dpy, fbconfig); 909 if (vinfo) { 910 GLX_surf->glx_drawable = GLX_drv->glXCreateGLXPixmap(GLX_dpy->dpy, 911 vinfo, GLX_surf->drawable); 912 XFree(vinfo); 913 } 914 } 915 else { 916 GLX_surf->glx_drawable = GLX_drv->glXCreateGLXPixmap(GLX_dpy->dpy, 917 &GLX_dpy->visuals[GLX_egl_config_index(conf)], 918 GLX_surf->drawable); 919 } 920 921 if (!GLX_surf->glx_drawable) { 922 free(GLX_surf); 923 return NULL; 924 } 925 926 GLX_surf->destroy = (GLX_dpy->have_1_3) ? 927 GLX_drv->glXDestroyPixmap : GLX_drv->glXDestroyGLXPixmap; 928 929 get_drawable_size(GLX_dpy->dpy, pixmap, &width, &height); 930 GLX_surf->Base.Width = width; 931 GLX_surf->Base.Height = height; 932 933 return &GLX_surf->Base; 934 } 935 936 static _EGLSurface * 937 GLX_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp, 938 _EGLConfig *conf, const EGLint *attrib_list) 939 { 940 struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv); 941 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); 942 struct GLX_egl_surface *GLX_surf; 943 int attribs[5]; 944 int i; 945 946 GLX_surf = CALLOC_STRUCT(GLX_egl_surface); 947 if (!GLX_surf) { 948 _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface"); 949 return NULL; 950 } 951 952 if (!_eglInitSurface(&GLX_surf->Base, disp, EGL_PBUFFER_BIT, 953 conf, attrib_list)) { 954 free(GLX_surf); 955 return NULL; 956 } 957 958 i = 0; 959 attribs[i] = None; 960 961 GLX_surf->drawable = None; 962 963 if (GLX_dpy->have_1_3) { 964 /* put geometry in attribs */ 965 if (GLX_surf->Base.Width) { 966 attribs[i++] = GLX_PBUFFER_WIDTH; 967 attribs[i++] = GLX_surf->Base.Width; 968 } 969 if (GLX_surf->Base.Height) { 970 attribs[i++] = GLX_PBUFFER_HEIGHT; 971 attribs[i++] = GLX_surf->Base.Height; 972 } 973 attribs[i] = None; 974 975 GLX_surf->glx_drawable = GLX_drv->glXCreatePbuffer(GLX_dpy->dpy, 976 GLX_dpy->fbconfigs[GLX_egl_config_index(conf)], attribs); 977 } 978 else if (GLX_dpy->have_pbuffer) { 979 GLX_surf->glx_drawable = GLX_drv->glXCreateGLXPbufferSGIX(GLX_dpy->dpy, 980 GLX_dpy->fbconfigs[GLX_egl_config_index(conf)], 981 GLX_surf->Base.Width, 982 GLX_surf->Base.Height, 983 attribs); 984 } 985 986 if (!GLX_surf->glx_drawable) { 987 free(GLX_surf); 988 return NULL; 989 } 990 991 GLX_surf->destroy = (GLX_dpy->have_1_3) ? 992 GLX_drv->glXDestroyPbuffer : GLX_drv->glXDestroyGLXPbufferSGIX; 993 994 return &GLX_surf->Base; 995 } 996 997 998 static EGLBoolean 999 GLX_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) 1000 { 1001 (void) drv; 1002 1003 if (_eglPutSurface(surf)) 1004 destroy_surface(disp, surf); 1005 1006 return EGL_TRUE; 1007 } 1008 1009 1010 static EGLBoolean 1011 GLX_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) 1012 { 1013 struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv); 1014 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); 1015 struct GLX_egl_surface *GLX_surf = GLX_egl_surface(draw); 1016 1017 GLX_drv->glXSwapBuffers(GLX_dpy->dpy, GLX_surf->glx_drawable); 1018 1019 return EGL_TRUE; 1020 } 1021 1022 /* 1023 * Called from eglGetProcAddress() via drv->API.GetProcAddress(). 1024 */ 1025 static _EGLProc 1026 GLX_eglGetProcAddress(_EGLDriver *drv, const char *procname) 1027 { 1028 struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv); 1029 1030 return (_EGLProc) GLX_drv->glXGetProcAddress((const GLubyte *) procname); 1031 } 1032 1033 static EGLBoolean 1034 GLX_eglWaitClient(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) 1035 { 1036 struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv); 1037 1038 (void) dpy; 1039 (void) ctx; 1040 1041 GLX_drv->glXWaitGL(); 1042 return EGL_TRUE; 1043 } 1044 1045 static EGLBoolean 1046 GLX_eglWaitNative(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine) 1047 { 1048 struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv); 1049 1050 (void) dpy; 1051 1052 if (engine != EGL_CORE_NATIVE_ENGINE) 1053 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); 1054 GLX_drv->glXWaitX(); 1055 return EGL_TRUE; 1056 } 1057 1058 static void 1059 GLX_Unload(_EGLDriver *drv) 1060 { 1061 struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv); 1062 1063 if (GLX_drv->handle) 1064 dlclose(GLX_drv->handle); 1065 free(GLX_drv); 1066 } 1067 1068 1069 static EGLBoolean 1070 GLX_Load(_EGLDriver *drv) 1071 { 1072 struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv); 1073 void *handle = NULL; 1074 1075 GLX_drv->glXGetProcAddress = dlsym(RTLD_DEFAULT, "glXGetProcAddress"); 1076 if (!GLX_drv->glXGetProcAddress) 1077 GLX_drv->glXGetProcAddress = dlsym(RTLD_DEFAULT, "glXGetProcAddressARB"); 1078 if (!GLX_drv->glXGetProcAddress) { 1079 handle = dlopen("libGL.so", RTLD_LAZY | RTLD_LOCAL); 1080 if (!handle) 1081 goto fail; 1082 1083 GLX_drv->glXGetProcAddress = dlsym(handle, "glXGetProcAddress"); 1084 if (!GLX_drv->glXGetProcAddress) 1085 GLX_drv->glXGetProcAddress = dlsym(handle, "glXGetProcAddressARB"); 1086 if (!GLX_drv->glXGetProcAddress) 1087 goto fail; 1088 } 1089 1090 #define GET_PROC(proc_type, proc_name, check) \ 1091 do { \ 1092 GLX_drv->proc_name = (proc_type) \ 1093 GLX_drv->glXGetProcAddress((const GLubyte *) #proc_name); \ 1094 if (check && !GLX_drv->proc_name) goto fail; \ 1095 } while (0) 1096 1097 /* GLX 1.0 */ 1098 GET_PROC(GLXCREATECONTEXTPROC, glXCreateContext, EGL_TRUE); 1099 GET_PROC(GLXDESTROYCONTEXTPROC, glXDestroyContext, EGL_TRUE); 1100 GET_PROC(GLXMAKECURRENTPROC, glXMakeCurrent, EGL_TRUE); 1101 GET_PROC(GLXSWAPBUFFERSPROC, glXSwapBuffers, EGL_TRUE); 1102 GET_PROC(GLXCREATEGLXPIXMAPPROC, glXCreateGLXPixmap, EGL_TRUE); 1103 GET_PROC(GLXDESTROYGLXPIXMAPPROC, glXDestroyGLXPixmap, EGL_TRUE); 1104 GET_PROC(GLXQUERYVERSIONPROC, glXQueryVersion, EGL_TRUE); 1105 GET_PROC(GLXGETCONFIGPROC, glXGetConfig, EGL_TRUE); 1106 GET_PROC(GLXWAITGLPROC, glXWaitGL, EGL_TRUE); 1107 GET_PROC(GLXWAITXPROC, glXWaitX, EGL_TRUE); 1108 1109 /* GLX 1.1 */ 1110 GET_PROC(GLXQUERYEXTENSIONSSTRINGPROC, glXQueryExtensionsString, EGL_TRUE); 1111 GET_PROC(GLXQUERYSERVERSTRINGPROC, glXQueryServerString, EGL_TRUE); 1112 GET_PROC(GLXGETCLIENTSTRINGPROC, glXGetClientString, EGL_TRUE); 1113 1114 /* GLX 1.3 */ 1115 GET_PROC(PFNGLXGETFBCONFIGSPROC, glXGetFBConfigs, EGL_FALSE); 1116 GET_PROC(PFNGLXGETFBCONFIGATTRIBPROC, glXGetFBConfigAttrib, EGL_FALSE); 1117 GET_PROC(PFNGLXGETVISUALFROMFBCONFIGPROC, glXGetVisualFromFBConfig, EGL_FALSE); 1118 GET_PROC(PFNGLXCREATEWINDOWPROC, glXCreateWindow, EGL_FALSE); 1119 GET_PROC(PFNGLXDESTROYWINDOWPROC, glXDestroyWindow, EGL_FALSE); 1120 GET_PROC(PFNGLXCREATEPIXMAPPROC, glXCreatePixmap, EGL_FALSE); 1121 GET_PROC(PFNGLXDESTROYPIXMAPPROC, glXDestroyPixmap, EGL_FALSE); 1122 GET_PROC(PFNGLXCREATEPBUFFERPROC, glXCreatePbuffer, EGL_FALSE); 1123 GET_PROC(PFNGLXDESTROYPBUFFERPROC, glXDestroyPbuffer, EGL_FALSE); 1124 GET_PROC(PFNGLXCREATENEWCONTEXTPROC, glXCreateNewContext, EGL_FALSE); 1125 GET_PROC(PFNGLXMAKECONTEXTCURRENTPROC, glXMakeContextCurrent, EGL_FALSE); 1126 1127 /* GLX_SGIX_pbuffer */ 1128 GET_PROC(PFNGLXCREATEGLXPBUFFERSGIXPROC, 1129 glXCreateGLXPbufferSGIX, EGL_FALSE); 1130 GET_PROC(PFNGLXDESTROYGLXPBUFFERSGIXPROC, 1131 glXDestroyGLXPbufferSGIX, EGL_FALSE); 1132 #undef GET_PROC 1133 1134 GLX_drv->handle = handle; 1135 1136 return EGL_TRUE; 1137 1138 fail: 1139 if (handle) 1140 dlclose(handle); 1141 return EGL_FALSE; 1142 } 1143 1144 1145 /** 1146 * This is the main entrypoint into the driver, called by libEGL. 1147 * Create a new _EGLDriver object and init its dispatch table. 1148 */ 1149 _EGLDriver * 1150 _eglBuiltInDriverGLX(const char *args) 1151 { 1152 struct GLX_egl_driver *GLX_drv = CALLOC_STRUCT(GLX_egl_driver); 1153 1154 (void) args; 1155 1156 if (!GLX_drv) 1157 return NULL; 1158 1159 if (!GLX_Load(&GLX_drv->Base)) { 1160 _eglLog(_EGL_WARNING, "GLX: failed to load GLX"); 1161 free(GLX_drv); 1162 return NULL; 1163 } 1164 1165 _eglInitDriverFallbacks(&GLX_drv->Base); 1166 GLX_drv->Base.API.Initialize = GLX_eglInitialize; 1167 GLX_drv->Base.API.Terminate = GLX_eglTerminate; 1168 GLX_drv->Base.API.CreateContext = GLX_eglCreateContext; 1169 GLX_drv->Base.API.DestroyContext = GLX_eglDestroyContext; 1170 GLX_drv->Base.API.MakeCurrent = GLX_eglMakeCurrent; 1171 GLX_drv->Base.API.CreateWindowSurface = GLX_eglCreateWindowSurface; 1172 GLX_drv->Base.API.CreatePixmapSurface = GLX_eglCreatePixmapSurface; 1173 GLX_drv->Base.API.CreatePbufferSurface = GLX_eglCreatePbufferSurface; 1174 GLX_drv->Base.API.DestroySurface = GLX_eglDestroySurface; 1175 GLX_drv->Base.API.SwapBuffers = GLX_eglSwapBuffers; 1176 GLX_drv->Base.API.GetProcAddress = GLX_eglGetProcAddress; 1177 GLX_drv->Base.API.WaitClient = GLX_eglWaitClient; 1178 GLX_drv->Base.API.WaitNative = GLX_eglWaitNative; 1179 1180 GLX_drv->Base.Name = "GLX"; 1181 GLX_drv->Base.Unload = GLX_Unload; 1182 1183 return &GLX_drv->Base; 1184 } 1185