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 32static Bool 33XCreateDrawable(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 79static void 80XDestroyDrawable(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 93static void 94swrastGetDrawableInfo(__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 */ 127static inline int 128bytes_per_line(unsigned pitch_bits, unsigned mul) 129{ 130 unsigned mask = mul - 1; 131 132 return ((pitch_bits + mask) & ~mask) / 8; 133} 134 135static void 136swrastPutImage2(__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 171static void 172swrastPutImage(__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 179static void 180swrastGetImage2(__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 203static void 204swrastGetImage(__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 211static 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 221static const __DRIextension *loader_extensions[] = { 222 &systemTimeExtension.base, 223 &swrastLoaderExtension.base, 224 NULL 225}; 226 227/** 228 * GLXDRI functions 229 */ 230 231static void 232drisw_destroy_context(struct glx_context *context) 233{ 234 struct drisw_context *pcp = (struct drisw_context *) context; 235 struct drisw_screen *psc = (struct drisw_screen *) context->psc; 236 237 driReleaseDrawables(&pcp->base); 238 239 free((char *) context->extensions); 240 241 (*psc->core->destroyContext) (pcp->driContext); 242 243 free(pcp); 244} 245 246static int 247drisw_bind_context(struct glx_context *context, struct glx_context *old, 248 GLXDrawable draw, GLXDrawable read) 249{ 250 struct drisw_context *pcp = (struct drisw_context *) context; 251 struct drisw_screen *psc = (struct drisw_screen *) pcp->base.psc; 252 struct drisw_drawable *pdraw, *pread; 253 254 pdraw = (struct drisw_drawable *) driFetchDrawable(context, draw); 255 pread = (struct drisw_drawable *) driFetchDrawable(context, read); 256 257 driReleaseDrawables(&pcp->base); 258 259 if (pdraw == NULL || pread == NULL) 260 return GLXBadDrawable; 261 262 if ((*psc->core->bindContext) (pcp->driContext, 263 pdraw->driDrawable, pread->driDrawable)) 264 return Success; 265 266 return GLXBadContext; 267} 268 269static void 270drisw_unbind_context(struct glx_context *context, struct glx_context *new) 271{ 272 struct drisw_context *pcp = (struct drisw_context *) context; 273 struct drisw_screen *psc = (struct drisw_screen *) pcp->base.psc; 274 275 (*psc->core->unbindContext) (pcp->driContext); 276} 277 278static void 279drisw_bind_tex_image(Display * dpy, 280 GLXDrawable drawable, 281 int buffer, const int *attrib_list) 282{ 283 struct glx_context *gc = __glXGetCurrentContext(); 284 struct drisw_context *pcp = (struct drisw_context *) gc; 285 __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable); 286 struct drisw_drawable *pdraw = (struct drisw_drawable *) base; 287 struct drisw_screen *psc; 288 289 __glXInitialize(dpy); 290 291 if (pdraw != NULL) { 292 psc = (struct drisw_screen *) base->psc; 293 294 if (!psc->texBuffer) 295 return; 296 297 if (psc->texBuffer->base.version >= 2 && 298 psc->texBuffer->setTexBuffer2 != NULL) { 299 (*psc->texBuffer->setTexBuffer2) (pcp->driContext, 300 pdraw->base.textureTarget, 301 pdraw->base.textureFormat, 302 pdraw->driDrawable); 303 } 304 else { 305 (*psc->texBuffer->setTexBuffer) (pcp->driContext, 306 pdraw->base.textureTarget, 307 pdraw->driDrawable); 308 } 309 } 310} 311 312static void 313drisw_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer) 314{ 315 struct glx_context *gc = __glXGetCurrentContext(); 316 struct drisw_context *pcp = (struct drisw_context *) gc; 317 __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable); 318 struct glx_display *dpyPriv = __glXInitialize(dpy); 319 struct drisw_drawable *pdraw = (struct drisw_drawable *) base; 320 struct drisw_screen *psc; 321 322 if (dpyPriv != NULL && pdraw != NULL) { 323 psc = (struct drisw_screen *) base->psc; 324 325 if (!psc->texBuffer) 326 return; 327 328 if (psc->texBuffer->base.version >= 3 && 329 psc->texBuffer->releaseTexBuffer != NULL) { 330 (*psc->texBuffer->releaseTexBuffer) (pcp->driContext, 331 pdraw->base.textureTarget, 332 pdraw->driDrawable); 333 } 334 } 335} 336 337static const struct glx_context_vtable drisw_context_vtable = { 338 .destroy = drisw_destroy_context, 339 .bind = drisw_bind_context, 340 .unbind = drisw_unbind_context, 341 .wait_gl = NULL, 342 .wait_x = NULL, 343 .use_x_font = DRI_glXUseXFont, 344 .bind_tex_image = drisw_bind_tex_image, 345 .release_tex_image = drisw_release_tex_image, 346 .get_proc_address = NULL, 347}; 348 349static struct glx_context * 350drisw_create_context(struct glx_screen *base, 351 struct glx_config *config_base, 352 struct glx_context *shareList, int renderType) 353{ 354 struct drisw_context *pcp, *pcp_shared; 355 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base; 356 struct drisw_screen *psc = (struct drisw_screen *) base; 357 __DRIcontext *shared = NULL; 358 359 if (!psc->base.driScreen) 360 return NULL; 361 362 /* Check the renderType value */ 363 if (!validate_renderType_against_config(config_base, renderType)) 364 return NULL; 365 366 if (shareList) { 367 /* If the shareList context is not a DRISW context, we cannot possibly 368 * create a DRISW context that shares it. 369 */ 370 if (shareList->vtable->destroy != drisw_destroy_context) { 371 return NULL; 372 } 373 374 pcp_shared = (struct drisw_context *) shareList; 375 shared = pcp_shared->driContext; 376 } 377 378 pcp = calloc(1, sizeof *pcp); 379 if (pcp == NULL) 380 return NULL; 381 382 if (!glx_context_init(&pcp->base, &psc->base, &config->base)) { 383 free(pcp); 384 return NULL; 385 } 386 387 pcp->base.renderType = renderType; 388 389 pcp->driContext = 390 (*psc->core->createNewContext) (psc->driScreen, 391 config->driConfig, shared, pcp); 392 if (pcp->driContext == NULL) { 393 free(pcp); 394 return NULL; 395 } 396 397 pcp->base.vtable = &drisw_context_vtable; 398 399 return &pcp->base; 400} 401 402static struct glx_context * 403drisw_create_context_attribs(struct glx_screen *base, 404 struct glx_config *config_base, 405 struct glx_context *shareList, 406 unsigned num_attribs, 407 const uint32_t *attribs, 408 unsigned *error) 409{ 410 struct drisw_context *pcp, *pcp_shared; 411 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base; 412 struct drisw_screen *psc = (struct drisw_screen *) base; 413 __DRIcontext *shared = NULL; 414 415 uint32_t minor_ver; 416 uint32_t major_ver; 417 uint32_t renderType; 418 uint32_t flags; 419 unsigned api; 420 int reset; 421 uint32_t ctx_attribs[2 * 4]; 422 unsigned num_ctx_attribs = 0; 423 424 if (!psc->base.driScreen) 425 return NULL; 426 427 if (psc->swrast->base.version < 3) 428 return NULL; 429 430 /* Remap the GLX tokens to DRI2 tokens. 431 */ 432 if (!dri2_convert_glx_attribs(num_attribs, attribs, 433 &major_ver, &minor_ver, &renderType, &flags, 434 &api, &reset, error)) 435 return NULL; 436 437 /* Check the renderType value */ 438 if (!validate_renderType_against_config(config_base, renderType)) { 439 return NULL; 440 } 441 442 if (reset != __DRI_CTX_RESET_NO_NOTIFICATION) 443 return NULL; 444 445 if (shareList) { 446 pcp_shared = (struct drisw_context *) shareList; 447 shared = pcp_shared->driContext; 448 } 449 450 pcp = calloc(1, sizeof *pcp); 451 if (pcp == NULL) 452 return NULL; 453 454 if (!glx_context_init(&pcp->base, &psc->base, &config->base)) { 455 free(pcp); 456 return NULL; 457 } 458 459 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION; 460 ctx_attribs[num_ctx_attribs++] = major_ver; 461 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION; 462 ctx_attribs[num_ctx_attribs++] = minor_ver; 463 464 if (flags != 0) { 465 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS; 466 467 /* The current __DRI_CTX_FLAG_* values are identical to the 468 * GLX_CONTEXT_*_BIT values. 469 */ 470 ctx_attribs[num_ctx_attribs++] = flags; 471 } 472 473 pcp->base.renderType = renderType; 474 475 pcp->driContext = 476 (*psc->swrast->createContextAttribs) (psc->driScreen, 477 api, 478 config->driConfig, 479 shared, 480 num_ctx_attribs / 2, 481 ctx_attribs, 482 error, 483 pcp); 484 if (pcp->driContext == NULL) { 485 free(pcp); 486 return NULL; 487 } 488 489 pcp->base.vtable = &drisw_context_vtable; 490 491 return &pcp->base; 492} 493 494static void 495driswDestroyDrawable(__GLXDRIdrawable * pdraw) 496{ 497 struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw; 498 struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc; 499 500 (*psc->core->destroyDrawable) (pdp->driDrawable); 501 502 XDestroyDrawable(pdp, pdraw->psc->dpy, pdraw->drawable); 503 free(pdp); 504} 505 506static __GLXDRIdrawable * 507driswCreateDrawable(struct glx_screen *base, XID xDrawable, 508 GLXDrawable drawable, struct glx_config *modes) 509{ 510 struct drisw_drawable *pdp; 511 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes; 512 struct drisw_screen *psc = (struct drisw_screen *) base; 513 Bool ret; 514 const __DRIswrastExtension *swrast = psc->swrast; 515 516 pdp = calloc(1, sizeof(*pdp)); 517 if (!pdp) 518 return NULL; 519 520 pdp->base.xDrawable = xDrawable; 521 pdp->base.drawable = drawable; 522 pdp->base.psc = &psc->base; 523 524 ret = XCreateDrawable(pdp, psc->base.dpy, xDrawable, modes->visualID); 525 if (!ret) { 526 free(pdp); 527 return NULL; 528 } 529 530 /* Create a new drawable */ 531 pdp->driDrawable = 532 (*swrast->createNewDrawable) (psc->driScreen, config->driConfig, pdp); 533 534 if (!pdp->driDrawable) { 535 XDestroyDrawable(pdp, psc->base.dpy, xDrawable); 536 free(pdp); 537 return NULL; 538 } 539 540 pdp->base.destroyDrawable = driswDestroyDrawable; 541 542 return &pdp->base; 543} 544 545static int64_t 546driswSwapBuffers(__GLXDRIdrawable * pdraw, 547 int64_t target_msc, int64_t divisor, int64_t remainder, 548 Bool flush) 549{ 550 struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw; 551 struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc; 552 553 (void) target_msc; 554 (void) divisor; 555 (void) remainder; 556 557 if (flush) { 558 glFlush(); 559 } 560 561 (*psc->core->swapBuffers) (pdp->driDrawable); 562 563 return 0; 564} 565 566static void 567driswCopySubBuffer(__GLXDRIdrawable * pdraw, 568 int x, int y, int width, int height, Bool flush) 569{ 570 struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw; 571 struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc; 572 573 if (flush) { 574 glFlush(); 575 } 576 577 (*psc->copySubBuffer->copySubBuffer) (pdp->driDrawable, 578 x, y, width, height); 579} 580 581static void 582driswDestroyScreen(struct glx_screen *base) 583{ 584 struct drisw_screen *psc = (struct drisw_screen *) base; 585 586 /* Free the direct rendering per screen data */ 587 (*psc->core->destroyScreen) (psc->driScreen); 588 driDestroyConfigs(psc->driver_configs); 589 psc->driScreen = NULL; 590 if (psc->driver) 591 dlclose(psc->driver); 592 free(psc); 593} 594 595#define SWRAST_DRIVER_NAME "swrast" 596 597static void * 598driOpenSwrast(void) 599{ 600 void *driver = NULL; 601 602 if (driver == NULL) 603 driver = driOpenDriver(SWRAST_DRIVER_NAME); 604 605 return driver; 606} 607 608static const struct glx_screen_vtable drisw_screen_vtable = { 609 .create_context = drisw_create_context, 610 .create_context_attribs = drisw_create_context_attribs, 611 .query_renderer_integer = drisw_query_renderer_integer, 612 .query_renderer_string = drisw_query_renderer_string, 613}; 614 615static void 616driswBindExtensions(struct drisw_screen *psc, const __DRIextension **extensions) 617{ 618 int i; 619 620 __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read"); 621 622 if (psc->swrast->base.version >= 3) { 623 __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context"); 624 __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context_profile"); 625 626 /* DRISW version >= 2 implies support for OpenGL ES. 627 */ 628 __glXEnableDirectExtension(&psc->base, 629 "GLX_EXT_create_context_es_profile"); 630 __glXEnableDirectExtension(&psc->base, 631 "GLX_EXT_create_context_es2_profile"); 632 } 633 634 if (psc->copySubBuffer) 635 __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer"); 636 637 /* FIXME: Figure out what other extensions can be ported here from dri2. */ 638 for (i = 0; extensions[i]; i++) { 639 if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) { 640 psc->texBuffer = (__DRItexBufferExtension *) extensions[i]; 641 __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap"); 642 } 643 /* DRISW version 3 is also required because GLX_MESA_query_renderer 644 * requires GLX_ARB_create_context_profile. 645 */ 646 if (psc->swrast->base.version >= 3 647 && strcmp(extensions[i]->name, __DRI2_RENDERER_QUERY) == 0) { 648 psc->rendererQuery = (__DRI2rendererQueryExtension *) extensions[i]; 649 __glXEnableDirectExtension(&psc->base, "GLX_MESA_query_renderer"); 650 } 651 } 652} 653 654static struct glx_screen * 655driswCreateScreen(int screen, struct glx_display *priv) 656{ 657 __GLXDRIscreen *psp; 658 const __DRIconfig **driver_configs; 659 const __DRIextension **extensions; 660 struct drisw_screen *psc; 661 struct glx_config *configs = NULL, *visuals = NULL; 662 int i; 663 664 psc = calloc(1, sizeof *psc); 665 if (psc == NULL) 666 return NULL; 667 668 if (!glx_screen_init(&psc->base, screen, priv)) { 669 free(psc); 670 return NULL; 671 } 672 673 psc->driver = driOpenSwrast(); 674 if (psc->driver == NULL) 675 goto handle_error; 676 677 extensions = driGetDriverExtensions(psc->driver, SWRAST_DRIVER_NAME); 678 if (extensions == NULL) 679 goto handle_error; 680 681 for (i = 0; extensions[i]; i++) { 682 if (strcmp(extensions[i]->name, __DRI_CORE) == 0) 683 psc->core = (__DRIcoreExtension *) extensions[i]; 684 if (strcmp(extensions[i]->name, __DRI_SWRAST) == 0) 685 psc->swrast = (__DRIswrastExtension *) extensions[i]; 686 if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) 687 psc->copySubBuffer = (__DRIcopySubBufferExtension *) extensions[i]; 688 } 689 690 if (psc->core == NULL || psc->swrast == NULL) { 691 ErrorMessageF("core dri extension not found\n"); 692 goto handle_error; 693 } 694 695 if (psc->swrast->base.version >= 4) { 696 psc->driScreen = 697 psc->swrast->createNewScreen2(screen, loader_extensions, 698 extensions, 699 &driver_configs, psc); 700 } else { 701 psc->driScreen = 702 psc->swrast->createNewScreen(screen, loader_extensions, 703 &driver_configs, psc); 704 } 705 if (psc->driScreen == NULL) { 706 ErrorMessageF("failed to create dri screen\n"); 707 goto handle_error; 708 } 709 710 extensions = psc->core->getExtensions(psc->driScreen); 711 driswBindExtensions(psc, extensions); 712 713 configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs); 714 visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs); 715 716 if (!configs || !visuals) { 717 ErrorMessageF("No matching fbConfigs or visuals found\n"); 718 goto handle_error; 719 } 720 721 glx_config_destroy_list(psc->base.configs); 722 psc->base.configs = configs; 723 glx_config_destroy_list(psc->base.visuals); 724 psc->base.visuals = visuals; 725 726 psc->driver_configs = driver_configs; 727 728 psc->base.vtable = &drisw_screen_vtable; 729 psp = &psc->vtable; 730 psc->base.driScreen = psp; 731 psp->destroyScreen = driswDestroyScreen; 732 psp->createDrawable = driswCreateDrawable; 733 psp->swapBuffers = driswSwapBuffers; 734 735 if (psc->copySubBuffer) 736 psp->copySubBuffer = driswCopySubBuffer; 737 738 return &psc->base; 739 740 handle_error: 741 if (configs) 742 glx_config_destroy_list(configs); 743 if (visuals) 744 glx_config_destroy_list(visuals); 745 if (psc->driScreen) 746 psc->core->destroyScreen(psc->driScreen); 747 psc->driScreen = NULL; 748 749 if (psc->driver) 750 dlclose(psc->driver); 751 glx_screen_cleanup(&psc->base); 752 free(psc); 753 754 CriticalErrorMessageF("failed to load driver: %s\n", SWRAST_DRIVER_NAME); 755 756 return NULL; 757} 758 759/* Called from __glXFreeDisplayPrivate. 760 */ 761static void 762driswDestroyDisplay(__GLXDRIdisplay * dpy) 763{ 764 free(dpy); 765} 766 767/* 768 * Allocate, initialize and return a __DRIdisplayPrivate object. 769 * This is called from __glXInitialize() when we are given a new 770 * display pointer. 771 */ 772_X_HIDDEN __GLXDRIdisplay * 773driswCreateDisplay(Display * dpy) 774{ 775 struct drisw_display *pdpyp; 776 777 pdpyp = malloc(sizeof *pdpyp); 778 if (pdpyp == NULL) 779 return NULL; 780 781 pdpyp->base.destroyDisplay = driswDestroyDisplay; 782 pdpyp->base.createScreen = driswCreateScreen; 783 784 return &pdpyp->base; 785} 786 787#endif /* GLX_DIRECT_RENDERING */ 788