1 /* 2 * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 3 * Copyright 2008 Red Hat, Inc. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Soft- 7 * ware"), to deal in the Software without restriction, including without 8 * limitation the rights to use, copy, modify, merge, publish, distribute, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, provided that the above copyright 11 * notice(s) and this permission notice appear in all copies of the Soft- 12 * ware and that both the above copyright notice(s) and this permission 13 * notice appear in supporting documentation. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 17 * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY 18 * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN 19 * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- 20 * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- 23 * MANCE OF THIS SOFTWARE. 24 * 25 * Except as contained in this notice, the name of a copyright holder shall 26 * not be used in advertising or otherwise to promote the sale, use or 27 * other dealings in this Software without prior written authorization of 28 * the copyright holder. 29 * 30 * Authors: 31 * Kevin E. Martin <kevin (at) precisioninsight.com> 32 * Brian Paul <brian (at) precisioninsight.com> 33 * Kristian Hgsberg (krh (at) redhat.com) 34 */ 35 36 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 37 38 #include <unistd.h> 39 #include <dlfcn.h> 40 #include <stdarg.h> 41 #include "glxclient.h" 42 #include "dri_common.h" 43 #include "loader.h" 44 45 #ifndef RTLD_NOW 46 #define RTLD_NOW 0 47 #endif 48 #ifndef RTLD_GLOBAL 49 #define RTLD_GLOBAL 0 50 #endif 51 52 _X_HIDDEN void 53 dri_message(int level, const char *f, ...) 54 { 55 va_list args; 56 int threshold = _LOADER_WARNING; 57 const char *libgl_debug; 58 59 libgl_debug = getenv("LIBGL_DEBUG"); 60 if (libgl_debug) { 61 if (strstr(libgl_debug, "quiet")) 62 threshold = _LOADER_FATAL; 63 else if (strstr(libgl_debug, "verbose")) 64 threshold = _LOADER_DEBUG; 65 } 66 67 /* Note that the _LOADER_* levels are lower numbers for more severe. */ 68 if (level <= threshold) { 69 fprintf(stderr, "libGL%s: ", level <= _LOADER_WARNING ? " error" : ""); 70 va_start(args, f); 71 vfprintf(stderr, f, args); 72 va_end(args); 73 } 74 } 75 76 #ifndef GL_LIB_NAME 77 #define GL_LIB_NAME "libGL.so.1" 78 #endif 79 80 #ifndef DEFAULT_DRIVER_DIR 81 /* this is normally defined in Mesa/configs/default with DRI_DRIVER_SEARCH_PATH */ 82 #define DEFAULT_DRIVER_DIR "/usr/local/lib/dri" 83 #endif 84 85 /** 86 * Try to \c dlopen the named driver. 87 * 88 * This function adds the "_dri.so" suffix to the driver name and searches the 89 * directories specified by the \c LIBGL_DRIVERS_PATH environment variable in 90 * order to find the driver. 91 * 92 * \param driverName - a name like "i965", "radeon", "nouveau", etc. 93 * 94 * \returns 95 * A handle from \c dlopen, or \c NULL if driver file not found. 96 */ 97 _X_HIDDEN void * 98 driOpenDriver(const char *driverName) 99 { 100 void *glhandle, *handle; 101 const char *libPaths, *p, *next; 102 char realDriverName[200]; 103 int len; 104 105 /* Attempt to make sure libGL symbols will be visible to the driver */ 106 glhandle = dlopen(GL_LIB_NAME, RTLD_NOW | RTLD_GLOBAL); 107 108 libPaths = NULL; 109 if (geteuid() == getuid()) { 110 /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */ 111 libPaths = getenv("LIBGL_DRIVERS_PATH"); 112 if (!libPaths) 113 libPaths = getenv("LIBGL_DRIVERS_DIR"); /* deprecated */ 114 } 115 if (libPaths == NULL) 116 libPaths = DEFAULT_DRIVER_DIR; 117 118 handle = NULL; 119 for (p = libPaths; *p; p = next) { 120 next = strchr(p, ':'); 121 if (next == NULL) { 122 len = strlen(p); 123 next = p + len; 124 } 125 else { 126 len = next - p; 127 next++; 128 } 129 130 #ifdef GLX_USE_TLS 131 snprintf(realDriverName, sizeof realDriverName, 132 "%.*s/tls/%s_dri.so", len, p, driverName); 133 InfoMessageF("OpenDriver: trying %s\n", realDriverName); 134 handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL); 135 #endif 136 137 if (handle == NULL) { 138 snprintf(realDriverName, sizeof realDriverName, 139 "%.*s/%s_dri.so", len, p, driverName); 140 InfoMessageF("OpenDriver: trying %s\n", realDriverName); 141 handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL); 142 } 143 144 if (handle != NULL) 145 break; 146 else 147 InfoMessageF("dlopen %s failed (%s)\n", realDriverName, dlerror()); 148 } 149 150 if (!handle) 151 ErrorMessageF("unable to load driver: %s_dri.so\n", driverName); 152 153 if (glhandle) 154 dlclose(glhandle); 155 156 return handle; 157 } 158 159 _X_HIDDEN const __DRIextension ** 160 driGetDriverExtensions(void *handle, const char *driver_name) 161 { 162 const __DRIextension **extensions = NULL; 163 const __DRIextension **(*get_extensions)(void); 164 char *get_extensions_name = loader_get_extensions_name(driver_name); 165 166 if (get_extensions_name) { 167 get_extensions = dlsym(handle, get_extensions_name); 168 if (get_extensions) { 169 free(get_extensions_name); 170 return get_extensions(); 171 } else { 172 InfoMessageF("driver does not expose %s(): %s\n", 173 get_extensions_name, dlerror()); 174 free(get_extensions_name); 175 } 176 } 177 178 extensions = dlsym(handle, __DRI_DRIVER_EXTENSIONS); 179 if (extensions == NULL) { 180 ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); 181 return NULL; 182 } 183 184 return extensions; 185 } 186 187 static GLboolean 188 __driGetMSCRate(__DRIdrawable *draw, 189 int32_t * numerator, int32_t * denominator, 190 void *loaderPrivate) 191 { 192 __GLXDRIdrawable *glxDraw = loaderPrivate; 193 194 return __glxGetMscRate(glxDraw->psc, numerator, denominator); 195 } 196 197 _X_HIDDEN const __DRIsystemTimeExtension systemTimeExtension = { 198 .base = {__DRI_SYSTEM_TIME, 1 }, 199 200 .getUST = __glXGetUST, 201 .getMSCRate = __driGetMSCRate 202 }; 203 204 #define __ATTRIB(attrib, field) \ 205 { attrib, offsetof(struct glx_config, field) } 206 207 static const struct 208 { 209 unsigned int attrib, offset; 210 } attribMap[] = { 211 __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits), 212 __ATTRIB(__DRI_ATTRIB_LEVEL, level), 213 __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits), 214 __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits), 215 __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits), 216 __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits), 217 __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits), 218 __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits), 219 __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits), 220 __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits), 221 __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits), 222 __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits), 223 __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers), 224 __ATTRIB(__DRI_ATTRIB_SAMPLES, samples), 225 __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode), 226 __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode), 227 __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers), 228 #if 0 229 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel), 230 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentIndex), 231 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed), 232 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen), 233 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue), 234 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha), 235 __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask), 236 __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask), 237 __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask), 238 __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask), 239 #endif 240 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth), 241 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight), 242 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels), 243 __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth), 244 __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight), 245 __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod), 246 __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb), 247 __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba), 248 __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, 249 bindToMipmapTexture), 250 __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted), 251 __ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE, sRGBCapable) 252 }; 253 254 static int 255 scalarEqual(struct glx_config *mode, unsigned int attrib, unsigned int value) 256 { 257 unsigned glxValue, i; 258 259 for (i = 0; i < ARRAY_SIZE(attribMap); i++) 260 if (attribMap[i].attrib == attrib) { 261 glxValue = *(unsigned int *) ((char *) mode + attribMap[i].offset); 262 return glxValue == GLX_DONT_CARE || glxValue == value; 263 } 264 265 return GL_TRUE; /* Is a non-existing attribute equal to value? */ 266 } 267 268 static int 269 driConfigEqual(const __DRIcoreExtension *core, 270 struct glx_config *config, const __DRIconfig *driConfig) 271 { 272 unsigned int attrib, value, glxValue; 273 int i; 274 275 i = 0; 276 while (core->indexConfigAttrib(driConfig, i++, &attrib, &value)) { 277 switch (attrib) { 278 case __DRI_ATTRIB_RENDER_TYPE: 279 glxValue = 0; 280 if (value & __DRI_ATTRIB_RGBA_BIT) { 281 glxValue |= GLX_RGBA_BIT; 282 } 283 if (value & __DRI_ATTRIB_COLOR_INDEX_BIT) { 284 glxValue |= GLX_COLOR_INDEX_BIT; 285 } 286 if (value & __DRI_ATTRIB_FLOAT_BIT) { 287 glxValue |= GLX_RGBA_FLOAT_BIT_ARB; 288 } 289 if (value & __DRI_ATTRIB_UNSIGNED_FLOAT_BIT) { 290 glxValue |= GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT; 291 } 292 if (glxValue != config->renderType) 293 return GL_FALSE; 294 break; 295 296 case __DRI_ATTRIB_CONFIG_CAVEAT: 297 if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) 298 glxValue = GLX_NON_CONFORMANT_CONFIG; 299 else if (value & __DRI_ATTRIB_SLOW_BIT) 300 glxValue = GLX_SLOW_CONFIG; 301 else 302 glxValue = GLX_NONE; 303 if (glxValue != config->visualRating) 304 return GL_FALSE; 305 break; 306 307 case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS: 308 glxValue = 0; 309 if (value & __DRI_ATTRIB_TEXTURE_1D_BIT) 310 glxValue |= GLX_TEXTURE_1D_BIT_EXT; 311 if (value & __DRI_ATTRIB_TEXTURE_2D_BIT) 312 glxValue |= GLX_TEXTURE_2D_BIT_EXT; 313 if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT) 314 glxValue |= GLX_TEXTURE_RECTANGLE_BIT_EXT; 315 if (config->bindToTextureTargets != GLX_DONT_CARE && 316 glxValue != config->bindToTextureTargets) 317 return GL_FALSE; 318 break; 319 320 case __DRI_ATTRIB_SWAP_METHOD: 321 if (value == __DRI_ATTRIB_SWAP_EXCHANGE) 322 glxValue = GLX_SWAP_EXCHANGE_OML; 323 else if (value == __DRI_ATTRIB_SWAP_COPY) 324 glxValue = GLX_SWAP_COPY_OML; 325 else 326 glxValue = GLX_SWAP_UNDEFINED_OML; 327 328 if (!scalarEqual(config, attrib, glxValue)) 329 return GL_FALSE; 330 331 break; 332 333 default: 334 if (!scalarEqual(config, attrib, value)) 335 return GL_FALSE; 336 } 337 } 338 339 return GL_TRUE; 340 } 341 342 static struct glx_config * 343 createDriMode(const __DRIcoreExtension * core, 344 struct glx_config *config, const __DRIconfig **driConfigs) 345 { 346 __GLXDRIconfigPrivate *driConfig; 347 int i; 348 349 for (i = 0; driConfigs[i]; i++) { 350 if (driConfigEqual(core, config, driConfigs[i])) 351 break; 352 } 353 354 if (driConfigs[i] == NULL) 355 return NULL; 356 357 driConfig = malloc(sizeof *driConfig); 358 if (driConfig == NULL) 359 return NULL; 360 361 driConfig->base = *config; 362 driConfig->driConfig = driConfigs[i]; 363 364 return &driConfig->base; 365 } 366 367 _X_HIDDEN struct glx_config * 368 driConvertConfigs(const __DRIcoreExtension * core, 369 struct glx_config *configs, const __DRIconfig **driConfigs) 370 { 371 struct glx_config head, *tail, *m; 372 373 tail = &head; 374 head.next = NULL; 375 for (m = configs; m; m = m->next) { 376 tail->next = createDriMode(core, m, driConfigs); 377 if (tail->next == NULL) { 378 /* no matching dri config for m */ 379 continue; 380 } 381 382 383 tail = tail->next; 384 } 385 386 return head.next; 387 } 388 389 _X_HIDDEN void 390 driDestroyConfigs(const __DRIconfig **configs) 391 { 392 int i; 393 394 for (i = 0; configs[i]; i++) 395 free((__DRIconfig *) configs[i]); 396 free(configs); 397 } 398 399 static struct glx_config * 400 driInferDrawableConfig(struct glx_screen *psc, GLXDrawable draw) 401 { 402 unsigned int fbconfig = 0; 403 404 if (__glXGetDrawableAttribute(psc->dpy, draw, GLX_FBCONFIG_ID, &fbconfig)) { 405 return glx_config_find_fbconfig(psc->configs, fbconfig); 406 } 407 408 return NULL; 409 } 410 411 _X_HIDDEN __GLXDRIdrawable * 412 driFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable) 413 { 414 struct glx_display *const priv = __glXInitialize(gc->psc->dpy); 415 __GLXDRIdrawable *pdraw; 416 struct glx_screen *psc; 417 struct glx_config *config = gc->config; 418 419 if (priv == NULL) 420 return NULL; 421 422 if (glxDrawable == None) 423 return NULL; 424 425 psc = priv->screens[gc->screen]; 426 if (priv->drawHash == NULL) 427 return NULL; 428 429 if (__glxHashLookup(priv->drawHash, glxDrawable, (void *) &pdraw) == 0) { 430 pdraw->refcount ++; 431 return pdraw; 432 } 433 434 if (config == NULL) 435 config = driInferDrawableConfig(gc->psc, glxDrawable); 436 if (config == NULL) 437 return NULL; 438 439 pdraw = psc->driScreen->createDrawable(psc, glxDrawable, glxDrawable, 440 config); 441 442 if (pdraw == NULL) { 443 ErrorMessageF("failed to create drawable\n"); 444 return NULL; 445 } 446 447 if (__glxHashInsert(priv->drawHash, glxDrawable, pdraw)) { 448 (*pdraw->destroyDrawable) (pdraw); 449 return NULL; 450 } 451 pdraw->refcount = 1; 452 453 return pdraw; 454 } 455 456 _X_HIDDEN void 457 driReleaseDrawables(struct glx_context *gc) 458 { 459 const struct glx_display *priv = gc->psc->display; 460 __GLXDRIdrawable *pdraw; 461 462 if (priv == NULL) 463 return; 464 465 if (__glxHashLookup(priv->drawHash, 466 gc->currentDrawable, (void *) &pdraw) == 0) { 467 if (pdraw->drawable == pdraw->xDrawable) { 468 pdraw->refcount --; 469 if (pdraw->refcount == 0) { 470 (*pdraw->destroyDrawable)(pdraw); 471 __glxHashDelete(priv->drawHash, gc->currentDrawable); 472 } 473 } 474 } 475 476 if (__glxHashLookup(priv->drawHash, 477 gc->currentReadable, (void *) &pdraw) == 0) { 478 if (pdraw->drawable == pdraw->xDrawable) { 479 pdraw->refcount --; 480 if (pdraw->refcount == 0) { 481 (*pdraw->destroyDrawable)(pdraw); 482 __glxHashDelete(priv->drawHash, gc->currentReadable); 483 } 484 } 485 } 486 487 gc->currentDrawable = None; 488 gc->currentReadable = None; 489 490 } 491 492 _X_HIDDEN bool 493 dri2_convert_glx_attribs(unsigned num_attribs, const uint32_t *attribs, 494 unsigned *major_ver, unsigned *minor_ver, 495 uint32_t *render_type, uint32_t *flags, unsigned *api, 496 int *reset, int *release, unsigned *error) 497 { 498 unsigned i; 499 bool got_profile = false; 500 uint32_t profile; 501 502 *major_ver = 1; 503 *minor_ver = 0; 504 *render_type = GLX_RGBA_TYPE; 505 *reset = __DRI_CTX_RESET_NO_NOTIFICATION; 506 *release = __DRI_CTX_RELEASE_BEHAVIOR_FLUSH; 507 *flags = 0; 508 *api = __DRI_API_OPENGL; 509 510 if (num_attribs == 0) { 511 return true; 512 } 513 514 /* This is actually an internal error, but what the heck. 515 */ 516 if (attribs == NULL) { 517 *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; 518 return false; 519 } 520 521 for (i = 0; i < num_attribs; i++) { 522 switch (attribs[i * 2]) { 523 case GLX_CONTEXT_MAJOR_VERSION_ARB: 524 *major_ver = attribs[i * 2 + 1]; 525 break; 526 case GLX_CONTEXT_MINOR_VERSION_ARB: 527 *minor_ver = attribs[i * 2 + 1]; 528 break; 529 case GLX_CONTEXT_FLAGS_ARB: 530 *flags = attribs[i * 2 + 1]; 531 break; 532 case GLX_CONTEXT_PROFILE_MASK_ARB: 533 profile = attribs[i * 2 + 1]; 534 got_profile = true; 535 break; 536 case GLX_RENDER_TYPE: 537 *render_type = attribs[i * 2 + 1]; 538 break; 539 case GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB: 540 switch (attribs[i * 2 + 1]) { 541 case GLX_NO_RESET_NOTIFICATION_ARB: 542 *reset = __DRI_CTX_RESET_NO_NOTIFICATION; 543 break; 544 case GLX_LOSE_CONTEXT_ON_RESET_ARB: 545 *reset = __DRI_CTX_RESET_LOSE_CONTEXT; 546 break; 547 default: 548 *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; 549 return false; 550 } 551 break; 552 case GLX_CONTEXT_RELEASE_BEHAVIOR_ARB: 553 switch (attribs[i * 2 + 1]) { 554 case GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB: 555 *release = __DRI_CTX_RELEASE_BEHAVIOR_NONE; 556 break; 557 case GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB: 558 *release = __DRI_CTX_RELEASE_BEHAVIOR_FLUSH; 559 break; 560 default: 561 *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; 562 return false; 563 } 564 break; 565 default: 566 /* If an unknown attribute is received, fail. 567 */ 568 *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; 569 return false; 570 } 571 } 572 573 if (!got_profile) { 574 if (*major_ver > 3 || (*major_ver == 3 && *minor_ver >= 2)) 575 *api = __DRI_API_OPENGL_CORE; 576 } else { 577 switch (profile) { 578 case GLX_CONTEXT_CORE_PROFILE_BIT_ARB: 579 /* There are no profiles before OpenGL 3.2. The 580 * GLX_ARB_create_context_profile spec says: 581 * 582 * "If the requested OpenGL version is less than 3.2, 583 * GLX_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality 584 * of the context is determined solely by the requested version." 585 */ 586 *api = (*major_ver > 3 || (*major_ver == 3 && *minor_ver >= 2)) 587 ? __DRI_API_OPENGL_CORE : __DRI_API_OPENGL; 588 break; 589 case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB: 590 *api = __DRI_API_OPENGL; 591 break; 592 case GLX_CONTEXT_ES_PROFILE_BIT_EXT: 593 if (*major_ver >= 3) 594 *api = __DRI_API_GLES3; 595 else if (*major_ver == 2 && *minor_ver == 0) 596 *api = __DRI_API_GLES2; 597 else if (*major_ver == 1 && *minor_ver < 2) 598 *api = __DRI_API_GLES; 599 else { 600 *error = __DRI_CTX_ERROR_BAD_API; 601 return false; 602 } 603 break; 604 default: 605 *error = __DRI_CTX_ERROR_BAD_API; 606 return false; 607 } 608 } 609 610 /* Unknown flag value. 611 */ 612 if (*flags & ~(__DRI_CTX_FLAG_DEBUG | __DRI_CTX_FLAG_FORWARD_COMPATIBLE 613 | __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS)) { 614 *error = __DRI_CTX_ERROR_UNKNOWN_FLAG; 615 return false; 616 } 617 618 /* There are no forward-compatible contexts before OpenGL 3.0. The 619 * GLX_ARB_create_context spec says: 620 * 621 * "Forward-compatible contexts are defined only for OpenGL versions 622 * 3.0 and later." 623 */ 624 if (*major_ver < 3 && (*flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) { 625 *error = __DRI_CTX_ERROR_BAD_FLAG; 626 return false; 627 } 628 629 if (*major_ver >= 3 && *render_type == GLX_COLOR_INDEX_TYPE) { 630 *error = __DRI_CTX_ERROR_BAD_FLAG; 631 return false; 632 } 633 634 *error = __DRI_CTX_ERROR_SUCCESS; 635 return true; 636 } 637 638 #endif /* GLX_DIRECT_RENDERING */ 639