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