Home | History | Annotate | Download | only in glx
      1 /*
      2  * Copyright  2013 Keith Packard
      3  *
      4  * Permission to use, copy, modify, distribute, and sell this software and its
      5  * documentation for any purpose is hereby granted without fee, provided that
      6  * the above copyright notice appear in all copies and that both that copyright
      7  * notice and this permission notice appear in supporting documentation, and
      8  * that the name of the copyright holders not be used in advertising or
      9  * publicity pertaining to distribution of the software without specific,
     10  * written prior permission.  The copyright holders make no representations
     11  * about the suitability of this software for any purpose.  It is provided "as
     12  * is" without express or implied warranty.
     13  *
     14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
     20  * OF THIS SOFTWARE.
     21  */
     22 
     23 /*
     24  * Portions of this code were adapted from dri2_glx.c which carries the
     25  * following copyright:
     26  *
     27  * Copyright  2008 Red Hat, Inc.
     28  *
     29  * Permission is hereby granted, free of charge, to any person obtaining a
     30  * copy of this software and associated documentation files (the "Soft-
     31  * ware"), to deal in the Software without restriction, including without
     32  * limitation the rights to use, copy, modify, merge, publish, distribute,
     33  * and/or sell copies of the Software, and to permit persons to whom the
     34  * Software is furnished to do so, provided that the above copyright
     35  * notice(s) and this permission notice appear in all copies of the Soft-
     36  * ware and that both the above copyright notice(s) and this permission
     37  * notice appear in supporting documentation.
     38  *
     39  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     40  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
     41  * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
     42  * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
     43  * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
     44  * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     45  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     46  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
     47  * MANCE OF THIS SOFTWARE.
     48  *
     49  * Except as contained in this notice, the name of a copyright holder shall
     50  * not be used in advertising or otherwise to promote the sale, use or
     51  * other dealings in this Software without prior written authorization of
     52  * the copyright holder.
     53  *
     54  * Authors:
     55  *   Kristian Hgsberg (krh (at) redhat.com)
     56  */
     57 
     58 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
     59 
     60 #include <X11/Xlib.h>
     61 #include <X11/extensions/Xfixes.h>
     62 #include <X11/Xlib-xcb.h>
     63 #include <X11/xshmfence.h>
     64 #include <xcb/xcb.h>
     65 #include <xcb/dri3.h>
     66 #include <xcb/present.h>
     67 #include <GL/gl.h>
     68 #include "glxclient.h"
     69 #include <dlfcn.h>
     70 #include <fcntl.h>
     71 #include <unistd.h>
     72 #include <sys/types.h>
     73 #include <sys/mman.h>
     74 #include <sys/time.h>
     75 
     76 #include "dri_common.h"
     77 #include "dri3_priv.h"
     78 #include "loader.h"
     79 #include "dri2.h"
     80 
     81 static struct dri3_drawable *
     82 loader_drawable_to_dri3_drawable(struct loader_dri3_drawable *draw) {
     83    size_t offset = offsetof(struct dri3_drawable, loader_drawable);
     84    if (!draw)
     85       return NULL;
     86    return (struct dri3_drawable *)(((void*) draw) - offset);
     87 }
     88 
     89 static int
     90 glx_dri3_get_swap_interval(struct loader_dri3_drawable *draw)
     91 {
     92    struct dri3_drawable *priv = loader_drawable_to_dri3_drawable(draw);
     93 
     94    return priv->swap_interval;
     95 }
     96 
     97 static int
     98 glx_dri3_clamp_swap_interval(struct loader_dri3_drawable *draw, int interval)
     99 {
    100    return interval;
    101 }
    102 
    103 static void
    104 glx_dri3_set_swap_interval(struct loader_dri3_drawable *draw, int interval)
    105 {
    106    struct dri3_drawable *priv = loader_drawable_to_dri3_drawable(draw);
    107 
    108    priv->swap_interval = interval;
    109 }
    110 
    111 static void
    112 glx_dri3_set_drawable_size(struct loader_dri3_drawable *draw,
    113                            int width, int height)
    114 {
    115    /* Nothing to do */
    116 }
    117 
    118 static bool
    119 glx_dri3_in_current_context(struct loader_dri3_drawable *draw)
    120 {
    121    struct dri3_drawable *priv = loader_drawable_to_dri3_drawable(draw);
    122 
    123    if (!priv)
    124       return false;
    125 
    126    struct dri3_context *pcp = (struct dri3_context *) __glXGetCurrentContext();
    127    struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
    128 
    129    return (&pcp->base != &dummyContext) && pcp->base.psc == &psc->base;
    130 }
    131 
    132 static __DRIcontext *
    133 glx_dri3_get_dri_context(struct loader_dri3_drawable *draw)
    134 {
    135    struct glx_context *gc = __glXGetCurrentContext();
    136    struct dri3_context *dri3Ctx = (struct dri3_context *) gc;
    137 
    138    return (gc != &dummyContext) ? dri3Ctx->driContext : NULL;
    139 }
    140 
    141 static __DRIscreen *
    142 glx_dri3_get_dri_screen(struct loader_dri3_drawable *draw)
    143 {
    144    struct glx_context *gc = __glXGetCurrentContext();
    145    struct dri3_context *pcp = (struct dri3_context *) gc;
    146    struct dri3_screen *psc = (struct dri3_screen *) pcp->base.psc;
    147 
    148    return (gc != &dummyContext && psc) ? psc->driScreen : NULL;
    149 }
    150 
    151 static void
    152 glx_dri3_flush_drawable(struct loader_dri3_drawable *draw, unsigned flags)
    153 {
    154    loader_dri3_flush(draw, flags, __DRI2_THROTTLE_SWAPBUFFER);
    155 }
    156 
    157 static void
    158 glx_dri3_show_fps(struct loader_dri3_drawable *draw, uint64_t current_ust)
    159 {
    160    struct dri3_drawable *priv = loader_drawable_to_dri3_drawable(draw);
    161    const uint64_t interval =
    162       ((struct dri3_screen *) priv->base.psc)->show_fps_interval;
    163 
    164    if (!interval)
    165       return;
    166 
    167    priv->frames++;
    168 
    169    /* DRI3+Present together uses microseconds for UST. */
    170    if (priv->previous_ust + interval * 1000000 <= current_ust) {
    171       if (priv->previous_ust) {
    172          fprintf(stderr, "libGL: FPS = %.1f\n",
    173                  ((uint64_t) priv->frames * 1000000) /
    174                  (double)(current_ust - priv->previous_ust));
    175       }
    176       priv->frames = 0;
    177       priv->previous_ust = current_ust;
    178    }
    179 }
    180 
    181 static const struct loader_dri3_vtable glx_dri3_vtable = {
    182    .get_swap_interval = glx_dri3_get_swap_interval,
    183    .clamp_swap_interval = glx_dri3_clamp_swap_interval,
    184    .set_swap_interval = glx_dri3_set_swap_interval,
    185    .set_drawable_size = glx_dri3_set_drawable_size,
    186    .in_current_context = glx_dri3_in_current_context,
    187    .get_dri_context = glx_dri3_get_dri_context,
    188    .get_dri_screen = glx_dri3_get_dri_screen,
    189    .flush_drawable = glx_dri3_flush_drawable,
    190    .show_fps = glx_dri3_show_fps,
    191 };
    192 
    193 
    194 static const struct glx_context_vtable dri3_context_vtable;
    195 
    196 static void
    197 dri3_destroy_context(struct glx_context *context)
    198 {
    199    struct dri3_context *pcp = (struct dri3_context *) context;
    200    struct dri3_screen *psc = (struct dri3_screen *) context->psc;
    201 
    202    driReleaseDrawables(&pcp->base);
    203 
    204    free((char *) context->extensions);
    205 
    206    (*psc->core->destroyContext) (pcp->driContext);
    207 
    208    free(pcp);
    209 }
    210 
    211 static Bool
    212 dri3_bind_context(struct glx_context *context, struct glx_context *old,
    213                   GLXDrawable draw, GLXDrawable read)
    214 {
    215    struct dri3_context *pcp = (struct dri3_context *) context;
    216    struct dri3_screen *psc = (struct dri3_screen *) pcp->base.psc;
    217    struct dri3_drawable *pdraw, *pread;
    218    __DRIdrawable *dri_draw = NULL, *dri_read = NULL;
    219 
    220    pdraw = (struct dri3_drawable *) driFetchDrawable(context, draw);
    221    pread = (struct dri3_drawable *) driFetchDrawable(context, read);
    222 
    223    driReleaseDrawables(&pcp->base);
    224 
    225    if (pdraw)
    226       dri_draw = pdraw->loader_drawable.dri_drawable;
    227    else if (draw != None)
    228       return GLXBadDrawable;
    229 
    230    if (pread)
    231       dri_read = pread->loader_drawable.dri_drawable;
    232    else if (read != None)
    233       return GLXBadDrawable;
    234 
    235    if (!(*psc->core->bindContext) (pcp->driContext, dri_draw, dri_read))
    236       return GLXBadContext;
    237 
    238    return Success;
    239 }
    240 
    241 static void
    242 dri3_unbind_context(struct glx_context *context, struct glx_context *new)
    243 {
    244    struct dri3_context *pcp = (struct dri3_context *) context;
    245    struct dri3_screen *psc = (struct dri3_screen *) pcp->base.psc;
    246 
    247    (*psc->core->unbindContext) (pcp->driContext);
    248 }
    249 
    250 static struct glx_context *
    251 dri3_create_context_attribs(struct glx_screen *base,
    252                             struct glx_config *config_base,
    253                             struct glx_context *shareList,
    254                             unsigned num_attribs,
    255                             const uint32_t *attribs,
    256                             unsigned *error)
    257 {
    258    struct dri3_context *pcp = NULL;
    259    struct dri3_context *pcp_shared = NULL;
    260    struct dri3_screen *psc = (struct dri3_screen *) base;
    261    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
    262    __DRIcontext *shared = NULL;
    263 
    264    uint32_t minor_ver = 1;
    265    uint32_t major_ver = 2;
    266    uint32_t flags = 0;
    267    unsigned api;
    268    int reset = __DRI_CTX_RESET_NO_NOTIFICATION;
    269    uint32_t ctx_attribs[2 * 5];
    270    unsigned num_ctx_attribs = 0;
    271    uint32_t render_type;
    272 
    273    /* Remap the GLX tokens to DRI2 tokens.
    274     */
    275    if (!dri2_convert_glx_attribs(num_attribs, attribs,
    276                                  &major_ver, &minor_ver,
    277                                  &render_type, &flags, &api,
    278                                  &reset, error))
    279       goto error_exit;
    280 
    281    /* Check the renderType value */
    282    if (!validate_renderType_against_config(config_base, render_type))
    283        goto error_exit;
    284 
    285    if (shareList) {
    286       pcp_shared = (struct dri3_context *) shareList;
    287       shared = pcp_shared->driContext;
    288    }
    289 
    290    pcp = calloc(1, sizeof *pcp);
    291    if (pcp == NULL) {
    292       *error = __DRI_CTX_ERROR_NO_MEMORY;
    293       goto error_exit;
    294    }
    295 
    296    if (!glx_context_init(&pcp->base, &psc->base, &config->base))
    297       goto error_exit;
    298 
    299    ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
    300    ctx_attribs[num_ctx_attribs++] = major_ver;
    301    ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
    302    ctx_attribs[num_ctx_attribs++] = minor_ver;
    303 
    304    /* Only send a value when the non-default value is requested.  By doing
    305     * this we don't have to check the driver's DRI3 version before sending the
    306     * default value.
    307     */
    308    if (reset != __DRI_CTX_RESET_NO_NOTIFICATION) {
    309       ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
    310       ctx_attribs[num_ctx_attribs++] = reset;
    311    }
    312 
    313    if (flags != 0) {
    314       ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
    315 
    316       /* The current __DRI_CTX_FLAG_* values are identical to the
    317        * GLX_CONTEXT_*_BIT values.
    318        */
    319       ctx_attribs[num_ctx_attribs++] = flags;
    320    }
    321 
    322    pcp->driContext =
    323       (*psc->image_driver->createContextAttribs) (psc->driScreen,
    324                                                   api,
    325                                                   config->driConfig,
    326                                                   shared,
    327                                                   num_ctx_attribs / 2,
    328                                                   ctx_attribs,
    329                                                   error,
    330                                                   pcp);
    331 
    332    if (pcp->driContext == NULL)
    333       goto error_exit;
    334 
    335    pcp->base.vtable = &dri3_context_vtable;
    336 
    337    return &pcp->base;
    338 
    339 error_exit:
    340    free(pcp);
    341 
    342    return NULL;
    343 }
    344 
    345 static struct glx_context *
    346 dri3_create_context(struct glx_screen *base,
    347                     struct glx_config *config_base,
    348                     struct glx_context *shareList, int renderType)
    349 {
    350    unsigned int error;
    351 
    352    return dri3_create_context_attribs(base, config_base, shareList,
    353                                       0, NULL, &error);
    354 }
    355 
    356 static void
    357 dri3_destroy_drawable(__GLXDRIdrawable *base)
    358 {
    359    struct dri3_drawable *pdraw = (struct dri3_drawable *) base;
    360 
    361    loader_dri3_drawable_fini(&pdraw->loader_drawable);
    362 
    363    free(pdraw);
    364 }
    365 
    366 static __GLXDRIdrawable *
    367 dri3_create_drawable(struct glx_screen *base, XID xDrawable,
    368                      GLXDrawable drawable, struct glx_config *config_base)
    369 {
    370    struct dri3_drawable *pdraw;
    371    struct dri3_screen *psc = (struct dri3_screen *) base;
    372    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
    373 
    374    pdraw = calloc(1, sizeof(*pdraw));
    375    if (!pdraw)
    376       return NULL;
    377 
    378    pdraw->base.destroyDrawable = dri3_destroy_drawable;
    379    pdraw->base.xDrawable = xDrawable;
    380    pdraw->base.drawable = drawable;
    381    pdraw->base.psc = &psc->base;
    382 
    383    (void) __glXInitialize(psc->base.dpy);
    384 
    385    if (loader_dri3_drawable_init(XGetXCBConnection(base->dpy),
    386                                  xDrawable, psc->driScreen,
    387                                  psc->is_different_gpu, config->driConfig,
    388                                  &psc->loader_dri3_ext, &glx_dri3_vtable,
    389                                  &pdraw->loader_drawable)) {
    390       free(pdraw);
    391       return NULL;
    392    }
    393 
    394    return &pdraw->base;
    395 }
    396 
    397 /** dri3_wait_for_msc
    398  *
    399  * Get the X server to send an event when the target msc/divisor/remainder is
    400  * reached.
    401  */
    402 static int
    403 dri3_wait_for_msc(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
    404                   int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc)
    405 {
    406    struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
    407 
    408    loader_dri3_wait_for_msc(&priv->loader_drawable, target_msc, divisor,
    409                             remainder, ust, msc, sbc);
    410 
    411    return 1;
    412 }
    413 
    414 /** dri3_drawable_get_msc
    415  *
    416  * Return the current UST/MSC/SBC triplet by asking the server
    417  * for an event
    418  */
    419 static int
    420 dri3_drawable_get_msc(struct glx_screen *psc, __GLXDRIdrawable *pdraw,
    421                       int64_t *ust, int64_t *msc, int64_t *sbc)
    422 {
    423    return dri3_wait_for_msc(pdraw, 0, 0, 0, ust, msc,sbc);
    424 }
    425 
    426 /** dri3_wait_for_sbc
    427  *
    428  * Wait for the completed swap buffer count to reach the specified
    429  * target. Presumably the application knows that this will be reached with
    430  * outstanding complete events, or we're going to be here awhile.
    431  */
    432 static int
    433 dri3_wait_for_sbc(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
    434                   int64_t *msc, int64_t *sbc)
    435 {
    436    struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
    437 
    438    return loader_dri3_wait_for_sbc(&priv->loader_drawable, target_sbc,
    439                                    ust, msc, sbc);
    440 }
    441 
    442 static void
    443 dri3_copy_sub_buffer(__GLXDRIdrawable *pdraw, int x, int y,
    444                      int width, int height,
    445                      Bool flush)
    446 {
    447    struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
    448 
    449    loader_dri3_copy_sub_buffer(&priv->loader_drawable, x, y,
    450                                width, height, flush);
    451 }
    452 
    453 static void
    454 dri3_wait_x(struct glx_context *gc)
    455 {
    456    struct dri3_drawable *priv = (struct dri3_drawable *)
    457       GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
    458 
    459    if (priv)
    460       loader_dri3_wait_x(&priv->loader_drawable);
    461 }
    462 
    463 static void
    464 dri3_wait_gl(struct glx_context *gc)
    465 {
    466    struct dri3_drawable *priv = (struct dri3_drawable *)
    467       GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
    468 
    469    if (priv)
    470       loader_dri3_wait_gl(&priv->loader_drawable);
    471 }
    472 
    473 /**
    474  * Called by the driver when it needs to update the real front buffer with the
    475  * contents of its fake front buffer.
    476  */
    477 static void
    478 dri3_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate)
    479 {
    480    struct loader_dri3_drawable *draw = loaderPrivate;
    481    struct dri3_drawable *pdraw = loader_drawable_to_dri3_drawable(draw);
    482    struct dri3_screen *psc;
    483 
    484    if (!pdraw)
    485       return;
    486 
    487    if (!pdraw->base.psc)
    488       return;
    489 
    490    psc = (struct dri3_screen *) pdraw->base.psc;
    491 
    492    (void) __glXInitialize(psc->base.dpy);
    493 
    494    loader_dri3_flush(draw, __DRI2_FLUSH_DRAWABLE, __DRI2_THROTTLE_FLUSHFRONT);
    495 
    496    loader_dri3_wait_gl(draw);
    497 }
    498 
    499 /* The image loader extension record for DRI3
    500  */
    501 static const __DRIimageLoaderExtension imageLoaderExtension = {
    502    .base = { __DRI_IMAGE_LOADER, 1 },
    503 
    504    .getBuffers          = loader_dri3_get_buffers,
    505    .flushFrontBuffer    = dri3_flush_front_buffer,
    506 };
    507 
    508 const __DRIuseInvalidateExtension dri3UseInvalidate = {
    509    .base = { __DRI_USE_INVALIDATE, 1 }
    510 };
    511 
    512 static const __DRIextension *loader_extensions[] = {
    513    &imageLoaderExtension.base,
    514    &systemTimeExtension.base,
    515    &dri3UseInvalidate.base,
    516    NULL
    517 };
    518 
    519 /** dri3_swap_buffers
    520  *
    521  * Make the current back buffer visible using the present extension
    522  */
    523 static int64_t
    524 dri3_swap_buffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
    525                   int64_t remainder, Bool flush)
    526 {
    527    struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
    528    unsigned flags = __DRI2_FLUSH_DRAWABLE;
    529 
    530    if (flush)
    531       flags |= __DRI2_FLUSH_CONTEXT;
    532 
    533    return loader_dri3_swap_buffers_msc(&priv->loader_drawable,
    534                                        target_msc, divisor, remainder,
    535                                        flags, false);
    536 }
    537 
    538 static int
    539 dri3_get_buffer_age(__GLXDRIdrawable *pdraw)
    540 {
    541    struct dri3_drawable *priv = (struct dri3_drawable *)pdraw;
    542 
    543    return loader_dri3_query_buffer_age(&priv->loader_drawable);
    544 }
    545 
    546 /** dri3_destroy_screen
    547  */
    548 static void
    549 dri3_destroy_screen(struct glx_screen *base)
    550 {
    551    struct dri3_screen *psc = (struct dri3_screen *) base;
    552 
    553    /* Free the direct rendering per screen data */
    554    (*psc->core->destroyScreen) (psc->driScreen);
    555    driDestroyConfigs(psc->driver_configs);
    556    close(psc->fd);
    557    free(psc);
    558 }
    559 
    560 /** dri3_set_swap_interval
    561  *
    562  * Record the application swap interval specification,
    563  */
    564 static int
    565 dri3_set_swap_interval(__GLXDRIdrawable *pdraw, int interval)
    566 {
    567    assert(pdraw != NULL);
    568 
    569    struct dri3_drawable *priv =  (struct dri3_drawable *) pdraw;
    570    GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
    571    struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
    572 
    573    if (psc->config)
    574       psc->config->configQueryi(psc->driScreen,
    575                                 "vblank_mode", &vblank_mode);
    576 
    577    switch (vblank_mode) {
    578    case DRI_CONF_VBLANK_NEVER:
    579       if (interval != 0)
    580          return GLX_BAD_VALUE;
    581       break;
    582    case DRI_CONF_VBLANK_ALWAYS_SYNC:
    583       if (interval <= 0)
    584          return GLX_BAD_VALUE;
    585       break;
    586    default:
    587       break;
    588    }
    589 
    590    loader_dri3_set_swap_interval(&priv->loader_drawable, interval);
    591 
    592    return 0;
    593 }
    594 
    595 /** dri3_get_swap_interval
    596  *
    597  * Return the stored swap interval
    598  */
    599 static int
    600 dri3_get_swap_interval(__GLXDRIdrawable *pdraw)
    601 {
    602    assert(pdraw != NULL);
    603 
    604    struct dri3_drawable *priv =  (struct dri3_drawable *) pdraw;
    605 
    606   return priv->swap_interval;
    607 }
    608 
    609 static void
    610 dri3_bind_tex_image(Display * dpy,
    611                     GLXDrawable drawable,
    612                     int buffer, const int *attrib_list)
    613 {
    614    struct glx_context *gc = __glXGetCurrentContext();
    615    struct dri3_context *pcp = (struct dri3_context *) gc;
    616    __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
    617    struct dri3_drawable *pdraw = (struct dri3_drawable *) base;
    618    struct dri3_screen *psc;
    619 
    620    if (pdraw != NULL) {
    621       psc = (struct dri3_screen *) base->psc;
    622 
    623       (*psc->f->invalidate)(pdraw->loader_drawable.dri_drawable);
    624 
    625       XSync(dpy, false);
    626 
    627       (*psc->texBuffer->setTexBuffer2) (pcp->driContext,
    628                                         pdraw->base.textureTarget,
    629                                         pdraw->base.textureFormat,
    630                                         pdraw->loader_drawable.dri_drawable);
    631    }
    632 }
    633 
    634 static void
    635 dri3_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
    636 {
    637    struct glx_context *gc = __glXGetCurrentContext();
    638    struct dri3_context *pcp = (struct dri3_context *) gc;
    639    __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
    640    struct dri3_drawable *pdraw = (struct dri3_drawable *) base;
    641    struct dri3_screen *psc;
    642 
    643    if (pdraw != NULL) {
    644       psc = (struct dri3_screen *) base->psc;
    645 
    646       if (psc->texBuffer->base.version >= 3 &&
    647           psc->texBuffer->releaseTexBuffer != NULL)
    648          (*psc->texBuffer->releaseTexBuffer) (pcp->driContext,
    649                                               pdraw->base.textureTarget,
    650                                               pdraw->loader_drawable.dri_drawable);
    651    }
    652 }
    653 
    654 static const struct glx_context_vtable dri3_context_vtable = {
    655    .destroy             = dri3_destroy_context,
    656    .bind                = dri3_bind_context,
    657    .unbind              = dri3_unbind_context,
    658    .wait_gl             = dri3_wait_gl,
    659    .wait_x              = dri3_wait_x,
    660    .use_x_font          = DRI_glXUseXFont,
    661    .bind_tex_image      = dri3_bind_tex_image,
    662    .release_tex_image   = dri3_release_tex_image,
    663    .get_proc_address    = NULL,
    664    .interop_query_device_info = dri3_interop_query_device_info,
    665    .interop_export_object = dri3_interop_export_object
    666 };
    667 
    668 /** dri3_bind_extensions
    669  *
    670  * Enable all of the extensions supported on DRI3
    671  */
    672 static void
    673 dri3_bind_extensions(struct dri3_screen *psc, struct glx_display * priv,
    674                      const char *driverName)
    675 {
    676    const __DRIextension **extensions;
    677    unsigned mask;
    678    int i;
    679 
    680    extensions = psc->core->getExtensions(psc->driScreen);
    681 
    682    __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync");
    683    __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control");
    684    __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control");
    685    __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
    686    __glXEnableDirectExtension(&psc->base, "GLX_INTEL_swap_event");
    687 
    688    mask = psc->image_driver->getAPIMask(psc->driScreen);
    689 
    690    __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context");
    691    __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context_profile");
    692 
    693    if ((mask & ((1 << __DRI_API_GLES) |
    694                 (1 << __DRI_API_GLES2) |
    695                 (1 << __DRI_API_GLES3))) != 0) {
    696       __glXEnableDirectExtension(&psc->base,
    697                                  "GLX_EXT_create_context_es_profile");
    698       __glXEnableDirectExtension(&psc->base,
    699                                  "GLX_EXT_create_context_es2_profile");
    700    }
    701 
    702    for (i = 0; extensions[i]; i++) {
    703       /* when on a different gpu than the server, the server pixmaps
    704        * can have a tiling mode we can't read. Thus we can't create
    705        * a texture from them.
    706        */
    707       if (!psc->is_different_gpu &&
    708          (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) {
    709          psc->texBuffer = (__DRItexBufferExtension *) extensions[i];
    710          __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap");
    711       }
    712 
    713       if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0)) {
    714          psc->f = (__DRI2flushExtension *) extensions[i];
    715          /* internal driver extension, no GL extension exposed */
    716       }
    717 
    718       if (strcmp(extensions[i]->name, __DRI_IMAGE) == 0)
    719          psc->image = (__DRIimageExtension *) extensions[i];
    720 
    721       if ((strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0))
    722          psc->config = (__DRI2configQueryExtension *) extensions[i];
    723 
    724       if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0)
    725          __glXEnableDirectExtension(&psc->base,
    726                                     "GLX_ARB_create_context_robustness");
    727 
    728       if (strcmp(extensions[i]->name, __DRI2_RENDERER_QUERY) == 0) {
    729          psc->rendererQuery = (__DRI2rendererQueryExtension *) extensions[i];
    730          __glXEnableDirectExtension(&psc->base, "GLX_MESA_query_renderer");
    731       }
    732 
    733       if (strcmp(extensions[i]->name, __DRI2_INTEROP) == 0)
    734 	 psc->interop = (__DRI2interopExtension*)extensions[i];
    735    }
    736 }
    737 
    738 static const struct glx_screen_vtable dri3_screen_vtable = {
    739    .create_context         = dri3_create_context,
    740    .create_context_attribs = dri3_create_context_attribs,
    741    .query_renderer_integer = dri3_query_renderer_integer,
    742    .query_renderer_string  = dri3_query_renderer_string,
    743 };
    744 
    745 /** dri3_create_screen
    746  *
    747  * Initialize DRI3 on the specified screen.
    748  *
    749  * Opens the DRI device, locates the appropriate DRI driver
    750  * and loads that.
    751  *
    752  * Checks to see if the driver supports the necessary extensions
    753  *
    754  * Initializes the driver for the screen and sets up our structures
    755  */
    756 
    757 static struct glx_screen *
    758 dri3_create_screen(int screen, struct glx_display * priv)
    759 {
    760    xcb_connection_t *c = XGetXCBConnection(priv->dpy);
    761    const __DRIconfig **driver_configs;
    762    const __DRIextension **extensions;
    763    const struct dri3_display *const pdp = (struct dri3_display *)
    764       priv->dri3Display;
    765    struct dri3_screen *psc;
    766    __GLXDRIscreen *psp;
    767    struct glx_config *configs = NULL, *visuals = NULL;
    768    char *driverName, *deviceName, *tmp;
    769    int i;
    770 
    771    psc = calloc(1, sizeof *psc);
    772    if (psc == NULL)
    773       return NULL;
    774 
    775    psc->fd = -1;
    776 
    777    if (!glx_screen_init(&psc->base, screen, priv)) {
    778       free(psc);
    779       return NULL;
    780    }
    781 
    782    psc->fd = loader_dri3_open(c, RootWindow(priv->dpy, screen), None);
    783    if (psc->fd < 0) {
    784       int conn_error = xcb_connection_has_error(c);
    785 
    786       glx_screen_cleanup(&psc->base);
    787       free(psc);
    788       InfoMessageF("screen %d does not appear to be DRI3 capable\n", screen);
    789 
    790       if (conn_error)
    791          ErrorMessageF("Connection closed during DRI3 initialization failure");
    792 
    793       return NULL;
    794    }
    795 
    796    psc->fd = loader_get_user_preferred_fd(psc->fd, &psc->is_different_gpu);
    797    deviceName = NULL;
    798 
    799    driverName = loader_get_driver_for_fd(psc->fd);
    800    if (!driverName) {
    801       ErrorMessageF("No driver found\n");
    802       goto handle_error;
    803    }
    804 
    805    psc->driver = driOpenDriver(driverName);
    806    if (psc->driver == NULL) {
    807       ErrorMessageF("driver pointer missing\n");
    808       goto handle_error;
    809    }
    810 
    811    extensions = driGetDriverExtensions(psc->driver, driverName);
    812    if (extensions == NULL)
    813       goto handle_error;
    814 
    815    for (i = 0; extensions[i]; i++) {
    816       if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
    817          psc->core = (__DRIcoreExtension *) extensions[i];
    818       if (strcmp(extensions[i]->name, __DRI_IMAGE_DRIVER) == 0)
    819          psc->image_driver = (__DRIimageDriverExtension *) extensions[i];
    820    }
    821 
    822 
    823    if (psc->core == NULL) {
    824       ErrorMessageF("core dri driver extension not found\n");
    825       goto handle_error;
    826    }
    827 
    828    if (psc->image_driver == NULL) {
    829       ErrorMessageF("image driver extension not found\n");
    830       goto handle_error;
    831    }
    832 
    833    psc->driScreen =
    834       psc->image_driver->createNewScreen2(screen, psc->fd,
    835                                           pdp->loader_extensions,
    836                                           extensions,
    837                                           &driver_configs, psc);
    838 
    839    if (psc->driScreen == NULL) {
    840       ErrorMessageF("failed to create dri screen\n");
    841       goto handle_error;
    842    }
    843 
    844    dri3_bind_extensions(psc, priv, driverName);
    845 
    846    if (!psc->image || psc->image->base.version < 7 || !psc->image->createImageFromFds) {
    847       ErrorMessageF("Version 7 or imageFromFds image extension not found\n");
    848       goto handle_error;
    849    }
    850 
    851    if (!psc->f || psc->f->base.version < 4) {
    852       ErrorMessageF("Version 4 or later of flush extension not found\n");
    853       goto handle_error;
    854    }
    855 
    856    if (psc->is_different_gpu && psc->image->base.version < 9) {
    857       ErrorMessageF("Different GPU, but image extension version 9 or later not found\n");
    858       goto handle_error;
    859    }
    860 
    861    if (psc->is_different_gpu && !psc->image->blitImage) {
    862       ErrorMessageF("Different GPU, but blitImage not implemented for this driver\n");
    863       goto handle_error;
    864    }
    865 
    866    if (!psc->is_different_gpu && (
    867        !psc->texBuffer || psc->texBuffer->base.version < 2 ||
    868        !psc->texBuffer->setTexBuffer2
    869        )) {
    870       ErrorMessageF("Version 2 or later of texBuffer extension not found\n");
    871       goto handle_error;
    872    }
    873 
    874    psc->loader_dri3_ext.core = psc->core;
    875    psc->loader_dri3_ext.image_driver = psc->image_driver;
    876    psc->loader_dri3_ext.flush = psc->f;
    877    psc->loader_dri3_ext.tex_buffer = psc->texBuffer;
    878    psc->loader_dri3_ext.image = psc->image;
    879    psc->loader_dri3_ext.config = psc->config;
    880 
    881    configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs);
    882    visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
    883 
    884    if (!configs || !visuals) {
    885        ErrorMessageF("No matching fbConfigs or visuals found\n");
    886        goto handle_error;
    887    }
    888 
    889    glx_config_destroy_list(psc->base.configs);
    890    psc->base.configs = configs;
    891    glx_config_destroy_list(psc->base.visuals);
    892    psc->base.visuals = visuals;
    893 
    894    psc->driver_configs = driver_configs;
    895 
    896    psc->base.vtable = &dri3_screen_vtable;
    897    psp = &psc->vtable;
    898    psc->base.driScreen = psp;
    899    psp->destroyScreen = dri3_destroy_screen;
    900    psp->createDrawable = dri3_create_drawable;
    901    psp->swapBuffers = dri3_swap_buffers;
    902 
    903    psp->getDrawableMSC = dri3_drawable_get_msc;
    904    psp->waitForMSC = dri3_wait_for_msc;
    905    psp->waitForSBC = dri3_wait_for_sbc;
    906    psp->setSwapInterval = dri3_set_swap_interval;
    907    psp->getSwapInterval = dri3_get_swap_interval;
    908    __glXEnableDirectExtension(&psc->base, "GLX_OML_sync_control");
    909 
    910    psp->copySubBuffer = dri3_copy_sub_buffer;
    911    __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
    912 
    913    psp->getBufferAge = dri3_get_buffer_age;
    914    __glXEnableDirectExtension(&psc->base, "GLX_EXT_buffer_age");
    915 
    916    free(driverName);
    917    free(deviceName);
    918 
    919    tmp = getenv("LIBGL_SHOW_FPS");
    920    psc->show_fps_interval = tmp ? atoi(tmp) : 0;
    921    if (psc->show_fps_interval < 0)
    922       psc->show_fps_interval = 0;
    923 
    924    InfoMessageF("Using DRI3 for screen %d\n", screen);
    925 
    926    return &psc->base;
    927 
    928 handle_error:
    929    CriticalErrorMessageF("failed to load driver: %s\n", driverName);
    930 
    931    if (configs)
    932        glx_config_destroy_list(configs);
    933    if (visuals)
    934        glx_config_destroy_list(visuals);
    935    if (psc->driScreen)
    936        psc->core->destroyScreen(psc->driScreen);
    937    psc->driScreen = NULL;
    938    if (psc->fd >= 0)
    939       close(psc->fd);
    940    if (psc->driver)
    941       dlclose(psc->driver);
    942 
    943    free(driverName);
    944    free(deviceName);
    945    glx_screen_cleanup(&psc->base);
    946    free(psc);
    947 
    948    return NULL;
    949 }
    950 
    951 /** dri_destroy_display
    952  *
    953  * Called from __glXFreeDisplayPrivate.
    954  */
    955 static void
    956 dri3_destroy_display(__GLXDRIdisplay * dpy)
    957 {
    958    free(dpy);
    959 }
    960 
    961 /** dri3_create_display
    962  *
    963  * Allocate, initialize and return a __DRIdisplayPrivate object.
    964  * This is called from __glXInitialize() when we are given a new
    965  * display pointer. This is public to that function, but hidden from
    966  * outside of libGL.
    967  */
    968 _X_HIDDEN __GLXDRIdisplay *
    969 dri3_create_display(Display * dpy)
    970 {
    971    struct dri3_display                  *pdp;
    972    xcb_connection_t                     *c = XGetXCBConnection(dpy);
    973    xcb_dri3_query_version_cookie_t      dri3_cookie;
    974    xcb_dri3_query_version_reply_t       *dri3_reply;
    975    xcb_present_query_version_cookie_t   present_cookie;
    976    xcb_present_query_version_reply_t    *present_reply;
    977    xcb_generic_error_t                  *error;
    978    const xcb_query_extension_reply_t    *extension;
    979 
    980    xcb_prefetch_extension_data(c, &xcb_dri3_id);
    981    xcb_prefetch_extension_data(c, &xcb_present_id);
    982 
    983    extension = xcb_get_extension_data(c, &xcb_dri3_id);
    984    if (!(extension && extension->present))
    985       return NULL;
    986 
    987    extension = xcb_get_extension_data(c, &xcb_present_id);
    988    if (!(extension && extension->present))
    989       return NULL;
    990 
    991    dri3_cookie = xcb_dri3_query_version(c,
    992                                         XCB_DRI3_MAJOR_VERSION,
    993                                         XCB_DRI3_MINOR_VERSION);
    994 
    995 
    996    present_cookie = xcb_present_query_version(c,
    997                                    XCB_PRESENT_MAJOR_VERSION,
    998                                    XCB_PRESENT_MINOR_VERSION);
    999 
   1000    pdp = malloc(sizeof *pdp);
   1001    if (pdp == NULL)
   1002       return NULL;
   1003 
   1004    dri3_reply = xcb_dri3_query_version_reply(c, dri3_cookie, &error);
   1005    if (!dri3_reply) {
   1006       free(error);
   1007       goto no_extension;
   1008    }
   1009 
   1010    pdp->dri3Major = dri3_reply->major_version;
   1011    pdp->dri3Minor = dri3_reply->minor_version;
   1012    free(dri3_reply);
   1013 
   1014    present_reply = xcb_present_query_version_reply(c, present_cookie, &error);
   1015    if (!present_reply) {
   1016       free(error);
   1017       goto no_extension;
   1018    }
   1019    pdp->presentMajor = present_reply->major_version;
   1020    pdp->presentMinor = present_reply->minor_version;
   1021    free(present_reply);
   1022 
   1023    pdp->base.destroyDisplay = dri3_destroy_display;
   1024    pdp->base.createScreen = dri3_create_screen;
   1025 
   1026    loader_set_logger(dri_message);
   1027 
   1028    pdp->loader_extensions = loader_extensions;
   1029 
   1030    return &pdp->base;
   1031 no_extension:
   1032    free(pdp);
   1033    return NULL;
   1034 }
   1035 
   1036 #endif /* GLX_DIRECT_RENDERING */
   1037