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 "utils.h" 45 #include "xmlpool.h" 46 #include "main/mtypes.h" 47 #include "main/framebuffer.h" 48 #include "main/version.h" 49 #include "main/debug_output.h" 50 #include "main/errors.h" 51 #include "main/macros.h" 52 53 const char __dri2ConfigOptions[] = 54 DRI_CONF_BEGIN 55 DRI_CONF_SECTION_PERFORMANCE 56 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1) 57 DRI_CONF_SECTION_END 58 DRI_CONF_END; 59 60 /*****************************************************************/ 61 /** \name Screen handling functions */ 62 /*****************************************************************/ 63 /*@{*/ 64 65 static void 66 setupLoaderExtensions(__DRIscreen *psp, 67 const __DRIextension **extensions) 68 { 69 int i; 70 71 for (i = 0; extensions[i]; i++) { 72 if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0) 73 psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i]; 74 if (strcmp(extensions[i]->name, __DRI_IMAGE_LOOKUP) == 0) 75 psp->dri2.image = (__DRIimageLookupExtension *) extensions[i]; 76 if (strcmp(extensions[i]->name, __DRI_USE_INVALIDATE) == 0) 77 psp->dri2.useInvalidate = (__DRIuseInvalidateExtension *) extensions[i]; 78 if (strcmp(extensions[i]->name, __DRI_SWRAST_LOADER) == 0) 79 psp->swrast_loader = (__DRIswrastLoaderExtension *) extensions[i]; 80 if (strcmp(extensions[i]->name, __DRI_IMAGE_LOADER) == 0) 81 psp->image.loader = (__DRIimageLoaderExtension *) extensions[i]; 82 } 83 } 84 85 /** 86 * This pointer determines which driver API we'll use in the case of the 87 * loader not passing us an explicit driver extensions list (that would, 88 * itself, contain a pointer to a driver API.) 89 * 90 * A driver's driDriverGetExtensions_drivername() can update this pointer to 91 * what it's returning, and a loader that is ignorant of createNewScreen2() 92 * will get the correct driver screen created, as long as no other 93 * driDriverGetExtensions() happened in between the first one and the 94 * createNewScreen(). 95 * 96 * This allows the X Server to not require the significant dri_interface.h 97 * updates for doing createNewScreen2(), which would discourage backporting of 98 * the X Server patches to support the new loader interface. 99 */ 100 const struct __DriverAPIRec *globalDriverAPI = &driDriverAPI; 101 102 /** 103 * This is the first entrypoint in the driver called by the DRI driver loader 104 * after dlopen()ing it. 105 * 106 * It's used to create global state for the driver across contexts on the same 107 * Display. 108 */ 109 static __DRIscreen * 110 driCreateNewScreen2(int scrn, int fd, 111 const __DRIextension **extensions, 112 const __DRIextension **driver_extensions, 113 const __DRIconfig ***driver_configs, void *data) 114 { 115 static const __DRIextension *emptyExtensionList[] = { NULL }; 116 __DRIscreen *psp; 117 118 psp = calloc(1, sizeof(*psp)); 119 if (!psp) 120 return NULL; 121 122 /* By default, use the global driDriverAPI symbol (non-megadrivers). */ 123 psp->driver = globalDriverAPI; 124 125 /* If the driver exposes its vtable through its extensions list 126 * (megadrivers), use that instead. 127 */ 128 if (driver_extensions) { 129 for (int i = 0; driver_extensions[i]; i++) { 130 if (strcmp(driver_extensions[i]->name, __DRI_DRIVER_VTABLE) == 0) { 131 psp->driver = 132 ((__DRIDriverVtableExtension *)driver_extensions[i])->vtable; 133 } 134 } 135 } 136 137 setupLoaderExtensions(psp, extensions); 138 139 psp->loaderPrivate = data; 140 141 psp->extensions = emptyExtensionList; 142 psp->fd = fd; 143 psp->myNum = scrn; 144 145 *driver_configs = psp->driver->InitScreen(psp); 146 if (*driver_configs == NULL) { 147 free(psp); 148 return NULL; 149 } 150 151 struct gl_constants consts = { 0 }; 152 gl_api api; 153 unsigned version; 154 155 api = API_OPENGLES2; 156 if (_mesa_override_gl_version_contextless(&consts, &api, &version)) 157 psp->max_gl_es2_version = version; 158 159 api = API_OPENGL_COMPAT; 160 if (_mesa_override_gl_version_contextless(&consts, &api, &version)) { 161 if (api == API_OPENGL_CORE) { 162 psp->max_gl_core_version = version; 163 } else { 164 psp->max_gl_compat_version = version; 165 } 166 } 167 168 psp->api_mask = 0; 169 if (psp->max_gl_compat_version > 0) 170 psp->api_mask |= (1 << __DRI_API_OPENGL); 171 if (psp->max_gl_core_version > 0) 172 psp->api_mask |= (1 << __DRI_API_OPENGL_CORE); 173 if (psp->max_gl_es1_version > 0) 174 psp->api_mask |= (1 << __DRI_API_GLES); 175 if (psp->max_gl_es2_version > 0) 176 psp->api_mask |= (1 << __DRI_API_GLES2); 177 if (psp->max_gl_es2_version >= 30) 178 psp->api_mask |= (1 << __DRI_API_GLES3); 179 180 driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions); 181 driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum, "dri2"); 182 183 184 return psp; 185 } 186 187 static __DRIscreen * 188 dri2CreateNewScreen(int scrn, int fd, 189 const __DRIextension **extensions, 190 const __DRIconfig ***driver_configs, void *data) 191 { 192 return driCreateNewScreen2(scrn, fd, extensions, NULL, 193 driver_configs, data); 194 } 195 196 /** swrast driver createNewScreen entrypoint. */ 197 static __DRIscreen * 198 driSWRastCreateNewScreen(int scrn, const __DRIextension **extensions, 199 const __DRIconfig ***driver_configs, void *data) 200 { 201 return driCreateNewScreen2(scrn, -1, extensions, NULL, 202 driver_configs, data); 203 } 204 205 static __DRIscreen * 206 driSWRastCreateNewScreen2(int scrn, const __DRIextension **extensions, 207 const __DRIextension **driver_extensions, 208 const __DRIconfig ***driver_configs, void *data) 209 { 210 return driCreateNewScreen2(scrn, -1, extensions, driver_extensions, 211 driver_configs, data); 212 } 213 214 /** 215 * Destroy the per-screen private information. 216 * 217 * \internal 218 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls 219 * drmClose(), and finally frees \p screenPrivate. 220 */ 221 static void driDestroyScreen(__DRIscreen *psp) 222 { 223 if (psp) { 224 /* No interaction with the X-server is possible at this point. This 225 * routine is called after XCloseDisplay, so there is no protocol 226 * stream open to the X-server anymore. 227 */ 228 229 psp->driver->DestroyScreen(psp); 230 231 driDestroyOptionCache(&psp->optionCache); 232 driDestroyOptionInfo(&psp->optionInfo); 233 234 free(psp); 235 } 236 } 237 238 static const __DRIextension **driGetExtensions(__DRIscreen *psp) 239 { 240 return psp->extensions; 241 } 242 243 /*@}*/ 244 245 246 static bool 247 validate_context_version(__DRIscreen *screen, 248 int mesa_api, 249 unsigned major_version, 250 unsigned minor_version, 251 unsigned *dri_ctx_error) 252 { 253 unsigned req_version = 10 * major_version + minor_version; 254 unsigned max_version = 0; 255 256 switch (mesa_api) { 257 case API_OPENGL_COMPAT: 258 max_version = screen->max_gl_compat_version; 259 break; 260 case API_OPENGL_CORE: 261 max_version = screen->max_gl_core_version; 262 break; 263 case API_OPENGLES: 264 max_version = screen->max_gl_es1_version; 265 break; 266 case API_OPENGLES2: 267 max_version = screen->max_gl_es2_version; 268 break; 269 default: 270 max_version = 0; 271 break; 272 } 273 274 if (max_version == 0) { 275 *dri_ctx_error = __DRI_CTX_ERROR_BAD_API; 276 return false; 277 } else if (req_version > max_version) { 278 *dri_ctx_error = __DRI_CTX_ERROR_BAD_VERSION; 279 return false; 280 } 281 282 return true; 283 } 284 285 /*****************************************************************/ 286 /** \name Context handling functions */ 287 /*****************************************************************/ 288 /*@{*/ 289 290 static __DRIcontext * 291 driCreateContextAttribs(__DRIscreen *screen, int api, 292 const __DRIconfig *config, 293 __DRIcontext *shared, 294 unsigned num_attribs, 295 const uint32_t *attribs, 296 unsigned *error, 297 void *data) 298 { 299 __DRIcontext *context; 300 const struct gl_config *modes = (config != NULL) ? &config->modes : NULL; 301 void *shareCtx = (shared != NULL) ? shared->driverPrivate : NULL; 302 gl_api mesa_api; 303 unsigned major_version = 1; 304 unsigned minor_version = 0; 305 uint32_t flags = 0; 306 bool notify_reset = false; 307 308 assert((num_attribs == 0) || (attribs != NULL)); 309 310 if (!(screen->api_mask & (1 << api))) { 311 *error = __DRI_CTX_ERROR_BAD_API; 312 return NULL; 313 } 314 315 switch (api) { 316 case __DRI_API_OPENGL: 317 mesa_api = API_OPENGL_COMPAT; 318 break; 319 case __DRI_API_GLES: 320 mesa_api = API_OPENGLES; 321 break; 322 case __DRI_API_GLES2: 323 case __DRI_API_GLES3: 324 mesa_api = API_OPENGLES2; 325 break; 326 case __DRI_API_OPENGL_CORE: 327 mesa_api = API_OPENGL_CORE; 328 break; 329 default: 330 *error = __DRI_CTX_ERROR_BAD_API; 331 return NULL; 332 } 333 334 for (unsigned i = 0; i < num_attribs; i++) { 335 switch (attribs[i * 2]) { 336 case __DRI_CTX_ATTRIB_MAJOR_VERSION: 337 major_version = attribs[i * 2 + 1]; 338 break; 339 case __DRI_CTX_ATTRIB_MINOR_VERSION: 340 minor_version = attribs[i * 2 + 1]; 341 break; 342 case __DRI_CTX_ATTRIB_FLAGS: 343 flags = attribs[i * 2 + 1]; 344 break; 345 case __DRI_CTX_ATTRIB_RESET_STRATEGY: 346 notify_reset = (attribs[i * 2 + 1] 347 != __DRI_CTX_RESET_NO_NOTIFICATION); 348 break; 349 default: 350 /* We can't create a context that satisfies the requirements of an 351 * attribute that we don't understand. Return failure. 352 */ 353 assert(!"Should not get here."); 354 *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; 355 return NULL; 356 } 357 } 358 359 /* Mesa does not support the GL_ARB_compatibilty extension or the 360 * compatibility profile. This means that we treat a API_OPENGL_COMPAT 3.1 as 361 * API_OPENGL_CORE and reject API_OPENGL_COMPAT 3.2+. 362 */ 363 if (mesa_api == API_OPENGL_COMPAT && major_version == 3 && minor_version == 1) 364 mesa_api = API_OPENGL_CORE; 365 366 if (mesa_api == API_OPENGL_COMPAT 367 && ((major_version > 3) 368 || (major_version == 3 && minor_version >= 2))) { 369 *error = __DRI_CTX_ERROR_BAD_API; 370 return NULL; 371 } 372 373 /* The latest version of EGL_KHR_create_context spec says: 374 * 375 * "If the EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR flag bit is set in 376 * EGL_CONTEXT_FLAGS_KHR, then a <debug context> will be created. 377 * [...] This bit is supported for OpenGL and OpenGL ES contexts. 378 * 379 * No other EGL_CONTEXT_OPENGL_*_BIT is legal for an ES context. 380 * 381 * However, Mesa's EGL layer translates the context attribute 382 * EGL_CONTEXT_OPENGL_ROBUST_ACCESS into the context flag 383 * __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS. That attribute is legal for ES 384 * (with EGL 1.5 or EGL_EXT_create_context_robustness) and GL (only with 385 * EGL 1.5). 386 * 387 * From the EGL_EXT_create_context_robustness spec: 388 * 389 * This extension is written against the OpenGL ES 2.0 Specification 390 * but can apply to OpenGL ES 1.1 and up. 391 * 392 * From the EGL 1.5 (2014.08.27) spec, p55: 393 * 394 * If the EGL_CONTEXT_OPENGL_ROBUST_ACCESS attribute is set to 395 * EGL_TRUE, a context supporting robust buffer access will be created. 396 * OpenGL contexts must support the GL_ARB_robustness extension, or 397 * equivalent core API functional- ity. OpenGL ES contexts must support 398 * the GL_EXT_robustness extension, or equivalent core API 399 * functionality. 400 */ 401 if (mesa_api != API_OPENGL_COMPAT 402 && mesa_api != API_OPENGL_CORE 403 && (flags & ~(__DRI_CTX_FLAG_DEBUG | 404 __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS))) { 405 *error = __DRI_CTX_ERROR_BAD_FLAG; 406 return NULL; 407 } 408 409 /* There are no forward-compatible contexts before OpenGL 3.0. The 410 * GLX_ARB_create_context spec says: 411 * 412 * "Forward-compatible contexts are defined only for OpenGL versions 413 * 3.0 and later." 414 * 415 * Forward-looking contexts are supported by silently converting the 416 * requested API to API_OPENGL_CORE. 417 * 418 * In Mesa, a debug context is the same as a regular context. 419 */ 420 if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) { 421 mesa_api = API_OPENGL_CORE; 422 } 423 424 const uint32_t allowed_flags = (__DRI_CTX_FLAG_DEBUG 425 | __DRI_CTX_FLAG_FORWARD_COMPATIBLE 426 | __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS); 427 if (flags & ~allowed_flags) { 428 *error = __DRI_CTX_ERROR_UNKNOWN_FLAG; 429 return NULL; 430 } 431 432 if (!validate_context_version(screen, mesa_api, 433 major_version, minor_version, error)) 434 return NULL; 435 436 context = calloc(1, sizeof *context); 437 if (!context) { 438 *error = __DRI_CTX_ERROR_NO_MEMORY; 439 return NULL; 440 } 441 442 context->loaderPrivate = data; 443 444 context->driScreenPriv = screen; 445 context->driDrawablePriv = NULL; 446 context->driReadablePriv = NULL; 447 448 if (!screen->driver->CreateContext(mesa_api, modes, context, 449 major_version, minor_version, 450 flags, notify_reset, error, shareCtx)) { 451 free(context); 452 return NULL; 453 } 454 455 *error = __DRI_CTX_ERROR_SUCCESS; 456 return context; 457 } 458 459 void 460 driContextSetFlags(struct gl_context *ctx, uint32_t flags) 461 { 462 if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) 463 ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; 464 if ((flags & __DRI_CTX_FLAG_DEBUG) != 0) { 465 _mesa_set_debug_state_int(ctx, GL_DEBUG_OUTPUT, GL_TRUE); 466 ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT; 467 } 468 } 469 470 static __DRIcontext * 471 driCreateNewContextForAPI(__DRIscreen *screen, int api, 472 const __DRIconfig *config, 473 __DRIcontext *shared, void *data) 474 { 475 unsigned error; 476 477 return driCreateContextAttribs(screen, api, config, shared, 0, NULL, 478 &error, data); 479 } 480 481 static __DRIcontext * 482 driCreateNewContext(__DRIscreen *screen, const __DRIconfig *config, 483 __DRIcontext *shared, void *data) 484 { 485 return driCreateNewContextForAPI(screen, __DRI_API_OPENGL, 486 config, shared, data); 487 } 488 489 /** 490 * Destroy the per-context private information. 491 * 492 * \internal 493 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls 494 * drmDestroyContext(), and finally frees \p contextPrivate. 495 */ 496 static void 497 driDestroyContext(__DRIcontext *pcp) 498 { 499 if (pcp) { 500 pcp->driScreenPriv->driver->DestroyContext(pcp); 501 free(pcp); 502 } 503 } 504 505 static int 506 driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask) 507 { 508 (void) dest; 509 (void) src; 510 (void) mask; 511 return GL_FALSE; 512 } 513 514 /*@}*/ 515 516 517 /*****************************************************************/ 518 /** \name Context (un)binding functions */ 519 /*****************************************************************/ 520 /*@{*/ 521 522 static void dri_get_drawable(__DRIdrawable *pdp); 523 static void dri_put_drawable(__DRIdrawable *pdp); 524 525 /** 526 * This function takes both a read buffer and a draw buffer. This is needed 527 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent 528 * function. 529 */ 530 static int driBindContext(__DRIcontext *pcp, 531 __DRIdrawable *pdp, 532 __DRIdrawable *prp) 533 { 534 /* 535 ** Assume error checking is done properly in glXMakeCurrent before 536 ** calling driUnbindContext. 537 */ 538 539 if (!pcp) 540 return GL_FALSE; 541 542 /* Bind the drawable to the context */ 543 pcp->driDrawablePriv = pdp; 544 pcp->driReadablePriv = prp; 545 if (pdp) { 546 pdp->driContextPriv = pcp; 547 dri_get_drawable(pdp); 548 } 549 if (prp && pdp != prp) { 550 dri_get_drawable(prp); 551 } 552 553 return pcp->driScreenPriv->driver->MakeCurrent(pcp, pdp, prp); 554 } 555 556 /** 557 * Unbind context. 558 * 559 * \param scrn the screen. 560 * \param gc context. 561 * 562 * \return \c GL_TRUE on success, or \c GL_FALSE on failure. 563 * 564 * \internal 565 * This function calls __DriverAPIRec::UnbindContext, and then decrements 566 * __DRIdrawableRec::refcount which must be non-zero for a successful 567 * return. 568 * 569 * While casting the opaque private pointers associated with the parameters 570 * into their respective real types it also assures they are not \c NULL. 571 */ 572 static int driUnbindContext(__DRIcontext *pcp) 573 { 574 __DRIdrawable *pdp; 575 __DRIdrawable *prp; 576 577 /* 578 ** Assume error checking is done properly in glXMakeCurrent before 579 ** calling driUnbindContext. 580 */ 581 582 if (pcp == NULL) 583 return GL_FALSE; 584 585 /* 586 ** Call driUnbindContext before checking for valid drawables 587 ** to handle surfaceless contexts properly. 588 */ 589 pcp->driScreenPriv->driver->UnbindContext(pcp); 590 591 pdp = pcp->driDrawablePriv; 592 prp = pcp->driReadablePriv; 593 594 /* already unbound */ 595 if (!pdp && !prp) 596 return GL_TRUE; 597 598 assert(pdp); 599 if (pdp->refcount == 0) { 600 /* ERROR!!! */ 601 return GL_FALSE; 602 } 603 604 dri_put_drawable(pdp); 605 606 if (prp != pdp) { 607 if (prp->refcount == 0) { 608 /* ERROR!!! */ 609 return GL_FALSE; 610 } 611 612 dri_put_drawable(prp); 613 } 614 615 pcp->driDrawablePriv = NULL; 616 pcp->driReadablePriv = NULL; 617 618 return GL_TRUE; 619 } 620 621 /*@}*/ 622 623 624 static void dri_get_drawable(__DRIdrawable *pdp) 625 { 626 pdp->refcount++; 627 } 628 629 static void dri_put_drawable(__DRIdrawable *pdp) 630 { 631 if (pdp) { 632 pdp->refcount--; 633 if (pdp->refcount) 634 return; 635 636 pdp->driScreenPriv->driver->DestroyBuffer(pdp); 637 free(pdp); 638 } 639 } 640 641 static __DRIdrawable * 642 driCreateNewDrawable(__DRIscreen *screen, 643 const __DRIconfig *config, 644 void *data) 645 { 646 __DRIdrawable *pdraw; 647 648 assert(data != NULL); 649 650 pdraw = malloc(sizeof *pdraw); 651 if (!pdraw) 652 return NULL; 653 654 pdraw->loaderPrivate = data; 655 656 pdraw->driScreenPriv = screen; 657 pdraw->driContextPriv = NULL; 658 pdraw->refcount = 0; 659 pdraw->lastStamp = 0; 660 pdraw->w = 0; 661 pdraw->h = 0; 662 663 dri_get_drawable(pdraw); 664 665 if (!screen->driver->CreateBuffer(screen, pdraw, &config->modes, 666 GL_FALSE)) { 667 free(pdraw); 668 return NULL; 669 } 670 671 pdraw->dri2.stamp = pdraw->lastStamp + 1; 672 673 return pdraw; 674 } 675 676 static void 677 driDestroyDrawable(__DRIdrawable *pdp) 678 { 679 /* 680 * The loader's data structures are going away, even if pdp itself stays 681 * around for the time being because it is currently bound. This happens 682 * when a currently bound GLX pixmap is destroyed. 683 * 684 * Clear out the pointer back into the loader's data structures to avoid 685 * accessing an outdated pointer. 686 */ 687 pdp->loaderPrivate = NULL; 688 689 dri_put_drawable(pdp); 690 } 691 692 static __DRIbuffer * 693 dri2AllocateBuffer(__DRIscreen *screen, 694 unsigned int attachment, unsigned int format, 695 int width, int height) 696 { 697 return screen->driver->AllocateBuffer(screen, attachment, format, 698 width, height); 699 } 700 701 static void 702 dri2ReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer) 703 { 704 screen->driver->ReleaseBuffer(screen, buffer); 705 } 706 707 708 static int 709 dri2ConfigQueryb(__DRIscreen *screen, const char *var, unsigned char *val) 710 { 711 if (!driCheckOption(&screen->optionCache, var, DRI_BOOL)) 712 return -1; 713 714 *val = driQueryOptionb(&screen->optionCache, var); 715 716 return 0; 717 } 718 719 static int 720 dri2ConfigQueryi(__DRIscreen *screen, const char *var, int *val) 721 { 722 if (!driCheckOption(&screen->optionCache, var, DRI_INT) && 723 !driCheckOption(&screen->optionCache, var, DRI_ENUM)) 724 return -1; 725 726 *val = driQueryOptioni(&screen->optionCache, var); 727 728 return 0; 729 } 730 731 static int 732 dri2ConfigQueryf(__DRIscreen *screen, const char *var, float *val) 733 { 734 if (!driCheckOption(&screen->optionCache, var, DRI_FLOAT)) 735 return -1; 736 737 *val = driQueryOptionf(&screen->optionCache, var); 738 739 return 0; 740 } 741 742 static unsigned int 743 driGetAPIMask(__DRIscreen *screen) 744 { 745 return screen->api_mask; 746 } 747 748 /** 749 * swrast swapbuffers entrypoint. 750 * 751 * DRI2 implements this inside the loader with only flushes handled by the 752 * driver. 753 */ 754 static void 755 driSwapBuffers(__DRIdrawable *pdp) 756 { 757 assert(pdp->driScreenPriv->swrast_loader); 758 759 pdp->driScreenPriv->driver->SwapBuffers(pdp); 760 } 761 762 /** Core interface */ 763 const __DRIcoreExtension driCoreExtension = { 764 .base = { __DRI_CORE, 1 }, 765 766 .createNewScreen = NULL, 767 .destroyScreen = driDestroyScreen, 768 .getExtensions = driGetExtensions, 769 .getConfigAttrib = driGetConfigAttrib, 770 .indexConfigAttrib = driIndexConfigAttrib, 771 .createNewDrawable = NULL, 772 .destroyDrawable = driDestroyDrawable, 773 .swapBuffers = driSwapBuffers, /* swrast */ 774 .createNewContext = driCreateNewContext, /* swrast */ 775 .copyContext = driCopyContext, 776 .destroyContext = driDestroyContext, 777 .bindContext = driBindContext, 778 .unbindContext = driUnbindContext 779 }; 780 781 /** DRI2 interface */ 782 const __DRIdri2Extension driDRI2Extension = { 783 .base = { __DRI_DRI2, 4 }, 784 785 .createNewScreen = dri2CreateNewScreen, 786 .createNewDrawable = driCreateNewDrawable, 787 .createNewContext = driCreateNewContext, 788 .getAPIMask = driGetAPIMask, 789 .createNewContextForAPI = driCreateNewContextForAPI, 790 .allocateBuffer = dri2AllocateBuffer, 791 .releaseBuffer = dri2ReleaseBuffer, 792 .createContextAttribs = driCreateContextAttribs, 793 .createNewScreen2 = driCreateNewScreen2, 794 }; 795 796 const __DRIswrastExtension driSWRastExtension = { 797 .base = { __DRI_SWRAST, 4 }, 798 799 .createNewScreen = driSWRastCreateNewScreen, 800 .createNewDrawable = driCreateNewDrawable, 801 .createNewContextForAPI = driCreateNewContextForAPI, 802 .createContextAttribs = driCreateContextAttribs, 803 .createNewScreen2 = driSWRastCreateNewScreen2, 804 }; 805 806 const __DRI2configQueryExtension dri2ConfigQueryExtension = { 807 .base = { __DRI2_CONFIG_QUERY, 1 }, 808 809 .configQueryb = dri2ConfigQueryb, 810 .configQueryi = dri2ConfigQueryi, 811 .configQueryf = dri2ConfigQueryf, 812 }; 813 814 void 815 dri2InvalidateDrawable(__DRIdrawable *drawable) 816 { 817 drawable->dri2.stamp++; 818 } 819 820 /** 821 * Check that the gl_framebuffer associated with dPriv is the right size. 822 * Resize the gl_framebuffer if needed. 823 * It's expected that the dPriv->driverPrivate member points to a 824 * gl_framebuffer object. 825 */ 826 void 827 driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv) 828 { 829 struct gl_framebuffer *fb = (struct gl_framebuffer *) dPriv->driverPrivate; 830 if (fb && (dPriv->w != fb->Width || dPriv->h != fb->Height)) { 831 _mesa_resize_framebuffer(ctx, fb, dPriv->w, dPriv->h); 832 /* if the driver needs the hw lock for ResizeBuffers, the drawable 833 might have changed again by now */ 834 assert(fb->Width == dPriv->w); 835 assert(fb->Height == dPriv->h); 836 } 837 } 838 839 uint32_t 840 driGLFormatToImageFormat(mesa_format format) 841 { 842 switch (format) { 843 case MESA_FORMAT_B5G6R5_UNORM: 844 return __DRI_IMAGE_FORMAT_RGB565; 845 case MESA_FORMAT_B5G5R5A1_UNORM: 846 return __DRI_IMAGE_FORMAT_ARGB1555; 847 case MESA_FORMAT_B8G8R8X8_UNORM: 848 return __DRI_IMAGE_FORMAT_XRGB8888; 849 case MESA_FORMAT_B10G10R10A2_UNORM: 850 return __DRI_IMAGE_FORMAT_ARGB2101010; 851 case MESA_FORMAT_B10G10R10X2_UNORM: 852 return __DRI_IMAGE_FORMAT_XRGB2101010; 853 case MESA_FORMAT_B8G8R8A8_UNORM: 854 return __DRI_IMAGE_FORMAT_ARGB8888; 855 case MESA_FORMAT_R8G8B8A8_UNORM: 856 return __DRI_IMAGE_FORMAT_ABGR8888; 857 case MESA_FORMAT_R8G8B8X8_UNORM: 858 return __DRI_IMAGE_FORMAT_XBGR8888; 859 case MESA_FORMAT_L_UNORM8: 860 case MESA_FORMAT_R_UNORM8: 861 return __DRI_IMAGE_FORMAT_R8; 862 case MESA_FORMAT_L8A8_UNORM: 863 case MESA_FORMAT_R8G8_UNORM: 864 return __DRI_IMAGE_FORMAT_GR88; 865 case MESA_FORMAT_NONE: 866 return __DRI_IMAGE_FORMAT_NONE; 867 case MESA_FORMAT_B8G8R8A8_SRGB: 868 return __DRI_IMAGE_FORMAT_SARGB8; 869 default: 870 return 0; 871 } 872 } 873 874 mesa_format 875 driImageFormatToGLFormat(uint32_t image_format) 876 { 877 switch (image_format) { 878 case __DRI_IMAGE_FORMAT_RGB565: 879 return MESA_FORMAT_B5G6R5_UNORM; 880 case __DRI_IMAGE_FORMAT_ARGB1555: 881 return MESA_FORMAT_B5G5R5A1_UNORM; 882 case __DRI_IMAGE_FORMAT_XRGB8888: 883 return MESA_FORMAT_B8G8R8X8_UNORM; 884 case __DRI_IMAGE_FORMAT_ARGB2101010: 885 return MESA_FORMAT_B10G10R10A2_UNORM; 886 case __DRI_IMAGE_FORMAT_XRGB2101010: 887 return MESA_FORMAT_B10G10R10X2_UNORM; 888 case __DRI_IMAGE_FORMAT_ARGB8888: 889 return MESA_FORMAT_B8G8R8A8_UNORM; 890 case __DRI_IMAGE_FORMAT_ABGR8888: 891 return MESA_FORMAT_R8G8B8A8_UNORM; 892 case __DRI_IMAGE_FORMAT_XBGR8888: 893 return MESA_FORMAT_R8G8B8X8_UNORM; 894 case __DRI_IMAGE_FORMAT_R8: 895 return MESA_FORMAT_R_UNORM8; 896 case __DRI_IMAGE_FORMAT_GR88: 897 return MESA_FORMAT_R8G8_UNORM; 898 case __DRI_IMAGE_FORMAT_SARGB8: 899 return MESA_FORMAT_B8G8R8A8_SRGB; 900 case __DRI_IMAGE_FORMAT_NONE: 901 return MESA_FORMAT_NONE; 902 default: 903 return MESA_FORMAT_NONE; 904 } 905 } 906 907 /** Image driver interface */ 908 const __DRIimageDriverExtension driImageDriverExtension = { 909 .base = { __DRI_IMAGE_DRIVER, 1 }, 910 911 .createNewScreen2 = driCreateNewScreen2, 912 .createNewDrawable = driCreateNewDrawable, 913 .getAPIMask = driGetAPIMask, 914 .createContextAttribs = driCreateContextAttribs, 915 }; 916 917 /* swrast copy sub buffer entrypoint. */ 918 static void driCopySubBuffer(__DRIdrawable *pdp, int x, int y, 919 int w, int h) 920 { 921 assert(pdp->driScreenPriv->swrast_loader); 922 923 pdp->driScreenPriv->driver->CopySubBuffer(pdp, x, y, w, h); 924 } 925 926 /* for swrast only */ 927 const __DRIcopySubBufferExtension driCopySubBufferExtension = { 928 .base = { __DRI_COPY_SUB_BUFFER, 1 }, 929 930 .copySubBuffer = driCopySubBuffer, 931 }; 932