Home | History | Annotate | Download | only in glx
      1 /**************************************************************************
      2 
      3 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
      4 All Rights Reserved.
      5 
      6 Permission is hereby granted, free of charge, to any person obtaining a
      7 copy of this software and associated documentation files (the
      8 "Software"), to deal in the Software without restriction, including
      9 without limitation the rights to use, copy, modify, merge, publish,
     10 distribute, sub license, and/or sell copies of the Software, and to
     11 permit persons to whom the Software is furnished to do so, subject to
     12 the following conditions:
     13 
     14 The above copyright notice and this permission notice (including the
     15 next paragraph) shall be included in all copies or substantial portions
     16 of the Software.
     17 
     18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     21 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
     22 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     23 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     24 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25 
     26 **************************************************************************/
     27 
     28 /*
     29  * Authors:
     30  *   Kevin E. Martin <kevin (at) precisioninsight.com>
     31  *   Brian Paul <brian (at) precisioninsight.com>
     32  *
     33  */
     34 
     35 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
     36 
     37 #include <X11/Xlib.h>
     38 #include <X11/extensions/Xfixes.h>
     39 #include <X11/extensions/Xdamage.h>
     40 #include "glxclient.h"
     41 #include "xf86dri.h"
     42 #include "dri2.h"
     43 #include "dri_sarea.h"
     44 #include <dlfcn.h>
     45 #include <sys/types.h>
     46 #include <sys/mman.h>
     47 #include "xf86drm.h"
     48 #include "dri_common.h"
     49 
     50 struct dri_display
     51 {
     52    __GLXDRIdisplay base;
     53 
     54    /*
     55     ** XFree86-DRI version information
     56     */
     57    int driMajor;
     58    int driMinor;
     59    int driPatch;
     60 };
     61 
     62 struct dri_screen
     63 {
     64    struct glx_screen base;
     65 
     66    __DRIscreen *driScreen;
     67    __GLXDRIscreen vtable;
     68    const __DRIlegacyExtension *legacy;
     69    const __DRIcoreExtension *core;
     70    const __DRIswapControlExtension *swapControl;
     71    const __DRImediaStreamCounterExtension *msc;
     72    const __DRIconfig **driver_configs;
     73    const __DRIcopySubBufferExtension *driCopySubBuffer;
     74 
     75    void *driver;
     76    int fd;
     77 };
     78 
     79 struct dri_context
     80 {
     81    struct glx_context base;
     82    __DRIcontext *driContext;
     83    XID hwContextID;
     84 };
     85 
     86 struct dri_drawable
     87 {
     88    __GLXDRIdrawable base;
     89 
     90    __DRIdrawable *driDrawable;
     91 };
     92 
     93 /*
     94  * Given a display pointer and screen number, determine the name of
     95  * the DRI driver for the screen (i.e., "i965", "radeon", "nouveau", etc).
     96  * Return True for success, False for failure.
     97  */
     98 static Bool
     99 driGetDriverName(Display * dpy, int scrNum, char **driverName)
    100 {
    101    int directCapable;
    102    Bool b;
    103    int event, error;
    104    int driverMajor, driverMinor, driverPatch;
    105 
    106    *driverName = NULL;
    107 
    108    if (XF86DRIQueryExtension(dpy, &event, &error)) {    /* DRI1 */
    109       if (!XF86DRIQueryDirectRenderingCapable(dpy, scrNum, &directCapable)) {
    110          ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n");
    111          return False;
    112       }
    113       if (!directCapable) {
    114          ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n");
    115          return False;
    116       }
    117 
    118       b = XF86DRIGetClientDriverName(dpy, scrNum, &driverMajor, &driverMinor,
    119                                      &driverPatch, driverName);
    120       if (!b) {
    121          ErrorMessageF("Cannot determine driver name for screen %d\n",
    122                        scrNum);
    123          return False;
    124       }
    125 
    126       InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
    127                    driverMajor, driverMinor, driverPatch, *driverName,
    128                    scrNum);
    129 
    130       return True;
    131    }
    132    else if (DRI2QueryExtension(dpy, &event, &error)) {  /* DRI2 */
    133       char *dev;
    134       Bool ret = DRI2Connect(dpy, RootWindow(dpy, scrNum), driverName, &dev);
    135 
    136       if (ret)
    137          free(dev);
    138 
    139       return ret;
    140    }
    141 
    142    return False;
    143 }
    144 
    145 /*
    146  * Exported function for querying the DRI driver for a given screen.
    147  *
    148  * The returned char pointer points to a static array that will be
    149  * overwritten by subsequent calls.
    150  */
    151 _GLX_PUBLIC const char *
    152 glXGetScreenDriver(Display * dpy, int scrNum)
    153 {
    154    static char ret[32];
    155    char *driverName;
    156    if (driGetDriverName(dpy, scrNum, &driverName)) {
    157       int len;
    158       if (!driverName)
    159          return NULL;
    160       len = strlen(driverName);
    161       if (len >= 31)
    162          return NULL;
    163       memcpy(ret, driverName, len + 1);
    164       free(driverName);
    165       return ret;
    166    }
    167    return NULL;
    168 }
    169 
    170 /*
    171  * Exported function for obtaining a driver's option list (UTF-8 encoded XML).
    172  *
    173  * The returned char pointer points directly into the driver. Therefore
    174  * it should be treated as a constant.
    175  *
    176  * If the driver was not found or does not support configuration NULL is
    177  * returned.
    178  *
    179  * Note: The driver remains opened after this function returns.
    180  */
    181 _GLX_PUBLIC const char *
    182 glXGetDriverConfig(const char *driverName)
    183 {
    184    void *handle = driOpenDriver(driverName);
    185    const __DRIextension **extensions;
    186 
    187    if (!handle)
    188       return NULL;
    189 
    190    extensions = driGetDriverExtensions(handle, driverName);
    191    if (extensions) {
    192       for (int i = 0; extensions[i]; i++) {
    193          if (strcmp(extensions[i]->name, __DRI_CONFIG_OPTIONS) == 0)
    194             return ((__DRIconfigOptionsExtension *)extensions[i])->xml;
    195       }
    196    }
    197 
    198    /* Fall back to the old method */
    199    return dlsym(handle, "__driConfigOptions");
    200 }
    201 
    202 #ifdef XDAMAGE_1_1_INTERFACE
    203 
    204 static GLboolean
    205 has_damage_post(Display * dpy)
    206 {
    207    static GLboolean inited = GL_FALSE;
    208    static GLboolean has_damage;
    209 
    210    if (!inited) {
    211       int major, minor;
    212 
    213       if (XDamageQueryVersion(dpy, &major, &minor) &&
    214           major == 1 && minor >= 1) {
    215          has_damage = GL_TRUE;
    216       }
    217       else {
    218          has_damage = GL_FALSE;
    219       }
    220       inited = GL_TRUE;
    221    }
    222 
    223    return has_damage;
    224 }
    225 
    226 static void
    227 __glXReportDamage(__DRIdrawable * driDraw,
    228                   int x, int y,
    229                   drm_clip_rect_t * rects, int num_rects,
    230                   GLboolean front_buffer, void *loaderPrivate)
    231 {
    232    XRectangle *xrects;
    233    XserverRegion region;
    234    int i;
    235    int x_off, y_off;
    236    __GLXDRIdrawable *glxDraw = loaderPrivate;
    237    struct glx_screen *psc = glxDraw->psc;
    238    Display *dpy = psc->dpy;
    239    Drawable drawable;
    240 
    241    if (!has_damage_post(dpy))
    242       return;
    243 
    244    if (front_buffer) {
    245       x_off = x;
    246       y_off = y;
    247       drawable = RootWindow(dpy, psc->scr);
    248    }
    249    else {
    250       x_off = 0;
    251       y_off = 0;
    252       drawable = glxDraw->xDrawable;
    253    }
    254 
    255    xrects = malloc(sizeof(XRectangle) * num_rects);
    256    if (xrects == NULL)
    257       return;
    258 
    259    for (i = 0; i < num_rects; i++) {
    260       xrects[i].x = rects[i].x1 + x_off;
    261       xrects[i].y = rects[i].y1 + y_off;
    262       xrects[i].width = rects[i].x2 - rects[i].x1;
    263       xrects[i].height = rects[i].y2 - rects[i].y1;
    264    }
    265    region = XFixesCreateRegion(dpy, xrects, num_rects);
    266    free(xrects);
    267    XDamageAdd(dpy, drawable, region);
    268    XFixesDestroyRegion(dpy, region);
    269 }
    270 
    271 static const __DRIdamageExtension damageExtension = {
    272    .base = {__DRI_DAMAGE, 1 },
    273 
    274    .reportDamage        = __glXReportDamage,
    275 };
    276 
    277 #endif
    278 
    279 static GLboolean
    280 __glXDRIGetDrawableInfo(__DRIdrawable * drawable,
    281                         unsigned int *index, unsigned int *stamp,
    282                         int *X, int *Y, int *W, int *H,
    283                         int *numClipRects, drm_clip_rect_t ** pClipRects,
    284                         int *backX, int *backY,
    285                         int *numBackClipRects,
    286                         drm_clip_rect_t ** pBackClipRects,
    287                         void *loaderPrivate)
    288 {
    289    __GLXDRIdrawable *glxDraw = loaderPrivate;
    290    struct glx_screen *psc = glxDraw->psc;
    291    Display *dpy = psc->dpy;
    292 
    293    return XF86DRIGetDrawableInfo(dpy, psc->scr, glxDraw->drawable,
    294                                  index, stamp, X, Y, W, H,
    295                                  numClipRects, pClipRects,
    296                                  backX, backY,
    297                                  numBackClipRects, pBackClipRects);
    298 }
    299 
    300 static const __DRIgetDrawableInfoExtension getDrawableInfoExtension = {
    301    .base = {__DRI_GET_DRAWABLE_INFO, 1 },
    302 
    303    .getDrawableInfo     = __glXDRIGetDrawableInfo
    304 };
    305 
    306 static const __DRIextension *loader_extensions[] = {
    307    &systemTimeExtension.base,
    308    &getDrawableInfoExtension.base,
    309 #ifdef XDAMAGE_1_1_INTERFACE
    310    &damageExtension.base,
    311 #endif
    312    NULL
    313 };
    314 
    315 /**
    316  * Perform the required libGL-side initialization and call the client-side
    317  * driver's \c __driCreateNewScreen function.
    318  *
    319  * \param dpy    Display pointer.
    320  * \param scrn   Screen number on the display.
    321  * \param psc    DRI screen information.
    322  * \param driDpy DRI display information.
    323  * \param createNewScreen  Pointer to the client-side driver's
    324  *               \c __driCreateNewScreen function.
    325  * \returns A pointer to the \c __DRIscreen structure returned by
    326  *          the client-side driver on success, or \c NULL on failure.
    327  */
    328 static void *
    329 CallCreateNewScreen(Display *dpy, int scrn, struct dri_screen *psc,
    330                     struct dri_display * driDpy)
    331 {
    332    void *psp = NULL;
    333    drm_handle_t hSAREA;
    334    drmAddress pSAREA = MAP_FAILED;
    335    char *BusID;
    336    __DRIversion ddx_version;
    337    __DRIversion dri_version;
    338    __DRIversion drm_version;
    339    __DRIframebuffer framebuffer;
    340    int fd = -1;
    341    int status;
    342 
    343    drm_magic_t magic;
    344    drmVersionPtr version;
    345    int newlyopened;
    346    char *driverName;
    347    drm_handle_t hFB;
    348    int junk;
    349    const __DRIconfig **driver_configs;
    350    struct glx_config *visual, *configs = NULL, *visuals = NULL;
    351 
    352    /* DRI protocol version. */
    353    dri_version.major = driDpy->driMajor;
    354    dri_version.minor = driDpy->driMinor;
    355    dri_version.patch = driDpy->driPatch;
    356 
    357    framebuffer.base = MAP_FAILED;
    358    framebuffer.dev_priv = NULL;
    359    framebuffer.size = 0;
    360 
    361    if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
    362       ErrorMessageF("XF86DRIOpenConnection failed\n");
    363       goto handle_error;
    364    }
    365 
    366    fd = drmOpenOnce(NULL, BusID, &newlyopened);
    367 
    368    free(BusID);                /* No longer needed */
    369 
    370    if (fd < 0) {
    371       ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd));
    372       goto handle_error;
    373    }
    374 
    375    if (drmGetMagic(fd, &magic)) {
    376       ErrorMessageF("drmGetMagic failed\n");
    377       goto handle_error;
    378    }
    379 
    380    version = drmGetVersion(fd);
    381    if (version) {
    382       drm_version.major = version->version_major;
    383       drm_version.minor = version->version_minor;
    384       drm_version.patch = version->version_patchlevel;
    385       drmFreeVersion(version);
    386    }
    387    else {
    388       drm_version.major = -1;
    389       drm_version.minor = -1;
    390       drm_version.patch = -1;
    391    }
    392 
    393    if (newlyopened && !XF86DRIAuthConnection(dpy, scrn, magic)) {
    394       ErrorMessageF("XF86DRIAuthConnection failed\n");
    395       goto handle_error;
    396    }
    397 
    398    /* Get device name (like "radeon") and the ddx version numbers.
    399     * We'll check the version in each DRI driver's "createNewScreen"
    400     * function. */
    401    if (!XF86DRIGetClientDriverName(dpy, scrn,
    402                                    &ddx_version.major,
    403                                    &ddx_version.minor,
    404                                    &ddx_version.patch, &driverName)) {
    405       ErrorMessageF("XF86DRIGetClientDriverName failed\n");
    406       goto handle_error;
    407    }
    408 
    409    free(driverName);           /* No longer needed. */
    410 
    411    /*
    412     * Get device-specific info.  pDevPriv will point to a struct
    413     * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
    414     * has information about the screen size, depth, pitch, ancilliary
    415     * buffers, DRM mmap handles, etc.
    416     */
    417    if (!XF86DRIGetDeviceInfo(dpy, scrn, &hFB, &junk,
    418                              &framebuffer.size, &framebuffer.stride,
    419                              &framebuffer.dev_priv_size,
    420                              &framebuffer.dev_priv)) {
    421       ErrorMessageF("XF86DRIGetDeviceInfo failed\n");
    422       goto handle_error;
    423    }
    424 
    425    framebuffer.width = DisplayWidth(dpy, scrn);
    426    framebuffer.height = DisplayHeight(dpy, scrn);
    427 
    428    /* Map the framebuffer region. */
    429    status = drmMap(fd, hFB, framebuffer.size,
    430                    (drmAddressPtr) & framebuffer.base);
    431    if (status != 0) {
    432       ErrorMessageF("drmMap of framebuffer failed (%s)\n", strerror(-status));
    433       goto handle_error;
    434    }
    435 
    436    /* Map the SAREA region.  Further mmap regions may be setup in
    437     * each DRI driver's "createNewScreen" function.
    438     */
    439    status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA);
    440    if (status != 0) {
    441       ErrorMessageF("drmMap of SAREA failed (%s)\n", strerror(-status));
    442       goto handle_error;
    443    }
    444 
    445    psp = (*psc->legacy->createNewScreen) (scrn,
    446                                           &ddx_version,
    447                                           &dri_version,
    448                                           &drm_version,
    449                                           &framebuffer,
    450                                           pSAREA,
    451                                           fd,
    452                                           loader_extensions,
    453                                           &driver_configs, psc);
    454 
    455    if (psp == NULL) {
    456       ErrorMessageF("Calling driver entry point failed\n");
    457       goto handle_error;
    458    }
    459 
    460    configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs);
    461    visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
    462 
    463    if (!configs || !visuals) {
    464        ErrorMessageF("No matching fbConfigs or visuals found\n");
    465        goto handle_error;
    466    }
    467 
    468    glx_config_destroy_list(psc->base.configs);
    469    psc->base.configs = configs;
    470    glx_config_destroy_list(psc->base.visuals);
    471    psc->base.visuals = visuals;
    472 
    473    psc->driver_configs = driver_configs;
    474 
    475    /* Visuals with depth != screen depth are subject to automatic compositing
    476     * in the X server, so DRI1 can't render to them properly. Mark them as
    477     * non-conformant to prevent apps from picking them up accidentally.
    478     */
    479    for (visual = psc->base.visuals; visual; visual = visual->next) {
    480       XVisualInfo template;
    481       XVisualInfo *visuals;
    482       int num_visuals;
    483       long mask;
    484 
    485       template.visualid = visual->visualID;
    486       mask = VisualIDMask;
    487       visuals = XGetVisualInfo(dpy, mask, &template, &num_visuals);
    488 
    489       if (visuals) {
    490          if (num_visuals > 0 && visuals->depth != DefaultDepth(dpy, scrn))
    491             visual->visualRating = GLX_NON_CONFORMANT_CONFIG;
    492 
    493          free(visuals);
    494       }
    495    }
    496 
    497    return psp;
    498 
    499  handle_error:
    500    if (configs)
    501        glx_config_destroy_list(configs);
    502    if (visuals)
    503        glx_config_destroy_list(visuals);
    504 
    505    if (pSAREA != MAP_FAILED)
    506       drmUnmap(pSAREA, SAREA_MAX);
    507 
    508    if (framebuffer.base != MAP_FAILED)
    509       drmUnmap((drmAddress) framebuffer.base, framebuffer.size);
    510 
    511    free(framebuffer.dev_priv);
    512 
    513    if (fd >= 0)
    514       drmCloseOnce(fd);
    515 
    516    XF86DRICloseConnection(dpy, scrn);
    517 
    518    ErrorMessageF("reverting to software direct rendering\n");
    519 
    520    return NULL;
    521 }
    522 
    523 static void
    524 dri_destroy_context(struct glx_context * context)
    525 {
    526    struct dri_context *pcp = (struct dri_context *) context;
    527    struct dri_screen *psc = (struct dri_screen *) context->psc;
    528 
    529    driReleaseDrawables(&pcp->base);
    530 
    531    free((char *) context->extensions);
    532 
    533    (*psc->core->destroyContext) (pcp->driContext);
    534 
    535    XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID);
    536    free(pcp);
    537 }
    538 
    539 static int
    540 dri_bind_context(struct glx_context *context, struct glx_context *old,
    541 		 GLXDrawable draw, GLXDrawable read)
    542 {
    543    struct dri_context *pcp = (struct dri_context *) context;
    544    struct dri_screen *psc = (struct dri_screen *) pcp->base.psc;
    545    struct dri_drawable *pdraw, *pread;
    546 
    547    pdraw = (struct dri_drawable *) driFetchDrawable(context, draw);
    548    pread = (struct dri_drawable *) driFetchDrawable(context, read);
    549 
    550    driReleaseDrawables(&pcp->base);
    551 
    552    if (pdraw == NULL || pread == NULL)
    553       return GLXBadDrawable;
    554 
    555    if ((*psc->core->bindContext) (pcp->driContext,
    556 				  pdraw->driDrawable, pread->driDrawable))
    557       return Success;
    558 
    559    return GLXBadContext;
    560 }
    561 
    562 static void
    563 dri_unbind_context(struct glx_context *context, struct glx_context *new)
    564 {
    565    struct dri_context *pcp = (struct dri_context *) context;
    566    struct dri_screen *psc = (struct dri_screen *) pcp->base.psc;
    567 
    568    (*psc->core->unbindContext) (pcp->driContext);
    569 }
    570 
    571 static const struct glx_context_vtable dri_context_vtable = {
    572    .destroy             = dri_destroy_context,
    573    .bind                = dri_bind_context,
    574    .unbind              = dri_unbind_context,
    575    .wait_gl             = NULL,
    576    .wait_x              = NULL,
    577    .use_x_font          = DRI_glXUseXFont,
    578    .bind_tex_image      = NULL,
    579    .release_tex_image   = NULL,
    580    .get_proc_address    = NULL,
    581 };
    582 
    583 static struct glx_context *
    584 dri_create_context(struct glx_screen *base,
    585 		   struct glx_config *config_base,
    586 		   struct glx_context *shareList, int renderType)
    587 {
    588    struct dri_context *pcp, *pcp_shared;
    589    struct dri_screen *psc = (struct dri_screen *) base;
    590    drm_context_t hwContext;
    591    __DRIcontext *shared = NULL;
    592    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
    593 
    594    if (!psc->base.driScreen)
    595       return NULL;
    596 
    597    /* Check the renderType value */
    598    if (!validate_renderType_against_config(config_base, renderType))
    599        return NULL;
    600 
    601    if (shareList) {
    602       /* If the shareList context is not a DRI context, we cannot possibly
    603        * create a DRI context that shares it.
    604        */
    605       if (shareList->vtable->destroy != dri_destroy_context) {
    606 	 return NULL;
    607       }
    608 
    609       pcp_shared = (struct dri_context *) shareList;
    610       shared = pcp_shared->driContext;
    611    }
    612 
    613    pcp = calloc(1, sizeof *pcp);
    614    if (pcp == NULL)
    615       return NULL;
    616 
    617    if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
    618       free(pcp);
    619       return NULL;
    620    }
    621 
    622    pcp->base.renderType = renderType;
    623 
    624    if (!XF86DRICreateContextWithConfig(psc->base.dpy, psc->base.scr,
    625                                        config->base.visualID,
    626                                        &pcp->hwContextID, &hwContext)) {
    627       free(pcp);
    628       return NULL;
    629    }
    630 
    631    pcp->driContext =
    632       (*psc->legacy->createNewContext) (psc->driScreen,
    633                                         config->driConfig,
    634                                         renderType, shared, hwContext, pcp);
    635    if (pcp->driContext == NULL) {
    636       XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID);
    637       free(pcp);
    638       return NULL;
    639    }
    640 
    641    pcp->base.vtable = &dri_context_vtable;
    642 
    643    return &pcp->base;
    644 }
    645 
    646 static void
    647 driDestroyDrawable(__GLXDRIdrawable * pdraw)
    648 {
    649    struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
    650    struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
    651 
    652    (*psc->core->destroyDrawable) (pdp->driDrawable);
    653    XF86DRIDestroyDrawable(psc->base.dpy, psc->base.scr, pdraw->drawable);
    654    free(pdraw);
    655 }
    656 
    657 static __GLXDRIdrawable *
    658 driCreateDrawable(struct glx_screen *base,
    659                   XID xDrawable,
    660                   GLXDrawable drawable, struct glx_config *config_base)
    661 {
    662    drm_drawable_t hwDrawable;
    663    void *empty_attribute_list = NULL;
    664    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
    665    struct dri_screen *psc = (struct dri_screen *) base;
    666    struct dri_drawable *pdp;
    667 
    668    /* Old dri can't handle GLX 1.3+ drawable constructors. */
    669    if (xDrawable != drawable)
    670       return NULL;
    671 
    672    pdp = calloc(1, sizeof *pdp);
    673    if (!pdp)
    674       return NULL;
    675 
    676    pdp->base.drawable = drawable;
    677    pdp->base.psc = &psc->base;
    678 
    679    if (!XF86DRICreateDrawable(psc->base.dpy, psc->base.scr,
    680 			      drawable, &hwDrawable)) {
    681       free(pdp);
    682       return NULL;
    683    }
    684 
    685    /* Create a new drawable */
    686    pdp->driDrawable =
    687       (*psc->legacy->createNewDrawable) (psc->driScreen,
    688                                          config->driConfig,
    689                                          hwDrawable,
    690                                          GLX_WINDOW_BIT,
    691                                          empty_attribute_list, pdp);
    692 
    693    if (!pdp->driDrawable) {
    694       XF86DRIDestroyDrawable(psc->base.dpy, psc->base.scr, drawable);
    695       free(pdp);
    696       return NULL;
    697    }
    698 
    699    pdp->base.destroyDrawable = driDestroyDrawable;
    700 
    701    return &pdp->base;
    702 }
    703 
    704 static int64_t
    705 driSwapBuffers(__GLXDRIdrawable * pdraw, int64_t unused1, int64_t unused2,
    706 	       int64_t unused3, Bool flush)
    707 {
    708    struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
    709    struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
    710 
    711    if (flush) {
    712       glFlush();
    713    }
    714 
    715    (*psc->core->swapBuffers) (pdp->driDrawable);
    716    return 0;
    717 }
    718 
    719 static void
    720 driCopySubBuffer(__GLXDRIdrawable * pdraw,
    721                  int x, int y, int width, int height, Bool flush)
    722 {
    723    struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
    724    struct dri_screen *psc = (struct dri_screen *) pdp->base.psc;
    725 
    726    if (flush) {
    727       glFlush();
    728    }
    729 
    730    (*psc->driCopySubBuffer->copySubBuffer) (pdp->driDrawable,
    731 					    x, y, width, height);
    732 }
    733 
    734 static void
    735 driDestroyScreen(struct glx_screen *base)
    736 {
    737    struct dri_screen *psc = (struct dri_screen *) base;
    738 
    739    /* Free the direct rendering per screen data */
    740    if (psc->driScreen)
    741       (*psc->core->destroyScreen) (psc->driScreen);
    742    driDestroyConfigs(psc->driver_configs);
    743    psc->driScreen = NULL;
    744    if (psc->driver)
    745       dlclose(psc->driver);
    746 }
    747 
    748 static int
    749 driSetSwapInterval(__GLXDRIdrawable *pdraw, int interval)
    750 {
    751    struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
    752 
    753    if (pdraw != NULL) {
    754       struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
    755 
    756       if (psc->swapControl != NULL) {
    757          psc->swapControl->setSwapInterval(pdp->driDrawable, interval);
    758          return 0;
    759       }
    760    }
    761    return GLX_BAD_CONTEXT;
    762 }
    763 
    764 static int
    765 driGetSwapInterval(__GLXDRIdrawable *pdraw)
    766 {
    767    struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
    768 
    769    if (pdraw != NULL) {
    770       struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
    771 
    772       if (psc->swapControl != NULL)
    773          return psc->swapControl->getSwapInterval(pdp->driDrawable);
    774    }
    775    return 0;
    776 }
    777 
    778 /* Bind DRI1 specific extensions */
    779 static void
    780 driBindExtensions(struct dri_screen *psc, const __DRIextension **extensions)
    781 {
    782    int i;
    783 
    784    for (i = 0; extensions[i]; i++) {
    785       /* No DRI2 support for swap_control at the moment, since SwapBuffers
    786        * is done by the X server */
    787       if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) {
    788 	 psc->swapControl = (__DRIswapControlExtension *) extensions[i];
    789 	 __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control");
    790 	 __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control");
    791       }
    792 
    793       if (strcmp(extensions[i]->name, __DRI_MEDIA_STREAM_COUNTER) == 0) {
    794          psc->msc = (__DRImediaStreamCounterExtension *) extensions[i];
    795          __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync");
    796       }
    797 
    798       if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
    799 	 psc->driCopySubBuffer = (__DRIcopySubBufferExtension *) extensions[i];
    800 	 __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
    801       }
    802 
    803       if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
    804 	 __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
    805       }
    806       /* Ignore unknown extensions */
    807    }
    808 }
    809 
    810 static const struct glx_screen_vtable dri_screen_vtable = {
    811    .create_context         = dri_create_context,
    812    .create_context_attribs = NULL,
    813    .query_renderer_integer = NULL,
    814    .query_renderer_string  = NULL,
    815 };
    816 
    817 static struct glx_screen *
    818 driCreateScreen(int screen, struct glx_display *priv)
    819 {
    820    struct dri_display *pdp;
    821    __GLXDRIscreen *psp;
    822    const __DRIextension **extensions;
    823    struct dri_screen *psc;
    824    char *driverName;
    825    int i;
    826 
    827    psc = calloc(1, sizeof *psc);
    828    if (psc == NULL)
    829       return NULL;
    830 
    831    if (!glx_screen_init(&psc->base, screen, priv)) {
    832       free(psc);
    833       return NULL;
    834    }
    835 
    836    if (!driGetDriverName(priv->dpy, screen, &driverName)) {
    837       goto cleanup;
    838    }
    839 
    840    psc->driver = driOpenDriver(driverName);
    841    if (psc->driver == NULL)
    842       goto cleanup;
    843 
    844    extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
    845    if (extensions == NULL) {
    846       ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
    847       goto cleanup;
    848    }
    849 
    850    for (i = 0; extensions[i]; i++) {
    851       if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
    852 	 psc->core = (__DRIcoreExtension *) extensions[i];
    853       if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0)
    854 	 psc->legacy = (__DRIlegacyExtension *) extensions[i];
    855    }
    856 
    857    if (psc->core == NULL || psc->legacy == NULL)
    858       goto cleanup;
    859 
    860    pdp = (struct dri_display *) priv->driDisplay;
    861    psc->driScreen =
    862       CallCreateNewScreen(psc->base.dpy, screen, psc, pdp);
    863    if (psc->driScreen == NULL)
    864       goto cleanup;
    865 
    866    extensions = psc->core->getExtensions(psc->driScreen);
    867    driBindExtensions(psc, extensions);
    868 
    869    psc->base.vtable = &dri_screen_vtable;
    870    psp = &psc->vtable;
    871    psc->base.driScreen = psp;
    872    if (psc->driCopySubBuffer)
    873       psp->copySubBuffer = driCopySubBuffer;
    874 
    875    psp->destroyScreen = driDestroyScreen;
    876    psp->createDrawable = driCreateDrawable;
    877    psp->swapBuffers = driSwapBuffers;
    878 
    879    psp->setSwapInterval = driSetSwapInterval;
    880    psp->getSwapInterval = driGetSwapInterval;
    881 
    882    free(driverName);
    883 
    884    return &psc->base;
    885 
    886 cleanup:
    887    CriticalErrorMessageF("failed to load driver: %s\n", driverName);
    888 
    889    free(driverName);
    890 
    891    if (psc->driver)
    892       dlclose(psc->driver);
    893    glx_screen_cleanup(&psc->base);
    894    free(psc);
    895 
    896    return NULL;
    897 }
    898 
    899 /* Called from __glXFreeDisplayPrivate.
    900  */
    901 static void
    902 driDestroyDisplay(__GLXDRIdisplay * dpy)
    903 {
    904    free(dpy);
    905 }
    906 
    907 /*
    908  * Allocate, initialize and return a __DRIdisplayPrivate object.
    909  * This is called from __glXInitialize() when we are given a new
    910  * display pointer.
    911  */
    912 _X_HIDDEN __GLXDRIdisplay *
    913 driCreateDisplay(Display * dpy)
    914 {
    915    struct dri_display *pdpyp;
    916    int eventBase, errorBase;
    917    int major, minor, patch;
    918 
    919    if (!XF86DRIQueryExtension(dpy, &eventBase, &errorBase)) {
    920       return NULL;
    921    }
    922 
    923    if (!XF86DRIQueryVersion(dpy, &major, &minor, &patch)) {
    924       return NULL;
    925    }
    926 
    927    pdpyp = malloc(sizeof *pdpyp);
    928    if (!pdpyp) {
    929       return NULL;
    930    }
    931 
    932    pdpyp->driMajor = major;
    933    pdpyp->driMinor = minor;
    934    pdpyp->driPatch = patch;
    935 
    936    pdpyp->base.destroyDisplay = driDestroyDisplay;
    937    pdpyp->base.createScreen = driCreateScreen;
    938 
    939    return &pdpyp->base;
    940 }
    941 
    942 #endif /* GLX_DIRECT_RENDERING */
    943