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 <xf86drm.h> 43 #include "dri_util.h" 44 #include "utils.h" 45 #include "xmlpool.h" 46 #include "../glsl/glsl_parser_extras.h" 47 48 PUBLIC const char __dri2ConfigOptions[] = 49 DRI_CONF_BEGIN 50 DRI_CONF_SECTION_PERFORMANCE 51 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1) 52 DRI_CONF_SECTION_END 53 DRI_CONF_END; 54 55 static const uint __dri2NConfigOptions = 1; 56 57 /*****************************************************************/ 58 /** \name Screen handling functions */ 59 /*****************************************************************/ 60 /*@{*/ 61 62 static void 63 setupLoaderExtensions(__DRIscreen *psp, 64 const __DRIextension **extensions) 65 { 66 int i; 67 68 for (i = 0; extensions[i]; i++) { 69 if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0) 70 psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i]; 71 if (strcmp(extensions[i]->name, __DRI_IMAGE_LOOKUP) == 0) 72 psp->dri2.image = (__DRIimageLookupExtension *) extensions[i]; 73 if (strcmp(extensions[i]->name, __DRI_USE_INVALIDATE) == 0) 74 psp->dri2.useInvalidate = (__DRIuseInvalidateExtension *) extensions[i]; 75 } 76 } 77 78 static __DRIscreen * 79 dri2CreateNewScreen(int scrn, int fd, 80 const __DRIextension **extensions, 81 const __DRIconfig ***driver_configs, void *data) 82 { 83 static const __DRIextension *emptyExtensionList[] = { NULL }; 84 __DRIscreen *psp; 85 drmVersionPtr version; 86 87 psp = calloc(1, sizeof(*psp)); 88 if (!psp) 89 return NULL; 90 91 setupLoaderExtensions(psp, extensions); 92 93 version = drmGetVersion(fd); 94 if (version) { 95 psp->drm_version.major = version->version_major; 96 psp->drm_version.minor = version->version_minor; 97 psp->drm_version.patch = version->version_patchlevel; 98 drmFreeVersion(version); 99 } 100 101 psp->loaderPrivate = data; 102 103 psp->extensions = emptyExtensionList; 104 psp->fd = fd; 105 psp->myNum = scrn; 106 107 psp->api_mask = (1 << __DRI_API_OPENGL); 108 109 *driver_configs = driDriverAPI.InitScreen(psp); 110 if (*driver_configs == NULL) { 111 free(psp); 112 return NULL; 113 } 114 115 driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions, __dri2NConfigOptions); 116 driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum, "dri2"); 117 118 return psp; 119 } 120 121 /** 122 * Destroy the per-screen private information. 123 * 124 * \internal 125 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls 126 * drmClose(), and finally frees \p screenPrivate. 127 */ 128 static void driDestroyScreen(__DRIscreen *psp) 129 { 130 if (psp) { 131 /* No interaction with the X-server is possible at this point. This 132 * routine is called after XCloseDisplay, so there is no protocol 133 * stream open to the X-server anymore. 134 */ 135 136 _mesa_destroy_shader_compiler(); 137 138 driDriverAPI.DestroyScreen(psp); 139 140 driDestroyOptionCache(&psp->optionCache); 141 driDestroyOptionInfo(&psp->optionInfo); 142 143 free(psp); 144 } 145 } 146 147 static const __DRIextension **driGetExtensions(__DRIscreen *psp) 148 { 149 return psp->extensions; 150 } 151 152 /*@}*/ 153 154 155 /*****************************************************************/ 156 /** \name Context handling functions */ 157 /*****************************************************************/ 158 /*@{*/ 159 160 static __DRIcontext * 161 dri2CreateContextAttribs(__DRIscreen *screen, int api, 162 const __DRIconfig *config, 163 __DRIcontext *shared, 164 unsigned num_attribs, 165 const uint32_t *attribs, 166 unsigned *error, 167 void *data) 168 { 169 __DRIcontext *context; 170 const struct gl_config *modes = (config != NULL) ? &config->modes : NULL; 171 void *shareCtx = (shared != NULL) ? shared->driverPrivate : NULL; 172 gl_api mesa_api; 173 unsigned major_version = 1; 174 unsigned minor_version = 0; 175 uint32_t flags = 0; 176 177 assert((num_attribs == 0) || (attribs != NULL)); 178 179 if (!(screen->api_mask & (1 << api))) { 180 *error = __DRI_CTX_ERROR_BAD_API; 181 return NULL; 182 } 183 184 switch (api) { 185 case __DRI_API_OPENGL: 186 mesa_api = API_OPENGL; 187 break; 188 case __DRI_API_GLES: 189 mesa_api = API_OPENGLES; 190 break; 191 case __DRI_API_GLES2: 192 mesa_api = API_OPENGLES2; 193 break; 194 case __DRI_API_OPENGL_CORE: 195 mesa_api = API_OPENGL_CORE; 196 break; 197 default: 198 *error = __DRI_CTX_ERROR_BAD_API; 199 return NULL; 200 } 201 202 for (unsigned i = 0; i < num_attribs; i++) { 203 switch (attribs[i * 2]) { 204 case __DRI_CTX_ATTRIB_MAJOR_VERSION: 205 major_version = attribs[i * 2 + 1]; 206 break; 207 case __DRI_CTX_ATTRIB_MINOR_VERSION: 208 minor_version = attribs[i * 2 + 1]; 209 break; 210 case __DRI_CTX_ATTRIB_FLAGS: 211 flags = attribs[i * 2 + 1]; 212 break; 213 default: 214 /* We can't create a context that satisfies the requirements of an 215 * attribute that we don't understand. Return failure. 216 */ 217 assert(!"Should not get here."); 218 *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; 219 return NULL; 220 } 221 } 222 223 /* Mesa does not support the GL_ARB_compatibilty extension or the 224 * compatibility profile. This means that we treat a API_OPENGL 3.1 as 225 * API_OPENGL_CORE and reject API_OPENGL 3.2+. 226 */ 227 if (mesa_api == API_OPENGL && major_version == 3 && minor_version == 1) 228 mesa_api = API_OPENGL_CORE; 229 230 if (mesa_api == API_OPENGL 231 && ((major_version > 3) 232 || (major_version == 3 && minor_version >= 2))) { 233 *error = __DRI_CTX_ERROR_BAD_API; 234 return NULL; 235 } 236 237 /* The EGL_KHR_create_context spec says: 238 * 239 * "Flags are only defined for OpenGL context creation, and specifying 240 * a flags value other than zero for other types of contexts, 241 * including OpenGL ES contexts, will generate an error." 242 * 243 * The GLX_EXT_create_context_es2_profile specification doesn't say 244 * anything specific about this case. However, none of the known flags 245 * have any meaning in an ES context, so this seems safe. 246 */ 247 if (mesa_api != API_OPENGL 248 && mesa_api != API_OPENGL_CORE 249 && flags != 0) { 250 *error = __DRI_CTX_ERROR_BAD_FLAG; 251 return NULL; 252 } 253 254 /* There are no forward-compatible contexts before OpenGL 3.0. The 255 * GLX_ARB_create_context spec says: 256 * 257 * "Forward-compatible contexts are defined only for OpenGL versions 258 * 3.0 and later." 259 * 260 * Forward-looking contexts are supported by silently converting the 261 * requested API to API_OPENGL_CORE. 262 * 263 * In Mesa, a debug context is the same as a regular context. 264 */ 265 if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) { 266 mesa_api = API_OPENGL_CORE; 267 } 268 269 if ((flags & ~(__DRI_CTX_FLAG_DEBUG | __DRI_CTX_FLAG_FORWARD_COMPATIBLE)) 270 != 0) { 271 *error = __DRI_CTX_ERROR_UNKNOWN_FLAG; 272 return NULL; 273 } 274 275 context = calloc(1, sizeof *context); 276 if (!context) { 277 *error = __DRI_CTX_ERROR_NO_MEMORY; 278 return NULL; 279 } 280 281 context->loaderPrivate = data; 282 283 context->driScreenPriv = screen; 284 context->driDrawablePriv = NULL; 285 context->driReadablePriv = NULL; 286 287 if (!driDriverAPI.CreateContext(mesa_api, modes, context, 288 major_version, minor_version, 289 flags, error, shareCtx) ) { 290 free(context); 291 return NULL; 292 } 293 294 *error = __DRI_CTX_ERROR_SUCCESS; 295 return context; 296 } 297 298 static __DRIcontext * 299 dri2CreateNewContextForAPI(__DRIscreen *screen, int api, 300 const __DRIconfig *config, 301 __DRIcontext *shared, void *data) 302 { 303 unsigned error; 304 305 return dri2CreateContextAttribs(screen, api, config, shared, 0, NULL, 306 &error, data); 307 } 308 309 static __DRIcontext * 310 dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config, 311 __DRIcontext *shared, void *data) 312 { 313 return dri2CreateNewContextForAPI(screen, __DRI_API_OPENGL, 314 config, shared, data); 315 } 316 317 /** 318 * Destroy the per-context private information. 319 * 320 * \internal 321 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls 322 * drmDestroyContext(), and finally frees \p contextPrivate. 323 */ 324 static void 325 driDestroyContext(__DRIcontext *pcp) 326 { 327 if (pcp) { 328 driDriverAPI.DestroyContext(pcp); 329 free(pcp); 330 } 331 } 332 333 static int 334 driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask) 335 { 336 (void) dest; 337 (void) src; 338 (void) mask; 339 return GL_FALSE; 340 } 341 342 /*@}*/ 343 344 345 /*****************************************************************/ 346 /** \name Context (un)binding functions */ 347 /*****************************************************************/ 348 /*@{*/ 349 350 static void dri_get_drawable(__DRIdrawable *pdp); 351 static void dri_put_drawable(__DRIdrawable *pdp); 352 353 /** 354 * This function takes both a read buffer and a draw buffer. This is needed 355 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent 356 * function. 357 */ 358 static int driBindContext(__DRIcontext *pcp, 359 __DRIdrawable *pdp, 360 __DRIdrawable *prp) 361 { 362 /* 363 ** Assume error checking is done properly in glXMakeCurrent before 364 ** calling driUnbindContext. 365 */ 366 367 if (!pcp) 368 return GL_FALSE; 369 370 /* Bind the drawable to the context */ 371 pcp->driDrawablePriv = pdp; 372 pcp->driReadablePriv = prp; 373 if (pdp) { 374 pdp->driContextPriv = pcp; 375 dri_get_drawable(pdp); 376 } 377 if (prp && pdp != prp) { 378 dri_get_drawable(prp); 379 } 380 381 return driDriverAPI.MakeCurrent(pcp, pdp, prp); 382 } 383 384 /** 385 * Unbind context. 386 * 387 * \param scrn the screen. 388 * \param gc context. 389 * 390 * \return \c GL_TRUE on success, or \c GL_FALSE on failure. 391 * 392 * \internal 393 * This function calls __DriverAPIRec::UnbindContext, and then decrements 394 * __DRIdrawableRec::refcount which must be non-zero for a successful 395 * return. 396 * 397 * While casting the opaque private pointers associated with the parameters 398 * into their respective real types it also assures they are not \c NULL. 399 */ 400 static int driUnbindContext(__DRIcontext *pcp) 401 { 402 __DRIdrawable *pdp; 403 __DRIdrawable *prp; 404 405 /* 406 ** Assume error checking is done properly in glXMakeCurrent before 407 ** calling driUnbindContext. 408 */ 409 410 if (pcp == NULL) 411 return GL_FALSE; 412 413 pdp = pcp->driDrawablePriv; 414 prp = pcp->driReadablePriv; 415 416 /* already unbound */ 417 if (!pdp && !prp) 418 return GL_TRUE; 419 420 driDriverAPI.UnbindContext(pcp); 421 422 assert(pdp); 423 if (pdp->refcount == 0) { 424 /* ERROR!!! */ 425 return GL_FALSE; 426 } 427 428 dri_put_drawable(pdp); 429 430 if (prp != pdp) { 431 if (prp->refcount == 0) { 432 /* ERROR!!! */ 433 return GL_FALSE; 434 } 435 436 dri_put_drawable(prp); 437 } 438 439 /* XXX this is disabled so that if we call SwapBuffers on an unbound 440 * window we can determine the last context bound to the window and 441 * use that context's lock. (BrianP, 2-Dec-2000) 442 */ 443 pcp->driDrawablePriv = NULL; 444 pcp->driReadablePriv = NULL; 445 446 return GL_TRUE; 447 } 448 449 /*@}*/ 450 451 452 static void dri_get_drawable(__DRIdrawable *pdp) 453 { 454 pdp->refcount++; 455 } 456 457 static void dri_put_drawable(__DRIdrawable *pdp) 458 { 459 if (pdp) { 460 pdp->refcount--; 461 if (pdp->refcount) 462 return; 463 464 driDriverAPI.DestroyBuffer(pdp); 465 free(pdp); 466 } 467 } 468 469 static __DRIdrawable * 470 dri2CreateNewDrawable(__DRIscreen *screen, 471 const __DRIconfig *config, 472 void *data) 473 { 474 __DRIdrawable *pdraw; 475 476 pdraw = malloc(sizeof *pdraw); 477 if (!pdraw) 478 return NULL; 479 480 pdraw->loaderPrivate = data; 481 482 pdraw->driScreenPriv = screen; 483 pdraw->driContextPriv = NULL; 484 pdraw->refcount = 0; 485 pdraw->lastStamp = 0; 486 pdraw->w = 0; 487 pdraw->h = 0; 488 489 dri_get_drawable(pdraw); 490 491 if (!driDriverAPI.CreateBuffer(screen, pdraw, &config->modes, GL_FALSE)) { 492 free(pdraw); 493 return NULL; 494 } 495 496 pdraw->dri2.stamp = pdraw->lastStamp + 1; 497 498 return pdraw; 499 } 500 501 static void 502 driDestroyDrawable(__DRIdrawable *pdp) 503 { 504 dri_put_drawable(pdp); 505 } 506 507 static __DRIbuffer * 508 dri2AllocateBuffer(__DRIscreen *screen, 509 unsigned int attachment, unsigned int format, 510 int width, int height) 511 { 512 return driDriverAPI.AllocateBuffer(screen, attachment, format, 513 width, height); 514 } 515 516 static void 517 dri2ReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer) 518 { 519 driDriverAPI.ReleaseBuffer(screen, buffer); 520 } 521 522 523 static int 524 dri2ConfigQueryb(__DRIscreen *screen, const char *var, GLboolean *val) 525 { 526 if (!driCheckOption(&screen->optionCache, var, DRI_BOOL)) 527 return -1; 528 529 *val = driQueryOptionb(&screen->optionCache, var); 530 531 return 0; 532 } 533 534 static int 535 dri2ConfigQueryi(__DRIscreen *screen, const char *var, GLint *val) 536 { 537 if (!driCheckOption(&screen->optionCache, var, DRI_INT) && 538 !driCheckOption(&screen->optionCache, var, DRI_ENUM)) 539 return -1; 540 541 *val = driQueryOptioni(&screen->optionCache, var); 542 543 return 0; 544 } 545 546 static int 547 dri2ConfigQueryf(__DRIscreen *screen, const char *var, GLfloat *val) 548 { 549 if (!driCheckOption(&screen->optionCache, var, DRI_FLOAT)) 550 return -1; 551 552 *val = driQueryOptionf(&screen->optionCache, var); 553 554 return 0; 555 } 556 557 static unsigned int 558 dri2GetAPIMask(__DRIscreen *screen) 559 { 560 return screen->api_mask; 561 } 562 563 564 /** Core interface */ 565 const __DRIcoreExtension driCoreExtension = { 566 { __DRI_CORE, __DRI_CORE_VERSION }, 567 NULL, 568 driDestroyScreen, 569 driGetExtensions, 570 driGetConfigAttrib, 571 driIndexConfigAttrib, 572 NULL, 573 driDestroyDrawable, 574 NULL, 575 NULL, 576 driCopyContext, 577 driDestroyContext, 578 driBindContext, 579 driUnbindContext 580 }; 581 582 /** DRI2 interface */ 583 const __DRIdri2Extension driDRI2Extension = { 584 { __DRI_DRI2, 3 }, 585 dri2CreateNewScreen, 586 dri2CreateNewDrawable, 587 dri2CreateNewContext, 588 dri2GetAPIMask, 589 dri2CreateNewContextForAPI, 590 dri2AllocateBuffer, 591 dri2ReleaseBuffer, 592 dri2CreateContextAttribs 593 }; 594 595 const __DRI2configQueryExtension dri2ConfigQueryExtension = { 596 { __DRI2_CONFIG_QUERY, __DRI2_CONFIG_QUERY_VERSION }, 597 dri2ConfigQueryb, 598 dri2ConfigQueryi, 599 dri2ConfigQueryf, 600 }; 601 602 void 603 dri2InvalidateDrawable(__DRIdrawable *drawable) 604 { 605 drawable->dri2.stamp++; 606 } 607 608 /** 609 * Check that the gl_framebuffer associated with dPriv is the right size. 610 * Resize the gl_framebuffer if needed. 611 * It's expected that the dPriv->driverPrivate member points to a 612 * gl_framebuffer object. 613 */ 614 void 615 driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv) 616 { 617 struct gl_framebuffer *fb = (struct gl_framebuffer *) dPriv->driverPrivate; 618 if (fb && (dPriv->w != fb->Width || dPriv->h != fb->Height)) { 619 ctx->Driver.ResizeBuffers(ctx, fb, dPriv->w, dPriv->h); 620 /* if the driver needs the hw lock for ResizeBuffers, the drawable 621 might have changed again by now */ 622 assert(fb->Width == dPriv->w); 623 assert(fb->Height == dPriv->h); 624 } 625 } 626