1/* 2 * (C) Copyright IBM Corporation 2002, 2004 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * on the rights to use, copy, modify, merge, publish, distribute, sub 9 * license, and/or sell copies of the Software, and to permit persons to whom 10 * the Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22 * USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25/** 26 * \file dri_util.c 27 * DRI utility functions. 28 * 29 * This module acts as glue between GLX and the actual hardware driver. A DRI 30 * driver doesn't really \e have to use any of this - it's optional. But, some 31 * useful stuff is done here that otherwise would have to be duplicated in most 32 * drivers. 33 * 34 * Basically, these utility functions take care of some of the dirty details of 35 * screen initialization, context creation, context binding, DRM setup, etc. 36 * 37 * These functions are compiled into each DRI driver so libGL.so knows nothing 38 * about them. 39 */ 40 41 42#include <stdbool.h> 43#include "dri_util.h" 44#include "dri_context.h" 45#include "dri_screen.h" 46#include "util/u_endian.h" 47#include "util/driconf.h" 48#include "main/framebuffer.h" 49#include "main/version.h" 50#include "main/debug_output.h" 51#include "main/errors.h" 52 53driOptionDescription __dri2ConfigOptions[] = { 54 DRI_CONF_SECTION_DEBUG 55 DRI_CONF_GLX_EXTENSION_OVERRIDE() 56 DRI_CONF_INDIRECT_GL_EXTENSION_OVERRIDE() 57 DRI_CONF_SECTION_END 58 59 DRI_CONF_SECTION_PERFORMANCE 60 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1) 61 DRI_CONF_SECTION_END 62}; 63 64/*****************************************************************/ 65/** \name Screen handling functions */ 66/*****************************************************************/ 67/*@{*/ 68 69static void 70setupLoaderExtensions(__DRIscreen *psp, 71 const __DRIextension **extensions) 72{ 73 int i; 74 75 for (i = 0; extensions[i]; i++) { 76 if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0) 77 psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i]; 78 if (strcmp(extensions[i]->name, __DRI_IMAGE_LOOKUP) == 0) 79 psp->dri2.image = (__DRIimageLookupExtension *) extensions[i]; 80 if (strcmp(extensions[i]->name, __DRI_USE_INVALIDATE) == 0) 81 psp->dri2.useInvalidate = (__DRIuseInvalidateExtension *) extensions[i]; 82 if (strcmp(extensions[i]->name, __DRI_BACKGROUND_CALLABLE) == 0) 83 psp->dri2.backgroundCallable = (__DRIbackgroundCallableExtension *) extensions[i]; 84 if (strcmp(extensions[i]->name, __DRI_SWRAST_LOADER) == 0) 85 psp->swrast_loader = (__DRIswrastLoaderExtension *) extensions[i]; 86 if (strcmp(extensions[i]->name, __DRI_IMAGE_LOADER) == 0) 87 psp->image.loader = (__DRIimageLoaderExtension *) extensions[i]; 88 if (strcmp(extensions[i]->name, __DRI_MUTABLE_RENDER_BUFFER_LOADER) == 0) 89 psp->mutableRenderBuffer.loader = (__DRImutableRenderBufferLoaderExtension *) extensions[i]; 90 if (strcmp(extensions[i]->name, __DRI_KOPPER_LOADER) == 0) 91 psp->kopper_loader = (__DRIkopperLoaderExtension *) extensions[i]; 92 } 93} 94 95/** 96 * This is the first entrypoint in the driver called by the DRI driver loader 97 * after dlopen()ing it. 98 * 99 * It's used to create global state for the driver across contexts on the same 100 * Display. 101 */ 102static __DRIscreen * 103driCreateNewScreen2(int scrn, int fd, 104 const __DRIextension **extensions, 105 const __DRIextension **driver_extensions, 106 const __DRIconfig ***driver_configs, void *data) 107{ 108 static const __DRIextension *emptyExtensionList[] = { NULL }; 109 __DRIscreen *psp; 110 111 psp = calloc(1, sizeof(*psp)); 112 if (!psp) 113 return NULL; 114 115 assert(driver_extensions); 116 for (int i = 0; driver_extensions[i]; i++) { 117 if (strcmp(driver_extensions[i]->name, __DRI_DRIVER_VTABLE) == 0) { 118 psp->driver = 119 ((__DRIDriverVtableExtension *)driver_extensions[i])->vtable; 120 } 121 } 122 123 setupLoaderExtensions(psp, extensions); 124 // dri2 drivers require working invalidate 125 if (fd != -1 && !psp->dri2.useInvalidate) { 126 free(psp); 127 return NULL; 128 } 129 130 psp->loaderPrivate = data; 131 132 psp->extensions = emptyExtensionList; 133 psp->fd = fd; 134 psp->myNum = scrn; 135 136 /* Option parsing before ->InitScreen(), as some options apply there. */ 137 driParseOptionInfo(&psp->optionInfo, 138 __dri2ConfigOptions, ARRAY_SIZE(__dri2ConfigOptions)); 139 driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum, 140 "dri2", NULL, NULL, NULL, 0, NULL, 0); 141 142 *driver_configs = psp->driver->InitScreen(psp); 143 if (*driver_configs == NULL) { 144 free(psp); 145 return NULL; 146 } 147 148 struct gl_constants consts = { 0 }; 149 gl_api api; 150 unsigned version; 151 152 api = API_OPENGLES2; 153 if (_mesa_override_gl_version_contextless(&consts, &api, &version)) 154 psp->max_gl_es2_version = version; 155 156 api = API_OPENGL_COMPAT; 157 if (_mesa_override_gl_version_contextless(&consts, &api, &version)) { 158 psp->max_gl_core_version = version; 159 if (api == API_OPENGL_COMPAT) 160 psp->max_gl_compat_version = version; 161 } 162 163 psp->api_mask = 0; 164 if (psp->max_gl_compat_version > 0) 165 psp->api_mask |= (1 << __DRI_API_OPENGL); 166 if (psp->max_gl_core_version > 0) 167 psp->api_mask |= (1 << __DRI_API_OPENGL_CORE); 168 if (psp->max_gl_es1_version > 0) 169 psp->api_mask |= (1 << __DRI_API_GLES); 170 if (psp->max_gl_es2_version > 0) 171 psp->api_mask |= (1 << __DRI_API_GLES2); 172 if (psp->max_gl_es2_version >= 30) 173 psp->api_mask |= (1 << __DRI_API_GLES3); 174 175 return psp; 176} 177 178static __DRIscreen * 179dri2CreateNewScreen(int scrn, int fd, 180 const __DRIextension **extensions, 181 const __DRIconfig ***driver_configs, void *data) 182{ 183 return driCreateNewScreen2(scrn, fd, extensions, 184 galliumdrm_driver_extensions, 185 driver_configs, data); 186} 187 188static __DRIscreen * 189swkmsCreateNewScreen(int scrn, int fd, 190 const __DRIextension **extensions, 191 const __DRIconfig ***driver_configs, void *data) 192{ 193 return driCreateNewScreen2(scrn, fd, extensions, 194 dri_swrast_kms_driver_extensions, 195 driver_configs, data); 196} 197 198/** swrast driver createNewScreen entrypoint. */ 199static __DRIscreen * 200driSWRastCreateNewScreen(int scrn, const __DRIextension **extensions, 201 const __DRIconfig ***driver_configs, void *data) 202{ 203 return driCreateNewScreen2(scrn, -1, extensions, 204 galliumsw_driver_extensions, 205 driver_configs, data); 206} 207 208static __DRIscreen * 209driSWRastCreateNewScreen2(int scrn, const __DRIextension **extensions, 210 const __DRIextension **driver_extensions, 211 const __DRIconfig ***driver_configs, void *data) 212{ 213 return driCreateNewScreen2(scrn, -1, extensions, driver_extensions, 214 driver_configs, data); 215} 216 217/** 218 * Destroy the per-screen private information. 219 * 220 * \internal 221 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls 222 * drmClose(), and finally frees \p screenPrivate. 223 */ 224static void driDestroyScreen(__DRIscreen *psp) 225{ 226 if (psp) { 227 /* No interaction with the X-server is possible at this point. This 228 * routine is called after XCloseDisplay, so there is no protocol 229 * stream open to the X-server anymore. 230 */ 231 232 psp->driver->DestroyScreen(psp); 233 234 driDestroyOptionCache(&psp->optionCache); 235 driDestroyOptionInfo(&psp->optionInfo); 236 237 free(psp); 238 } 239} 240 241static const __DRIextension **driGetExtensions(__DRIscreen *psp) 242{ 243 return psp->extensions; 244} 245 246/*@}*/ 247 248/* WARNING: HACK: Local defines to avoid pulling glx.h. 249 */ 250#define GLX_NONE 0x8000 251#define GLX_DONT_CARE 0xFFFFFFFF 252 253#define __ATTRIB(attrib, field) case attrib: *value = config->modes.field; break 254 255/** 256 * Return the value of a configuration attribute. The attribute is 257 * indicated by the index. 258 */ 259static int 260driGetConfigAttribIndex(const __DRIconfig *config, 261 unsigned int index, unsigned int *value) 262{ 263 switch (index + 1) { 264 __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits); 265 __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits); 266 __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits); 267 __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits); 268 case __DRI_ATTRIB_LEVEL: 269 case __DRI_ATTRIB_LUMINANCE_SIZE: 270 case __DRI_ATTRIB_AUX_BUFFERS: 271 *value = 0; 272 break; 273 __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits); 274 case __DRI_ATTRIB_ALPHA_MASK_SIZE: 275 /* I have no idea what this value was ever meant to mean, it's 276 * never been set to anything, just say 0. 277 */ 278 *value = 0; 279 break; 280 __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits); 281 __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits); 282 __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits); 283 __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits); 284 __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits); 285 __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits); 286 case __DRI_ATTRIB_SAMPLE_BUFFERS: 287 *value = !!config->modes.samples; 288 break; 289 __ATTRIB(__DRI_ATTRIB_SAMPLES, samples); 290 case __DRI_ATTRIB_RENDER_TYPE: 291 /* no support for color index mode */ 292 *value = __DRI_ATTRIB_RGBA_BIT; 293 if (config->modes.floatMode) 294 *value |= __DRI_ATTRIB_FLOAT_BIT; 295 break; 296 case __DRI_ATTRIB_CONFIG_CAVEAT: 297 if (config->modes.accumRedBits != 0) 298 *value = __DRI_ATTRIB_SLOW_BIT; 299 else 300 *value = 0; 301 break; 302 case __DRI_ATTRIB_CONFORMANT: 303 *value = GL_TRUE; 304 break; 305 __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode); 306 __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode); 307 case __DRI_ATTRIB_TRANSPARENT_TYPE: 308 case __DRI_ATTRIB_TRANSPARENT_INDEX_VALUE: /* horrible bc hack */ 309 *value = GLX_NONE; 310 break; 311 case __DRI_ATTRIB_TRANSPARENT_RED_VALUE: 312 case __DRI_ATTRIB_TRANSPARENT_GREEN_VALUE: 313 case __DRI_ATTRIB_TRANSPARENT_BLUE_VALUE: 314 case __DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE: 315 *value = GLX_DONT_CARE; 316 break; 317 case __DRI_ATTRIB_FLOAT_MODE: 318 *value = config->modes.floatMode; 319 break; 320 __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask); 321 __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask); 322 __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask); 323 __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask); 324 case __DRI_ATTRIB_MAX_PBUFFER_WIDTH: 325 case __DRI_ATTRIB_MAX_PBUFFER_HEIGHT: 326 case __DRI_ATTRIB_MAX_PBUFFER_PIXELS: 327 case __DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH: 328 case __DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT: 329 case __DRI_ATTRIB_VISUAL_SELECT_GROUP: 330 *value = 0; 331 break; 332 __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod); 333 case __DRI_ATTRIB_MAX_SWAP_INTERVAL: 334 *value = INT_MAX; 335 break; 336 case __DRI_ATTRIB_MIN_SWAP_INTERVAL: 337 *value = 0; 338 break; 339 case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB: 340 case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA: 341 case __DRI_ATTRIB_YINVERTED: 342 *value = GL_TRUE; 343 break; 344 case __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE: 345 *value = GL_FALSE; 346 break; 347 case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS: 348 *value = __DRI_ATTRIB_TEXTURE_1D_BIT | 349 __DRI_ATTRIB_TEXTURE_2D_BIT | 350 __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT; 351 break; 352 __ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE, sRGBCapable); 353 case __DRI_ATTRIB_MUTABLE_RENDER_BUFFER: 354 *value = GL_FALSE; 355 break; 356 __ATTRIB(__DRI_ATTRIB_RED_SHIFT, redShift); 357 __ATTRIB(__DRI_ATTRIB_GREEN_SHIFT, greenShift); 358 __ATTRIB(__DRI_ATTRIB_BLUE_SHIFT, blueShift); 359 __ATTRIB(__DRI_ATTRIB_ALPHA_SHIFT, alphaShift); 360 default: 361 /* XXX log an error or smth */ 362 return GL_FALSE; 363 } 364 365 return GL_TRUE; 366} 367 368/** 369 * Get the value of a configuration attribute. 370 * \param attrib the attribute (one of the _DRI_ATTRIB_x tokens) 371 * \param value returns the attribute's value 372 * \return 1 for success, 0 for failure 373 */ 374static int 375driGetConfigAttrib(const __DRIconfig *config, 376 unsigned int attrib, unsigned int *value) 377{ 378 return driGetConfigAttribIndex(config, attrib - 1, value); 379} 380 381/** 382 * Get a configuration attribute name and value, given an index. 383 * \param index which field of the __DRIconfig to query 384 * \param attrib returns the attribute name (one of the _DRI_ATTRIB_x tokens) 385 * \param value returns the attribute's value 386 * \return 1 for success, 0 for failure 387 */ 388static int 389driIndexConfigAttrib(const __DRIconfig *config, int index, 390 unsigned int *attrib, unsigned int *value) 391{ 392 if (driGetConfigAttribIndex(config, index, value)) { 393 *attrib = index + 1; 394 return GL_TRUE; 395 } 396 397 return GL_FALSE; 398} 399 400static bool 401validate_context_version(__DRIscreen *screen, 402 int mesa_api, 403 unsigned major_version, 404 unsigned minor_version, 405 unsigned *dri_ctx_error) 406{ 407 unsigned req_version = 10 * major_version + minor_version; 408 unsigned max_version = 0; 409 410 switch (mesa_api) { 411 case API_OPENGL_COMPAT: 412 max_version = screen->max_gl_compat_version; 413 break; 414 case API_OPENGL_CORE: 415 max_version = screen->max_gl_core_version; 416 break; 417 case API_OPENGLES: 418 max_version = screen->max_gl_es1_version; 419 break; 420 case API_OPENGLES2: 421 max_version = screen->max_gl_es2_version; 422 break; 423 default: 424 max_version = 0; 425 break; 426 } 427 428 if (max_version == 0) { 429 *dri_ctx_error = __DRI_CTX_ERROR_BAD_API; 430 return false; 431 } else if (req_version > max_version) { 432 *dri_ctx_error = __DRI_CTX_ERROR_BAD_VERSION; 433 return false; 434 } 435 436 return true; 437} 438 439/*****************************************************************/ 440/** \name Context handling functions */ 441/*****************************************************************/ 442/*@{*/ 443 444static __DRIcontext * 445driCreateContextAttribs(__DRIscreen *screen, int api, 446 const __DRIconfig *config, 447 __DRIcontext *shared, 448 unsigned num_attribs, 449 const uint32_t *attribs, 450 unsigned *error, 451 void *data) 452{ 453 __DRIcontext *context; 454 const struct gl_config *modes = (config != NULL) ? &config->modes : NULL; 455 void *shareCtx = (shared != NULL) ? shared->driverPrivate : NULL; 456 gl_api mesa_api; 457 struct __DriverContextConfig ctx_config; 458 459 ctx_config.major_version = 1; 460 ctx_config.minor_version = 0; 461 ctx_config.flags = 0; 462 ctx_config.attribute_mask = 0; 463 ctx_config.priority = __DRI_CTX_PRIORITY_MEDIUM; 464 465 assert((num_attribs == 0) || (attribs != NULL)); 466 467 if (!(screen->api_mask & (1 << api))) { 468 *error = __DRI_CTX_ERROR_BAD_API; 469 return NULL; 470 } 471 472 switch (api) { 473 case __DRI_API_OPENGL: 474 mesa_api = API_OPENGL_COMPAT; 475 break; 476 case __DRI_API_GLES: 477 mesa_api = API_OPENGLES; 478 break; 479 case __DRI_API_GLES2: 480 case __DRI_API_GLES3: 481 mesa_api = API_OPENGLES2; 482 break; 483 case __DRI_API_OPENGL_CORE: 484 mesa_api = API_OPENGL_CORE; 485 break; 486 default: 487 *error = __DRI_CTX_ERROR_BAD_API; 488 return NULL; 489 } 490 491 for (unsigned i = 0; i < num_attribs; i++) { 492 switch (attribs[i * 2]) { 493 case __DRI_CTX_ATTRIB_MAJOR_VERSION: 494 ctx_config.major_version = attribs[i * 2 + 1]; 495 break; 496 case __DRI_CTX_ATTRIB_MINOR_VERSION: 497 ctx_config.minor_version = attribs[i * 2 + 1]; 498 break; 499 case __DRI_CTX_ATTRIB_FLAGS: 500 ctx_config.flags = attribs[i * 2 + 1]; 501 break; 502 case __DRI_CTX_ATTRIB_RESET_STRATEGY: 503 if (attribs[i * 2 + 1] != __DRI_CTX_RESET_NO_NOTIFICATION) { 504 ctx_config.attribute_mask |= 505 __DRIVER_CONTEXT_ATTRIB_RESET_STRATEGY; 506 ctx_config.reset_strategy = attribs[i * 2 + 1]; 507 } else { 508 ctx_config.attribute_mask &= 509 ~__DRIVER_CONTEXT_ATTRIB_RESET_STRATEGY; 510 } 511 break; 512 case __DRI_CTX_ATTRIB_PRIORITY: 513 ctx_config.attribute_mask |= __DRIVER_CONTEXT_ATTRIB_PRIORITY; 514 ctx_config.priority = attribs[i * 2 + 1]; 515 break; 516 case __DRI_CTX_ATTRIB_RELEASE_BEHAVIOR: 517 if (attribs[i * 2 + 1] != __DRI_CTX_RELEASE_BEHAVIOR_FLUSH) { 518 ctx_config.attribute_mask |= 519 __DRIVER_CONTEXT_ATTRIB_RELEASE_BEHAVIOR; 520 ctx_config.release_behavior = attribs[i * 2 + 1]; 521 } else { 522 ctx_config.attribute_mask &= 523 ~__DRIVER_CONTEXT_ATTRIB_RELEASE_BEHAVIOR; 524 } 525 break; 526 case __DRI_CTX_ATTRIB_NO_ERROR: 527 if (attribs[i * 2 + 1] != 0) { 528 ctx_config.attribute_mask |= 529 __DRIVER_CONTEXT_ATTRIB_NO_ERROR; 530 ctx_config.no_error = attribs[i * 2 + 1]; 531 } else { 532 ctx_config.attribute_mask &= 533 ~__DRIVER_CONTEXT_ATTRIB_NO_ERROR; 534 } 535 break; 536 default: 537 /* We can't create a context that satisfies the requirements of an 538 * attribute that we don't understand. Return failure. 539 */ 540 assert(!"Should not get here."); 541 *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; 542 return NULL; 543 } 544 } 545 546 /* The specific Mesa driver may not support the GL_ARB_compatibilty 547 * extension or the compatibility profile. In that case, we treat an 548 * API_OPENGL_COMPAT 3.1 as API_OPENGL_CORE. We reject API_OPENGL_COMPAT 549 * 3.2+ in any case. 550 */ 551 if (mesa_api == API_OPENGL_COMPAT && 552 ctx_config.major_version == 3 && ctx_config.minor_version == 1 && 553 screen->max_gl_compat_version < 31) 554 mesa_api = API_OPENGL_CORE; 555 556 /* The latest version of EGL_KHR_create_context spec says: 557 * 558 * "If the EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR flag bit is set in 559 * EGL_CONTEXT_FLAGS_KHR, then a <debug context> will be created. 560 * [...] This bit is supported for OpenGL and OpenGL ES contexts. 561 * 562 * No other EGL_CONTEXT_OPENGL_*_BIT is legal for an ES context. 563 * 564 * However, Mesa's EGL layer translates the context attribute 565 * EGL_CONTEXT_OPENGL_ROBUST_ACCESS into the context flag 566 * __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS. That attribute is legal for ES 567 * (with EGL 1.5 or EGL_EXT_create_context_robustness) and GL (only with 568 * EGL 1.5). 569 * 570 * From the EGL_EXT_create_context_robustness spec: 571 * 572 * This extension is written against the OpenGL ES 2.0 Specification 573 * but can apply to OpenGL ES 1.1 and up. 574 * 575 * From the EGL 1.5 (2014.08.27) spec, p55: 576 * 577 * If the EGL_CONTEXT_OPENGL_ROBUST_ACCESS attribute is set to 578 * EGL_TRUE, a context supporting robust buffer access will be created. 579 * OpenGL contexts must support the GL_ARB_robustness extension, or 580 * equivalent core API functional- ity. OpenGL ES contexts must support 581 * the GL_EXT_robustness extension, or equivalent core API 582 * functionality. 583 */ 584 if (mesa_api != API_OPENGL_COMPAT 585 && mesa_api != API_OPENGL_CORE 586 && (ctx_config.flags & ~(__DRI_CTX_FLAG_DEBUG | 587 __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS))) { 588 *error = __DRI_CTX_ERROR_BAD_FLAG; 589 return NULL; 590 } 591 592 /* There are no forward-compatible contexts before OpenGL 3.0. The 593 * GLX_ARB_create_context spec says: 594 * 595 * "Forward-compatible contexts are defined only for OpenGL versions 596 * 3.0 and later." 597 * 598 * Forward-looking contexts are supported by silently converting the 599 * requested API to API_OPENGL_CORE. 600 * 601 * In Mesa, a debug context is the same as a regular context. 602 */ 603 if ((ctx_config.flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) { 604 mesa_api = API_OPENGL_CORE; 605 } 606 607 const uint32_t allowed_flags = (__DRI_CTX_FLAG_DEBUG 608 | __DRI_CTX_FLAG_FORWARD_COMPATIBLE 609 | __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS 610 | __DRI_CTX_FLAG_RESET_ISOLATION); 611 if (ctx_config.flags & ~allowed_flags) { 612 *error = __DRI_CTX_ERROR_UNKNOWN_FLAG; 613 return NULL; 614 } 615 616 if (!validate_context_version(screen, mesa_api, 617 ctx_config.major_version, 618 ctx_config.minor_version, 619 error)) 620 return NULL; 621 622 context = calloc(1, sizeof *context); 623 if (!context) { 624 *error = __DRI_CTX_ERROR_NO_MEMORY; 625 return NULL; 626 } 627 628 context->loaderPrivate = data; 629 630 context->driScreenPriv = screen; 631 context->driDrawablePriv = NULL; 632 context->driReadablePriv = NULL; 633 634 if (!dri_create_context(mesa_api, modes, context, &ctx_config, error, 635 shareCtx)) { 636 free(context); 637 return NULL; 638 } 639 640 *error = __DRI_CTX_ERROR_SUCCESS; 641 return context; 642} 643 644static __DRIcontext * 645driCreateNewContextForAPI(__DRIscreen *screen, int api, 646 const __DRIconfig *config, 647 __DRIcontext *shared, void *data) 648{ 649 unsigned error; 650 651 return driCreateContextAttribs(screen, api, config, shared, 0, NULL, 652 &error, data); 653} 654 655static __DRIcontext * 656driCreateNewContext(__DRIscreen *screen, const __DRIconfig *config, 657 __DRIcontext *shared, void *data) 658{ 659 return driCreateNewContextForAPI(screen, __DRI_API_OPENGL, 660 config, shared, data); 661} 662 663/** 664 * Destroy the per-context private information. 665 * 666 * \internal 667 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls 668 * drmDestroyContext(), and finally frees \p contextPrivate. 669 */ 670static void 671driDestroyContext(__DRIcontext *pcp) 672{ 673 if (pcp) { 674 dri_destroy_context(pcp); 675 free(pcp); 676 } 677} 678 679static int 680driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask) 681{ 682 (void) dest; 683 (void) src; 684 (void) mask; 685 return GL_FALSE; 686} 687 688/*@}*/ 689 690 691/*****************************************************************/ 692/** \name Context (un)binding functions */ 693/*****************************************************************/ 694/*@{*/ 695 696static void dri_get_drawable(__DRIdrawable *pdp); 697static void dri_put_drawable(__DRIdrawable *pdp); 698 699/** 700 * This function takes both a read buffer and a draw buffer. This is needed 701 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent 702 * function. 703 */ 704static int driBindContext(__DRIcontext *pcp, 705 __DRIdrawable *pdp, 706 __DRIdrawable *prp) 707{ 708 /* 709 ** Assume error checking is done properly in glXMakeCurrent before 710 ** calling driUnbindContext. 711 */ 712 713 if (!pcp) 714 return GL_FALSE; 715 716 /* Bind the drawable to the context */ 717 pcp->driDrawablePriv = pdp; 718 pcp->driReadablePriv = prp; 719 if (pdp) { 720 pdp->driContextPriv = pcp; 721 dri_get_drawable(pdp); 722 } 723 if (prp && pdp != prp) { 724 dri_get_drawable(prp); 725 } 726 727 return dri_make_current(pcp, pdp, prp); 728} 729 730/** 731 * Unbind context. 732 * 733 * \param scrn the screen. 734 * \param gc context. 735 * 736 * \return \c GL_TRUE on success, or \c GL_FALSE on failure. 737 * 738 * \internal 739 * This function calls __DriverAPIRec::UnbindContext, and then decrements 740 * __DRIdrawableRec::refcount which must be non-zero for a successful 741 * return. 742 * 743 * While casting the opaque private pointers associated with the parameters 744 * into their respective real types it also assures they are not \c NULL. 745 */ 746static int driUnbindContext(__DRIcontext *pcp) 747{ 748 __DRIdrawable *pdp; 749 __DRIdrawable *prp; 750 751 /* 752 ** Assume error checking is done properly in glXMakeCurrent before 753 ** calling driUnbindContext. 754 */ 755 756 if (pcp == NULL) 757 return GL_FALSE; 758 759 /* 760 ** Call dri_unbind_context before checking for valid drawables 761 ** to handle surfaceless contexts properly. 762 */ 763 dri_unbind_context(pcp); 764 765 pdp = pcp->driDrawablePriv; 766 prp = pcp->driReadablePriv; 767 768 /* already unbound */ 769 if (!pdp && !prp) 770 return GL_TRUE; 771 772 assert(pdp); 773 if (pdp->refcount == 0) { 774 /* ERROR!!! */ 775 return GL_FALSE; 776 } 777 778 dri_put_drawable(pdp); 779 780 if (prp != pdp) { 781 if (prp->refcount == 0) { 782 /* ERROR!!! */ 783 return GL_FALSE; 784 } 785 786 dri_put_drawable(prp); 787 } 788 789 pcp->driDrawablePriv = NULL; 790 pcp->driReadablePriv = NULL; 791 792 return GL_TRUE; 793} 794 795/*@}*/ 796 797 798static void dri_get_drawable(__DRIdrawable *pdp) 799{ 800 pdp->refcount++; 801} 802 803static void dri_put_drawable(__DRIdrawable *pdp) 804{ 805 if (pdp) { 806 pdp->refcount--; 807 if (pdp->refcount) 808 return; 809 810 pdp->driScreenPriv->driver->DestroyBuffer(pdp); 811 free(pdp); 812 } 813} 814 815static __DRIdrawable * 816driCreateNewDrawable(__DRIscreen *screen, 817 const __DRIconfig *config, 818 void *data) 819{ 820 __DRIdrawable *pdraw; 821 822 assert(data != NULL); 823 824 pdraw = malloc(sizeof *pdraw); 825 if (!pdraw) 826 return NULL; 827 828 pdraw->loaderPrivate = data; 829 830 pdraw->driScreenPriv = screen; 831 pdraw->driContextPriv = NULL; 832 pdraw->refcount = 0; 833 pdraw->lastStamp = 0; 834 pdraw->w = 0; 835 pdraw->h = 0; 836 837 dri_get_drawable(pdraw); 838 839 if (!screen->driver->CreateBuffer(screen, pdraw, &config->modes, 840 GL_FALSE)) { 841 free(pdraw); 842 return NULL; 843 } 844 845 pdraw->dri2.stamp = pdraw->lastStamp + 1; 846 847 return pdraw; 848} 849 850static void 851driDestroyDrawable(__DRIdrawable *pdp) 852{ 853 /* 854 * The loader's data structures are going away, even if pdp itself stays 855 * around for the time being because it is currently bound. This happens 856 * when a currently bound GLX pixmap is destroyed. 857 * 858 * Clear out the pointer back into the loader's data structures to avoid 859 * accessing an outdated pointer. 860 */ 861 pdp->loaderPrivate = NULL; 862 863 dri_put_drawable(pdp); 864} 865 866static __DRIbuffer * 867dri2AllocateBuffer(__DRIscreen *screen, 868 unsigned int attachment, unsigned int format, 869 int width, int height) 870{ 871 return screen->driver->AllocateBuffer(screen, attachment, format, 872 width, height); 873} 874 875static void 876dri2ReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer) 877{ 878 screen->driver->ReleaseBuffer(screen, buffer); 879} 880 881 882static int 883dri2ConfigQueryb(__DRIscreen *screen, const char *var, unsigned char *val) 884{ 885 if (!driCheckOption(&screen->optionCache, var, DRI_BOOL)) 886 return -1; 887 888 *val = driQueryOptionb(&screen->optionCache, var); 889 890 return 0; 891} 892 893static int 894dri2ConfigQueryi(__DRIscreen *screen, const char *var, int *val) 895{ 896 if (!driCheckOption(&screen->optionCache, var, DRI_INT) && 897 !driCheckOption(&screen->optionCache, var, DRI_ENUM)) 898 return -1; 899 900 *val = driQueryOptioni(&screen->optionCache, var); 901 902 return 0; 903} 904 905static int 906dri2ConfigQueryf(__DRIscreen *screen, const char *var, float *val) 907{ 908 if (!driCheckOption(&screen->optionCache, var, DRI_FLOAT)) 909 return -1; 910 911 *val = driQueryOptionf(&screen->optionCache, var); 912 913 return 0; 914} 915 916static int 917dri2ConfigQuerys(__DRIscreen *screen, const char *var, char **val) 918{ 919 if (!driCheckOption(&screen->optionCache, var, DRI_STRING)) 920 return -1; 921 922 *val = driQueryOptionstr(&screen->optionCache, var); 923 924 return 0; 925} 926 927static unsigned int 928driGetAPIMask(__DRIscreen *screen) 929{ 930 return screen->api_mask; 931} 932 933/** 934 * swrast swapbuffers entrypoint. 935 * 936 * DRI2 implements this inside the loader with only flushes handled by the 937 * driver. 938 */ 939static void 940driSwapBuffers(__DRIdrawable *pdp) 941{ 942 assert(pdp->driScreenPriv->swrast_loader); 943 944 pdp->driScreenPriv->driver->SwapBuffers(pdp); 945} 946 947/** Core interface */ 948const __DRIcoreExtension driCoreExtension = { 949 .base = { __DRI_CORE, 2 }, 950 951 .createNewScreen = NULL, 952 .destroyScreen = driDestroyScreen, 953 .getExtensions = driGetExtensions, 954 .getConfigAttrib = driGetConfigAttrib, 955 .indexConfigAttrib = driIndexConfigAttrib, 956 .createNewDrawable = NULL, 957 .destroyDrawable = driDestroyDrawable, 958 .swapBuffers = driSwapBuffers, /* swrast */ 959 .createNewContext = driCreateNewContext, /* swrast */ 960 .copyContext = driCopyContext, 961 .destroyContext = driDestroyContext, 962 .bindContext = driBindContext, 963 .unbindContext = driUnbindContext 964}; 965 966#if HAVE_DRI2 967 968/** DRI2 interface */ 969const __DRIdri2Extension driDRI2Extension = { 970 .base = { __DRI_DRI2, 4 }, 971 972 .createNewScreen = dri2CreateNewScreen, 973 .createNewDrawable = driCreateNewDrawable, 974 .createNewContext = driCreateNewContext, 975 .getAPIMask = driGetAPIMask, 976 .createNewContextForAPI = driCreateNewContextForAPI, 977 .allocateBuffer = dri2AllocateBuffer, 978 .releaseBuffer = dri2ReleaseBuffer, 979 .createContextAttribs = driCreateContextAttribs, 980 .createNewScreen2 = driCreateNewScreen2, 981}; 982 983const __DRIdri2Extension swkmsDRI2Extension = { 984 .base = { __DRI_DRI2, 4 }, 985 986 .createNewScreen = swkmsCreateNewScreen, 987 .createNewDrawable = driCreateNewDrawable, 988 .createNewContext = driCreateNewContext, 989 .getAPIMask = driGetAPIMask, 990 .createNewContextForAPI = driCreateNewContextForAPI, 991 .allocateBuffer = dri2AllocateBuffer, 992 .releaseBuffer = dri2ReleaseBuffer, 993 .createContextAttribs = driCreateContextAttribs, 994 .createNewScreen2 = driCreateNewScreen2, 995}; 996 997#endif 998 999const __DRIswrastExtension driSWRastExtension = { 1000 .base = { __DRI_SWRAST, 4 }, 1001 1002 .createNewScreen = driSWRastCreateNewScreen, 1003 .createNewDrawable = driCreateNewDrawable, 1004 .createNewContextForAPI = driCreateNewContextForAPI, 1005 .createContextAttribs = driCreateContextAttribs, 1006 .createNewScreen2 = driSWRastCreateNewScreen2, 1007}; 1008 1009const __DRI2configQueryExtension dri2ConfigQueryExtension = { 1010 .base = { __DRI2_CONFIG_QUERY, 2 }, 1011 1012 .configQueryb = dri2ConfigQueryb, 1013 .configQueryi = dri2ConfigQueryi, 1014 .configQueryf = dri2ConfigQueryf, 1015 .configQuerys = dri2ConfigQuerys, 1016}; 1017 1018const __DRI2flushControlExtension dri2FlushControlExtension = { 1019 .base = { __DRI2_FLUSH_CONTROL, 1 } 1020}; 1021 1022/* 1023 * Note: the first match is returned, which is important for formats like 1024 * __DRI_IMAGE_FORMAT_R8 which maps to both MESA_FORMAT_{R,L}_UNORM8 1025 */ 1026static const struct { 1027 uint32_t image_format; 1028 mesa_format mesa_format; 1029 GLenum internal_format; 1030} format_mapping[] = { 1031 { 1032 .image_format = __DRI_IMAGE_FORMAT_RGB565, 1033 .mesa_format = MESA_FORMAT_B5G6R5_UNORM, 1034 .internal_format = GL_RGB565, 1035 }, 1036 { 1037 .image_format = __DRI_IMAGE_FORMAT_ARGB1555, 1038 .mesa_format = MESA_FORMAT_B5G5R5A1_UNORM, 1039 .internal_format = GL_RGB5_A1, 1040 }, 1041 { 1042 .image_format = __DRI_IMAGE_FORMAT_XRGB8888, 1043 .mesa_format = MESA_FORMAT_B8G8R8X8_UNORM, 1044 .internal_format = GL_RGB8, 1045 }, 1046 { 1047 .image_format = __DRI_IMAGE_FORMAT_ABGR16161616F, 1048 .mesa_format = MESA_FORMAT_RGBA_FLOAT16, 1049 .internal_format = GL_RGBA16F, 1050 }, 1051 { 1052 .image_format = __DRI_IMAGE_FORMAT_XBGR16161616F, 1053 .mesa_format = MESA_FORMAT_RGBX_FLOAT16, 1054 .internal_format = GL_RGBA16F, 1055 }, 1056 { 1057 .image_format = __DRI_IMAGE_FORMAT_ABGR16161616, 1058 .mesa_format = MESA_FORMAT_RGBA_UNORM16, 1059 .internal_format = GL_RGBA16, 1060 }, 1061 { 1062 .image_format = __DRI_IMAGE_FORMAT_XBGR16161616, 1063 .mesa_format = MESA_FORMAT_RGBX_UNORM16, 1064 .internal_format = GL_RGBA16, 1065 }, 1066 { 1067 .image_format = __DRI_IMAGE_FORMAT_ARGB2101010, 1068 .mesa_format = MESA_FORMAT_B10G10R10A2_UNORM, 1069 .internal_format = GL_RGB10_A2, 1070 }, 1071 { 1072 .image_format = __DRI_IMAGE_FORMAT_XRGB2101010, 1073 .mesa_format = MESA_FORMAT_B10G10R10X2_UNORM, 1074 .internal_format = GL_RGB10_A2, 1075 }, 1076 { 1077 .image_format = __DRI_IMAGE_FORMAT_ABGR2101010, 1078 .mesa_format = MESA_FORMAT_R10G10B10A2_UNORM, 1079 .internal_format = GL_RGB10_A2, 1080 }, 1081 { 1082 .image_format = __DRI_IMAGE_FORMAT_XBGR2101010, 1083 .mesa_format = MESA_FORMAT_R10G10B10X2_UNORM, 1084 .internal_format = GL_RGB10_A2, 1085 }, 1086 { 1087 .image_format = __DRI_IMAGE_FORMAT_ARGB8888, 1088 .mesa_format = MESA_FORMAT_B8G8R8A8_UNORM, 1089 .internal_format = GL_RGBA8, 1090 }, 1091 { 1092 .image_format = __DRI_IMAGE_FORMAT_ABGR8888, 1093 .mesa_format = MESA_FORMAT_R8G8B8A8_UNORM, 1094 .internal_format = GL_RGBA8, 1095 }, 1096 { 1097 .image_format = __DRI_IMAGE_FORMAT_XBGR8888, 1098 .mesa_format = MESA_FORMAT_R8G8B8X8_UNORM, 1099 .internal_format = GL_RGB8, 1100 }, 1101 { 1102 .image_format = __DRI_IMAGE_FORMAT_R8, 1103 .mesa_format = MESA_FORMAT_R_UNORM8, 1104 .internal_format = GL_R8, 1105 }, 1106 { 1107 .image_format = __DRI_IMAGE_FORMAT_R8, 1108 .mesa_format = MESA_FORMAT_L_UNORM8, 1109 .internal_format = GL_R8, 1110 }, 1111#if UTIL_ARCH_LITTLE_ENDIAN 1112 { 1113 .image_format = __DRI_IMAGE_FORMAT_GR88, 1114 .mesa_format = MESA_FORMAT_RG_UNORM8, 1115 .internal_format = GL_RG8, 1116 }, 1117 { 1118 .image_format = __DRI_IMAGE_FORMAT_GR88, 1119 .mesa_format = MESA_FORMAT_LA_UNORM8, 1120 .internal_format = GL_RG8, 1121 }, 1122#endif 1123 { 1124 .image_format = __DRI_IMAGE_FORMAT_SABGR8, 1125 .mesa_format = MESA_FORMAT_R8G8B8A8_SRGB, 1126 .internal_format = GL_SRGB8_ALPHA8, 1127 }, 1128 { 1129 .image_format = __DRI_IMAGE_FORMAT_SARGB8, 1130 .mesa_format = MESA_FORMAT_B8G8R8A8_SRGB, 1131 .internal_format = GL_SRGB8_ALPHA8, 1132 }, 1133 { 1134 .image_format = __DRI_IMAGE_FORMAT_SXRGB8, 1135 .mesa_format = MESA_FORMAT_B8G8R8X8_SRGB, 1136 .internal_format = GL_SRGB8_ALPHA8, 1137 }, 1138 { 1139 .image_format = __DRI_IMAGE_FORMAT_R16, 1140 .mesa_format = MESA_FORMAT_R_UNORM16, 1141 .internal_format = GL_R16, 1142 }, 1143 { 1144 .image_format = __DRI_IMAGE_FORMAT_R16, 1145 .mesa_format = MESA_FORMAT_L_UNORM16, 1146 .internal_format = GL_R16, 1147 }, 1148#if UTIL_ARCH_LITTLE_ENDIAN 1149 { 1150 .image_format = __DRI_IMAGE_FORMAT_GR1616, 1151 .mesa_format = MESA_FORMAT_RG_UNORM16, 1152 .internal_format = GL_RG16, 1153 }, 1154 { 1155 .image_format = __DRI_IMAGE_FORMAT_GR1616, 1156 .mesa_format = MESA_FORMAT_LA_UNORM16, 1157 .internal_format = GL_RG16, 1158 }, 1159#endif 1160}; 1161 1162uint32_t 1163driGLFormatToImageFormat(mesa_format format) 1164{ 1165 for (size_t i = 0; i < ARRAY_SIZE(format_mapping); i++) 1166 if (format_mapping[i].mesa_format == format) 1167 return format_mapping[i].image_format; 1168 1169 return __DRI_IMAGE_FORMAT_NONE; 1170} 1171 1172uint32_t 1173driGLFormatToSizedInternalGLFormat(mesa_format format) 1174{ 1175 for (size_t i = 0; i < ARRAY_SIZE(format_mapping); i++) 1176 if (format_mapping[i].mesa_format == format) 1177 return format_mapping[i].internal_format; 1178 1179 return GL_NONE; 1180} 1181 1182mesa_format 1183driImageFormatToGLFormat(uint32_t image_format) 1184{ 1185 for (size_t i = 0; i < ARRAY_SIZE(format_mapping); i++) 1186 if (format_mapping[i].image_format == image_format) 1187 return format_mapping[i].mesa_format; 1188 1189 return MESA_FORMAT_NONE; 1190} 1191 1192/** Image driver interface */ 1193const __DRIimageDriverExtension driImageDriverExtension = { 1194 .base = { __DRI_IMAGE_DRIVER, 1 }, 1195 1196 .createNewScreen2 = driCreateNewScreen2, 1197 .createNewDrawable = driCreateNewDrawable, 1198 .getAPIMask = driGetAPIMask, 1199 .createContextAttribs = driCreateContextAttribs, 1200}; 1201