1 /* 2 * Copyright 2008 George Sapountzis 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 */ 23 24 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 25 26 #include <X11/Xlib.h> 27 #include "glxclient.h" 28 #include <dlfcn.h> 29 #include "dri_common.h" 30 #include "drisw_priv.h" 31 32 static Bool 33 XCreateDrawable(struct drisw_drawable * pdp, 34 Display * dpy, XID drawable, int visualid) 35 { 36 XGCValues gcvalues; 37 long visMask; 38 XVisualInfo visTemp; 39 int num_visuals; 40 41 /* create GC's */ 42 pdp->gc = XCreateGC(dpy, drawable, 0, NULL); 43 pdp->swapgc = XCreateGC(dpy, drawable, 0, NULL); 44 45 gcvalues.function = GXcopy; 46 gcvalues.graphics_exposures = False; 47 XChangeGC(dpy, pdp->gc, GCFunction, &gcvalues); 48 XChangeGC(dpy, pdp->swapgc, GCFunction, &gcvalues); 49 XChangeGC(dpy, pdp->swapgc, GCGraphicsExposures, &gcvalues); 50 51 /* visual */ 52 visTemp.visualid = visualid; 53 visMask = VisualIDMask; 54 pdp->visinfo = XGetVisualInfo(dpy, visMask, &visTemp, &num_visuals); 55 56 if (!pdp->visinfo || num_visuals == 0) 57 return False; 58 59 /* create XImage */ 60 pdp->ximage = XCreateImage(dpy, 61 pdp->visinfo->visual, 62 pdp->visinfo->depth, 63 ZPixmap, 0, /* format, offset */ 64 NULL, /* data */ 65 0, 0, /* width, height */ 66 32, /* bitmap_pad */ 67 0); /* bytes_per_line */ 68 69 /** 70 * swrast does not handle 24-bit depth with 24 bpp, so let X do the 71 * the conversion for us. 72 */ 73 if (pdp->ximage->bits_per_pixel == 24) 74 pdp->ximage->bits_per_pixel = 32; 75 76 return True; 77 } 78 79 static void 80 XDestroyDrawable(struct drisw_drawable * pdp, Display * dpy, XID drawable) 81 { 82 XDestroyImage(pdp->ximage); 83 free(pdp->visinfo); 84 85 XFreeGC(dpy, pdp->gc); 86 XFreeGC(dpy, pdp->swapgc); 87 } 88 89 /** 90 * swrast loader functions 91 */ 92 93 static void 94 swrastGetDrawableInfo(__DRIdrawable * draw, 95 int *x, int *y, int *w, int *h, 96 void *loaderPrivate) 97 { 98 struct drisw_drawable *pdp = loaderPrivate; 99 __GLXDRIdrawable *pdraw = &(pdp->base); 100 Display *dpy = pdraw->psc->dpy; 101 Drawable drawable; 102 103 Window root; 104 unsigned uw, uh, bw, depth; 105 106 drawable = pdraw->xDrawable; 107 108 XGetGeometry(dpy, drawable, &root, x, y, &uw, &uh, &bw, &depth); 109 *w = uw; 110 *h = uh; 111 } 112 113 /** 114 * Align renderbuffer pitch. 115 * 116 * This should be chosen by the driver and the loader (libGL, xserver/glx) 117 * should use the driver provided pitch. 118 * 119 * It seems that the xorg loader (that is the xserver loading swrast_dri for 120 * indirect rendering, not client-side libGL) requires that the pitch is 121 * exactly the image width padded to 32 bits. XXX 122 * 123 * The above restriction can probably be overcome by using ScratchPixmap and 124 * CopyArea in the xserver, similar to ShmPutImage, and setting the width of 125 * the scratch pixmap to 'pitch / cpp'. 126 */ 127 static inline int 128 bytes_per_line(unsigned pitch_bits, unsigned mul) 129 { 130 unsigned mask = mul - 1; 131 132 return ((pitch_bits + mask) & ~mask) / 8; 133 } 134 135 static void 136 swrastPutImage2(__DRIdrawable * draw, int op, 137 int x, int y, int w, int h, int stride, 138 char *data, void *loaderPrivate) 139 { 140 struct drisw_drawable *pdp = loaderPrivate; 141 __GLXDRIdrawable *pdraw = &(pdp->base); 142 Display *dpy = pdraw->psc->dpy; 143 Drawable drawable; 144 XImage *ximage; 145 GC gc; 146 147 switch (op) { 148 case __DRI_SWRAST_IMAGE_OP_DRAW: 149 gc = pdp->gc; 150 break; 151 case __DRI_SWRAST_IMAGE_OP_SWAP: 152 gc = pdp->swapgc; 153 break; 154 default: 155 return; 156 } 157 158 drawable = pdraw->xDrawable; 159 160 ximage = pdp->ximage; 161 ximage->data = data; 162 ximage->width = w; 163 ximage->height = h; 164 ximage->bytes_per_line = stride ? stride : bytes_per_line(w * ximage->bits_per_pixel, 32); 165 166 XPutImage(dpy, drawable, gc, ximage, 0, 0, x, y, w, h); 167 168 ximage->data = NULL; 169 } 170 171 static void 172 swrastPutImage(__DRIdrawable * draw, int op, 173 int x, int y, int w, int h, 174 char *data, void *loaderPrivate) 175 { 176 swrastPutImage2(draw, op, x, y, w, h, 0, data, loaderPrivate); 177 } 178 179 static void 180 swrastGetImage2(__DRIdrawable * read, 181 int x, int y, int w, int h, int stride, 182 char *data, void *loaderPrivate) 183 { 184 struct drisw_drawable *prp = loaderPrivate; 185 __GLXDRIdrawable *pread = &(prp->base); 186 Display *dpy = pread->psc->dpy; 187 Drawable readable; 188 XImage *ximage; 189 190 readable = pread->xDrawable; 191 192 ximage = prp->ximage; 193 ximage->data = data; 194 ximage->width = w; 195 ximage->height = h; 196 ximage->bytes_per_line = stride ? stride : bytes_per_line(w * ximage->bits_per_pixel, 32); 197 198 XGetSubImage(dpy, readable, x, y, w, h, ~0L, ZPixmap, ximage, 0, 0); 199 200 ximage->data = NULL; 201 } 202 203 static void 204 swrastGetImage(__DRIdrawable * read, 205 int x, int y, int w, int h, 206 char *data, void *loaderPrivate) 207 { 208 swrastGetImage2(read, x, y, w, h, 0, data, loaderPrivate); 209 } 210 211 static const __DRIswrastLoaderExtension swrastLoaderExtension = { 212 .base = {__DRI_SWRAST_LOADER, 3 }, 213 214 .getDrawableInfo = swrastGetDrawableInfo, 215 .putImage = swrastPutImage, 216 .getImage = swrastGetImage, 217 .putImage2 = swrastPutImage2, 218 .getImage2 = swrastGetImage2, 219 }; 220 221 static const __DRIextension *loader_extensions[] = { 222 &swrastLoaderExtension.base, 223 NULL 224 }; 225 226 /** 227 * GLXDRI functions 228 */ 229 230 static void 231 drisw_destroy_context(struct glx_context *context) 232 { 233 struct drisw_context *pcp = (struct drisw_context *) context; 234 struct drisw_screen *psc = (struct drisw_screen *) context->psc; 235 236 driReleaseDrawables(&pcp->base); 237 238 free((char *) context->extensions); 239 240 (*psc->core->destroyContext) (pcp->driContext); 241 242 free(pcp); 243 } 244 245 static int 246 drisw_bind_context(struct glx_context *context, struct glx_context *old, 247 GLXDrawable draw, GLXDrawable read) 248 { 249 struct drisw_context *pcp = (struct drisw_context *) context; 250 struct drisw_screen *psc = (struct drisw_screen *) pcp->base.psc; 251 struct drisw_drawable *pdraw, *pread; 252 253 pdraw = (struct drisw_drawable *) driFetchDrawable(context, draw); 254 pread = (struct drisw_drawable *) driFetchDrawable(context, read); 255 256 driReleaseDrawables(&pcp->base); 257 258 if ((*psc->core->bindContext) (pcp->driContext, 259 pdraw ? pdraw->driDrawable : NULL, 260 pread ? pread->driDrawable : NULL)) 261 return Success; 262 263 return GLXBadContext; 264 } 265 266 static void 267 drisw_unbind_context(struct glx_context *context, struct glx_context *new) 268 { 269 struct drisw_context *pcp = (struct drisw_context *) context; 270 struct drisw_screen *psc = (struct drisw_screen *) pcp->base.psc; 271 272 (*psc->core->unbindContext) (pcp->driContext); 273 } 274 275 static void 276 drisw_bind_tex_image(Display * dpy, 277 GLXDrawable drawable, 278 int buffer, const int *attrib_list) 279 { 280 struct glx_context *gc = __glXGetCurrentContext(); 281 struct drisw_context *pcp = (struct drisw_context *) gc; 282 __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable); 283 struct drisw_drawable *pdraw = (struct drisw_drawable *) base; 284 struct drisw_screen *psc; 285 286 __glXInitialize(dpy); 287 288 if (pdraw != NULL) { 289 psc = (struct drisw_screen *) base->psc; 290 291 if (!psc->texBuffer) 292 return; 293 294 if (psc->texBuffer->base.version >= 2 && 295 psc->texBuffer->setTexBuffer2 != NULL) { 296 (*psc->texBuffer->setTexBuffer2) (pcp->driContext, 297 pdraw->base.textureTarget, 298 pdraw->base.textureFormat, 299 pdraw->driDrawable); 300 } 301 else { 302 (*psc->texBuffer->setTexBuffer) (pcp->driContext, 303 pdraw->base.textureTarget, 304 pdraw->driDrawable); 305 } 306 } 307 } 308 309 static void 310 drisw_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer) 311 { 312 struct glx_context *gc = __glXGetCurrentContext(); 313 struct drisw_context *pcp = (struct drisw_context *) gc; 314 __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable); 315 struct glx_display *dpyPriv = __glXInitialize(dpy); 316 struct drisw_drawable *pdraw = (struct drisw_drawable *) base; 317 struct drisw_screen *psc; 318 319 if (dpyPriv != NULL && pdraw != NULL) { 320 psc = (struct drisw_screen *) base->psc; 321 322 if (!psc->texBuffer) 323 return; 324 325 if (psc->texBuffer->base.version >= 3 && 326 psc->texBuffer->releaseTexBuffer != NULL) { 327 (*psc->texBuffer->releaseTexBuffer) (pcp->driContext, 328 pdraw->base.textureTarget, 329 pdraw->driDrawable); 330 } 331 } 332 } 333 334 static const struct glx_context_vtable drisw_context_vtable = { 335 .destroy = drisw_destroy_context, 336 .bind = drisw_bind_context, 337 .unbind = drisw_unbind_context, 338 .wait_gl = NULL, 339 .wait_x = NULL, 340 .use_x_font = DRI_glXUseXFont, 341 .bind_tex_image = drisw_bind_tex_image, 342 .release_tex_image = drisw_release_tex_image, 343 .get_proc_address = NULL, 344 }; 345 346 static struct glx_context * 347 drisw_create_context(struct glx_screen *base, 348 struct glx_config *config_base, 349 struct glx_context *shareList, int renderType) 350 { 351 struct drisw_context *pcp, *pcp_shared; 352 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base; 353 struct drisw_screen *psc = (struct drisw_screen *) base; 354 __DRIcontext *shared = NULL; 355 356 if (!psc->base.driScreen) 357 return NULL; 358 359 /* Check the renderType value */ 360 if (!validate_renderType_against_config(config_base, renderType)) 361 return NULL; 362 363 if (shareList) { 364 /* If the shareList context is not a DRISW context, we cannot possibly 365 * create a DRISW context that shares it. 366 */ 367 if (shareList->vtable->destroy != drisw_destroy_context) { 368 return NULL; 369 } 370 371 pcp_shared = (struct drisw_context *) shareList; 372 shared = pcp_shared->driContext; 373 } 374 375 pcp = calloc(1, sizeof *pcp); 376 if (pcp == NULL) 377 return NULL; 378 379 if (!glx_context_init(&pcp->base, &psc->base, &config->base)) { 380 free(pcp); 381 return NULL; 382 } 383 384 pcp->base.renderType = renderType; 385 386 pcp->driContext = 387 (*psc->core->createNewContext) (psc->driScreen, 388 config->driConfig, shared, pcp); 389 if (pcp->driContext == NULL) { 390 free(pcp); 391 return NULL; 392 } 393 394 pcp->base.vtable = &drisw_context_vtable; 395 396 return &pcp->base; 397 } 398 399 static struct glx_context * 400 drisw_create_context_attribs(struct glx_screen *base, 401 struct glx_config *config_base, 402 struct glx_context *shareList, 403 unsigned num_attribs, 404 const uint32_t *attribs, 405 unsigned *error) 406 { 407 struct drisw_context *pcp, *pcp_shared; 408 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base; 409 struct drisw_screen *psc = (struct drisw_screen *) base; 410 __DRIcontext *shared = NULL; 411 412 uint32_t minor_ver; 413 uint32_t major_ver; 414 uint32_t renderType; 415 uint32_t flags; 416 unsigned api; 417 int reset; 418 int release; 419 uint32_t ctx_attribs[2 * 5]; 420 unsigned num_ctx_attribs = 0; 421 422 if (!psc->base.driScreen) 423 return NULL; 424 425 if (psc->swrast->base.version < 3) 426 return NULL; 427 428 /* Remap the GLX tokens to DRI2 tokens. 429 */ 430 if (!dri2_convert_glx_attribs(num_attribs, attribs, 431 &major_ver, &minor_ver, &renderType, &flags, 432 &api, &reset, &release, error)) 433 return NULL; 434 435 /* Check the renderType value */ 436 if (!validate_renderType_against_config(config_base, renderType)) { 437 return NULL; 438 } 439 440 if (reset != __DRI_CTX_RESET_NO_NOTIFICATION) 441 return NULL; 442 443 if (release != __DRI_CTX_RELEASE_BEHAVIOR_FLUSH && 444 release != __DRI_CTX_RELEASE_BEHAVIOR_NONE) 445 return NULL; 446 447 if (shareList) { 448 pcp_shared = (struct drisw_context *) shareList; 449 shared = pcp_shared->driContext; 450 } 451 452 pcp = calloc(1, sizeof *pcp); 453 if (pcp == NULL) 454 return NULL; 455 456 if (!glx_context_init(&pcp->base, &psc->base, config_base)) { 457 free(pcp); 458 return NULL; 459 } 460 461 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION; 462 ctx_attribs[num_ctx_attribs++] = major_ver; 463 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION; 464 ctx_attribs[num_ctx_attribs++] = minor_ver; 465 if (release != __DRI_CTX_RELEASE_BEHAVIOR_FLUSH) { 466 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_RELEASE_BEHAVIOR; 467 ctx_attribs[num_ctx_attribs++] = release; 468 } 469 470 if (flags != 0) { 471 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS; 472 473 /* The current __DRI_CTX_FLAG_* values are identical to the 474 * GLX_CONTEXT_*_BIT values. 475 */ 476 ctx_attribs[num_ctx_attribs++] = flags; 477 } 478 479 pcp->base.renderType = renderType; 480 481 pcp->driContext = 482 (*psc->swrast->createContextAttribs) (psc->driScreen, 483 api, 484 config ? config->driConfig : 0, 485 shared, 486 num_ctx_attribs / 2, 487 ctx_attribs, 488 error, 489 pcp); 490 if (pcp->driContext == NULL) { 491 free(pcp); 492 return NULL; 493 } 494 495 pcp->base.vtable = &drisw_context_vtable; 496 497 return &pcp->base; 498 } 499 500 static void 501 driswDestroyDrawable(__GLXDRIdrawable * pdraw) 502 { 503 struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw; 504 struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc; 505 506 (*psc->core->destroyDrawable) (pdp->driDrawable); 507 508 XDestroyDrawable(pdp, pdraw->psc->dpy, pdraw->drawable); 509 free(pdp); 510 } 511 512 static __GLXDRIdrawable * 513 driswCreateDrawable(struct glx_screen *base, XID xDrawable, 514 GLXDrawable drawable, struct glx_config *modes) 515 { 516 struct drisw_drawable *pdp; 517 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes; 518 struct drisw_screen *psc = (struct drisw_screen *) base; 519 Bool ret; 520 const __DRIswrastExtension *swrast = psc->swrast; 521 522 pdp = calloc(1, sizeof(*pdp)); 523 if (!pdp) 524 return NULL; 525 526 pdp->base.xDrawable = xDrawable; 527 pdp->base.drawable = drawable; 528 pdp->base.psc = &psc->base; 529 530 ret = XCreateDrawable(pdp, psc->base.dpy, xDrawable, modes->visualID); 531 if (!ret) { 532 free(pdp); 533 return NULL; 534 } 535 536 /* Create a new drawable */ 537 pdp->driDrawable = 538 (*swrast->createNewDrawable) (psc->driScreen, config->driConfig, pdp); 539 540 if (!pdp->driDrawable) { 541 XDestroyDrawable(pdp, psc->base.dpy, xDrawable); 542 free(pdp); 543 return NULL; 544 } 545 546 pdp->base.destroyDrawable = driswDestroyDrawable; 547 548 return &pdp->base; 549 } 550 551 static int64_t 552 driswSwapBuffers(__GLXDRIdrawable * pdraw, 553 int64_t target_msc, int64_t divisor, int64_t remainder, 554 Bool flush) 555 { 556 struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw; 557 struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc; 558 559 (void) target_msc; 560 (void) divisor; 561 (void) remainder; 562 563 if (flush) { 564 glFlush(); 565 } 566 567 (*psc->core->swapBuffers) (pdp->driDrawable); 568 569 return 0; 570 } 571 572 static void 573 driswCopySubBuffer(__GLXDRIdrawable * pdraw, 574 int x, int y, int width, int height, Bool flush) 575 { 576 struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw; 577 struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc; 578 579 if (flush) { 580 glFlush(); 581 } 582 583 (*psc->copySubBuffer->copySubBuffer) (pdp->driDrawable, 584 x, y, width, height); 585 } 586 587 static void 588 driswDestroyScreen(struct glx_screen *base) 589 { 590 struct drisw_screen *psc = (struct drisw_screen *) base; 591 592 /* Free the direct rendering per screen data */ 593 (*psc->core->destroyScreen) (psc->driScreen); 594 driDestroyConfigs(psc->driver_configs); 595 psc->driScreen = NULL; 596 if (psc->driver) 597 dlclose(psc->driver); 598 free(psc); 599 } 600 601 #define SWRAST_DRIVER_NAME "swrast" 602 603 static void * 604 driOpenSwrast(void) 605 { 606 void *driver = NULL; 607 608 if (driver == NULL) 609 driver = driOpenDriver(SWRAST_DRIVER_NAME); 610 611 return driver; 612 } 613 614 static const struct glx_screen_vtable drisw_screen_vtable = { 615 .create_context = drisw_create_context, 616 .create_context_attribs = drisw_create_context_attribs, 617 .query_renderer_integer = drisw_query_renderer_integer, 618 .query_renderer_string = drisw_query_renderer_string, 619 }; 620 621 static void 622 driswBindExtensions(struct drisw_screen *psc, const __DRIextension **extensions) 623 { 624 int i; 625 626 __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read"); 627 628 if (psc->swrast->base.version >= 3) { 629 __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context"); 630 __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context_profile"); 631 632 /* DRISW version >= 2 implies support for OpenGL ES. 633 */ 634 __glXEnableDirectExtension(&psc->base, 635 "GLX_EXT_create_context_es_profile"); 636 __glXEnableDirectExtension(&psc->base, 637 "GLX_EXT_create_context_es2_profile"); 638 } 639 640 if (psc->copySubBuffer) 641 __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer"); 642 643 /* FIXME: Figure out what other extensions can be ported here from dri2. */ 644 for (i = 0; extensions[i]; i++) { 645 if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) { 646 psc->texBuffer = (__DRItexBufferExtension *) extensions[i]; 647 __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap"); 648 } 649 /* DRISW version 3 is also required because GLX_MESA_query_renderer 650 * requires GLX_ARB_create_context_profile. 651 */ 652 if (psc->swrast->base.version >= 3 653 && strcmp(extensions[i]->name, __DRI2_RENDERER_QUERY) == 0) { 654 psc->rendererQuery = (__DRI2rendererQueryExtension *) extensions[i]; 655 __glXEnableDirectExtension(&psc->base, "GLX_MESA_query_renderer"); 656 } 657 if (strcmp(extensions[i]->name, __DRI2_FLUSH_CONTROL) == 0) { 658 __glXEnableDirectExtension(&psc->base, 659 "GLX_ARB_context_flush_control"); 660 } 661 } 662 } 663 664 static struct glx_screen * 665 driswCreateScreen(int screen, struct glx_display *priv) 666 { 667 __GLXDRIscreen *psp; 668 const __DRIconfig **driver_configs; 669 const __DRIextension **extensions; 670 struct drisw_screen *psc; 671 struct glx_config *configs = NULL, *visuals = NULL; 672 int i; 673 674 psc = calloc(1, sizeof *psc); 675 if (psc == NULL) 676 return NULL; 677 678 if (!glx_screen_init(&psc->base, screen, priv)) { 679 free(psc); 680 return NULL; 681 } 682 683 psc->driver = driOpenSwrast(); 684 if (psc->driver == NULL) 685 goto handle_error; 686 687 extensions = driGetDriverExtensions(psc->driver, SWRAST_DRIVER_NAME); 688 if (extensions == NULL) 689 goto handle_error; 690 691 for (i = 0; extensions[i]; i++) { 692 if (strcmp(extensions[i]->name, __DRI_CORE) == 0) 693 psc->core = (__DRIcoreExtension *) extensions[i]; 694 if (strcmp(extensions[i]->name, __DRI_SWRAST) == 0) 695 psc->swrast = (__DRIswrastExtension *) extensions[i]; 696 if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) 697 psc->copySubBuffer = (__DRIcopySubBufferExtension *) extensions[i]; 698 } 699 700 if (psc->core == NULL || psc->swrast == NULL) { 701 ErrorMessageF("core dri extension not found\n"); 702 goto handle_error; 703 } 704 705 if (psc->swrast->base.version >= 4) { 706 psc->driScreen = 707 psc->swrast->createNewScreen2(screen, loader_extensions, 708 extensions, 709 &driver_configs, psc); 710 } else { 711 psc->driScreen = 712 psc->swrast->createNewScreen(screen, loader_extensions, 713 &driver_configs, psc); 714 } 715 if (psc->driScreen == NULL) { 716 ErrorMessageF("failed to create dri screen\n"); 717 goto handle_error; 718 } 719 720 extensions = psc->core->getExtensions(psc->driScreen); 721 driswBindExtensions(psc, extensions); 722 723 configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs); 724 visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs); 725 726 if (!configs || !visuals) { 727 ErrorMessageF("No matching fbConfigs or visuals found\n"); 728 goto handle_error; 729 } 730 731 glx_config_destroy_list(psc->base.configs); 732 psc->base.configs = configs; 733 glx_config_destroy_list(psc->base.visuals); 734 psc->base.visuals = visuals; 735 736 psc->driver_configs = driver_configs; 737 738 psc->base.vtable = &drisw_screen_vtable; 739 psp = &psc->vtable; 740 psc->base.driScreen = psp; 741 psp->destroyScreen = driswDestroyScreen; 742 psp->createDrawable = driswCreateDrawable; 743 psp->swapBuffers = driswSwapBuffers; 744 745 if (psc->copySubBuffer) 746 psp->copySubBuffer = driswCopySubBuffer; 747 748 return &psc->base; 749 750 handle_error: 751 if (configs) 752 glx_config_destroy_list(configs); 753 if (visuals) 754 glx_config_destroy_list(visuals); 755 if (psc->driScreen) 756 psc->core->destroyScreen(psc->driScreen); 757 psc->driScreen = NULL; 758 759 if (psc->driver) 760 dlclose(psc->driver); 761 glx_screen_cleanup(&psc->base); 762 free(psc); 763 764 CriticalErrorMessageF("failed to load driver: %s\n", SWRAST_DRIVER_NAME); 765 766 return NULL; 767 } 768 769 /* Called from __glXFreeDisplayPrivate. 770 */ 771 static void 772 driswDestroyDisplay(__GLXDRIdisplay * dpy) 773 { 774 free(dpy); 775 } 776 777 /* 778 * Allocate, initialize and return a __DRIdisplayPrivate object. 779 * This is called from __glXInitialize() when we are given a new 780 * display pointer. 781 */ 782 _X_HIDDEN __GLXDRIdisplay * 783 driswCreateDisplay(Display * dpy) 784 { 785 struct drisw_display *pdpyp; 786 787 pdpyp = malloc(sizeof *pdpyp); 788 if (pdpyp == NULL) 789 return NULL; 790 791 pdpyp->base.destroyDisplay = driswDestroyDisplay; 792 pdpyp->base.createScreen = driswCreateScreen; 793 794 return &pdpyp->base; 795 } 796 797 #endif /* GLX_DIRECT_RENDERING */ 798