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