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