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 #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    &systemTimeExtension.base,
    223    &swrastLoaderExtension.base,
    224    NULL
    225 };
    226 
    227 /**
    228  * GLXDRI functions
    229  */
    230 
    231 static void
    232 drisw_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 
    246 static int
    247 drisw_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 
    269 static void
    270 drisw_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 
    278 static void
    279 drisw_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 
    312 static void
    313 drisw_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 
    337 static 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 
    349 static struct glx_context *
    350 drisw_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 
    402 static struct glx_context *
    403 drisw_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 
    494 static void
    495 driswDestroyDrawable(__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 
    506 static __GLXDRIdrawable *
    507 driswCreateDrawable(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 
    545 static int64_t
    546 driswSwapBuffers(__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 
    566 static void
    567 driswCopySubBuffer(__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 
    581 static void
    582 driswDestroyScreen(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 
    597 static void *
    598 driOpenSwrast(void)
    599 {
    600    void *driver = NULL;
    601 
    602    if (driver == NULL)
    603       driver = driOpenDriver(SWRAST_DRIVER_NAME);
    604 
    605    return driver;
    606 }
    607 
    608 static 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 
    615 static void
    616 driswBindExtensions(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 
    654 static struct glx_screen *
    655 driswCreateScreen(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  */
    761 static void
    762 driswDestroyDisplay(__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 *
    773 driswCreateDisplay(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