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