Home | History | Annotate | Download | only in dri2
      1 /*
      2  * Copyright  2011 Intel Corporation
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     18  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
     19  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     20  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     22  * DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors:
     25  *    Kristian Hgsberg <krh (at) bitplanet.net>
     26  */
     27 
     28 #include <stdbool.h>
     29 #include <stdint.h>
     30 #include <stdlib.h>
     31 #include <string.h>
     32 #include <stdio.h>
     33 #include <limits.h>
     34 #include <dlfcn.h>
     35 #include <fcntl.h>
     36 #include <errno.h>
     37 #include <unistd.h>
     38 #ifdef HAVE_LIBDRM
     39 #include <xf86drm.h>
     40 #endif
     41 #include <sys/types.h>
     42 #include <sys/stat.h>
     43 
     44 #include "egl_dri2.h"
     45 #include "egl_dri2_fallbacks.h"
     46 #include "loader.h"
     47 
     48 #ifdef HAVE_DRI3
     49 #include "platform_x11_dri3.h"
     50 #endif
     51 
     52 static EGLBoolean
     53 dri2_x11_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
     54                        EGLint interval);
     55 
     56 static void
     57 swrastCreateDrawable(struct dri2_egl_display * dri2_dpy,
     58                      struct dri2_egl_surface * dri2_surf)
     59 {
     60    uint32_t           mask;
     61    const uint32_t     function = GXcopy;
     62    uint32_t           valgc[2];
     63 
     64    /* create GC's */
     65    dri2_surf->gc = xcb_generate_id(dri2_dpy->conn);
     66    mask = XCB_GC_FUNCTION;
     67    xcb_create_gc(dri2_dpy->conn, dri2_surf->gc, dri2_surf->drawable, mask, &function);
     68 
     69    dri2_surf->swapgc = xcb_generate_id(dri2_dpy->conn);
     70    mask = XCB_GC_FUNCTION | XCB_GC_GRAPHICS_EXPOSURES;
     71    valgc[0] = function;
     72    valgc[1] = False;
     73    xcb_create_gc(dri2_dpy->conn, dri2_surf->swapgc, dri2_surf->drawable, mask, valgc);
     74    switch (dri2_surf->depth) {
     75       case 32:
     76       case 24:
     77          dri2_surf->bytes_per_pixel = 4;
     78          break;
     79       case 16:
     80          dri2_surf->bytes_per_pixel = 2;
     81          break;
     82       case 8:
     83          dri2_surf->bytes_per_pixel = 1;
     84          break;
     85       case 0:
     86          dri2_surf->bytes_per_pixel = 0;
     87          break;
     88       default:
     89          _eglLog(_EGL_WARNING, "unsupported depth %d", dri2_surf->depth);
     90    }
     91 }
     92 
     93 static void
     94 swrastDestroyDrawable(struct dri2_egl_display * dri2_dpy,
     95                       struct dri2_egl_surface * dri2_surf)
     96 {
     97    xcb_free_gc(dri2_dpy->conn, dri2_surf->gc);
     98    xcb_free_gc(dri2_dpy->conn, dri2_surf->swapgc);
     99 }
    100 
    101 static void
    102 swrastGetDrawableInfo(__DRIdrawable * draw,
    103                       int *x, int *y, int *w, int *h,
    104                       void *loaderPrivate)
    105 {
    106    struct dri2_egl_surface *dri2_surf = loaderPrivate;
    107    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);
    108 
    109    xcb_get_geometry_cookie_t cookie;
    110    xcb_get_geometry_reply_t *reply;
    111    xcb_generic_error_t *error;
    112 
    113    *w = *h = 0;
    114    cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable);
    115    reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error);
    116    if (reply == NULL)
    117       return;
    118 
    119    if (error != NULL) {
    120       _eglLog(_EGL_WARNING, "error in xcb_get_geometry");
    121       free(error);
    122    } else {
    123       *w = reply->width;
    124       *h = reply->height;
    125    }
    126    free(reply);
    127 }
    128 
    129 static void
    130 swrastPutImage(__DRIdrawable * draw, int op,
    131                int x, int y, int w, int h,
    132                char *data, void *loaderPrivate)
    133 {
    134    struct dri2_egl_surface *dri2_surf = loaderPrivate;
    135    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);
    136 
    137    xcb_gcontext_t gc;
    138 
    139    switch (op) {
    140    case __DRI_SWRAST_IMAGE_OP_DRAW:
    141       gc = dri2_surf->gc;
    142       break;
    143    case __DRI_SWRAST_IMAGE_OP_SWAP:
    144       gc = dri2_surf->swapgc;
    145       break;
    146    default:
    147       return;
    148    }
    149 
    150    xcb_put_image(dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, dri2_surf->drawable,
    151                  gc, w, h, x, y, 0, dri2_surf->depth,
    152                  w*h*dri2_surf->bytes_per_pixel, (const uint8_t *)data);
    153 }
    154 
    155 static void
    156 swrastGetImage(__DRIdrawable * read,
    157                int x, int y, int w, int h,
    158                char *data, void *loaderPrivate)
    159 {
    160    struct dri2_egl_surface *dri2_surf = loaderPrivate;
    161    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);
    162 
    163    xcb_get_image_cookie_t cookie;
    164    xcb_get_image_reply_t *reply;
    165    xcb_generic_error_t *error;
    166 
    167    cookie = xcb_get_image (dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP,
    168                            dri2_surf->drawable, x, y, w, h, ~0);
    169    reply = xcb_get_image_reply (dri2_dpy->conn, cookie, &error);
    170    if (reply == NULL)
    171       return;
    172 
    173    if (error != NULL) {
    174       _eglLog(_EGL_WARNING, "error in xcb_get_image");
    175       free(error);
    176    } else {
    177       uint32_t bytes = xcb_get_image_data_length(reply);
    178       uint8_t *idata = xcb_get_image_data(reply);
    179       memcpy(data, idata, bytes);
    180    }
    181    free(reply);
    182 }
    183 
    184 
    185 static xcb_screen_t *
    186 get_xcb_screen(xcb_screen_iterator_t iter, int screen)
    187 {
    188     for (; iter.rem; --screen, xcb_screen_next(&iter))
    189         if (screen == 0)
    190             return iter.data;
    191 
    192     return NULL;
    193 }
    194 
    195 
    196 /**
    197  * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
    198  */
    199 static _EGLSurface *
    200 dri2_x11_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
    201                         _EGLConfig *conf, void *native_surface,
    202                         const EGLint *attrib_list)
    203 {
    204    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    205    struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
    206    struct dri2_egl_surface *dri2_surf;
    207    xcb_get_geometry_cookie_t cookie;
    208    xcb_get_geometry_reply_t *reply;
    209    xcb_generic_error_t *error;
    210    xcb_drawable_t drawable;
    211    const __DRIconfig *config;
    212 
    213    STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_surface));
    214    drawable = (uintptr_t) native_surface;
    215 
    216    (void) drv;
    217 
    218    dri2_surf = malloc(sizeof *dri2_surf);
    219    if (!dri2_surf) {
    220       _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
    221       return NULL;
    222    }
    223 
    224    if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
    225       goto cleanup_surf;
    226 
    227    dri2_surf->region = XCB_NONE;
    228    if (type == EGL_PBUFFER_BIT) {
    229       dri2_surf->drawable = xcb_generate_id(dri2_dpy->conn);
    230       xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize,
    231                        dri2_surf->drawable, dri2_dpy->screen->root,
    232 			dri2_surf->base.Width, dri2_surf->base.Height);
    233    } else {
    234       if (!drawable) {
    235          if (type == EGL_WINDOW_BIT)
    236             _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_create_surface");
    237          else
    238             _eglError(EGL_BAD_NATIVE_PIXMAP, "dri2_create_surface");
    239          goto cleanup_surf;
    240       }
    241       dri2_surf->drawable = drawable;
    242    }
    243 
    244    config = dri2_get_dri_config(dri2_conf, type,
    245                                 dri2_surf->base.GLColorspace);
    246 
    247    if (dri2_dpy->dri2) {
    248       dri2_surf->dri_drawable =
    249          dri2_dpy->dri2->createNewDrawable(dri2_dpy->dri_screen, config,
    250                                            dri2_surf);
    251    } else {
    252       assert(dri2_dpy->swrast);
    253       dri2_surf->dri_drawable =
    254          dri2_dpy->swrast->createNewDrawable(dri2_dpy->dri_screen, config,
    255                                              dri2_surf);
    256    }
    257 
    258    if (dri2_surf->dri_drawable == NULL) {
    259       _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
    260       goto cleanup_pixmap;
    261    }
    262 
    263    if (type != EGL_PBUFFER_BIT) {
    264       cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable);
    265       reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error);
    266       if (error != NULL) {
    267          if (error->error_code == BadAlloc)
    268             _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
    269          else if (type == EGL_WINDOW_BIT)
    270             _eglError(EGL_BAD_NATIVE_WINDOW, "xcb_get_geometry");
    271          else
    272             _eglError(EGL_BAD_NATIVE_PIXMAP, "xcb_get_geometry");
    273          free(error);
    274          goto cleanup_dri_drawable;
    275       } else if (reply == NULL) {
    276          _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
    277          goto cleanup_dri_drawable;
    278       }
    279 
    280       dri2_surf->base.Width = reply->width;
    281       dri2_surf->base.Height = reply->height;
    282       dri2_surf->depth = reply->depth;
    283       free(reply);
    284    }
    285 
    286    if (dri2_dpy->dri2) {
    287       xcb_void_cookie_t cookie;
    288       int conn_error;
    289 
    290       cookie = xcb_dri2_create_drawable_checked(dri2_dpy->conn,
    291                                                 dri2_surf->drawable);
    292       error = xcb_request_check(dri2_dpy->conn, cookie);
    293       conn_error = xcb_connection_has_error(dri2_dpy->conn);
    294       if (conn_error || error != NULL) {
    295          if (type == EGL_PBUFFER_BIT || conn_error || error->error_code == BadAlloc)
    296             _eglError(EGL_BAD_ALLOC, "xcb_dri2_create_drawable_checked");
    297          else if (type == EGL_WINDOW_BIT)
    298             _eglError(EGL_BAD_NATIVE_WINDOW,
    299                       "xcb_dri2_create_drawable_checked");
    300          else
    301             _eglError(EGL_BAD_NATIVE_PIXMAP,
    302                       "xcb_dri2_create_drawable_checked");
    303          free(error);
    304          goto cleanup_dri_drawable;
    305       }
    306    } else {
    307       if (type == EGL_PBUFFER_BIT) {
    308          dri2_surf->depth = _eglGetConfigKey(conf, EGL_BUFFER_SIZE);
    309       }
    310       swrastCreateDrawable(dri2_dpy, dri2_surf);
    311    }
    312 
    313    /* we always copy the back buffer to front */
    314    dri2_surf->base.PostSubBufferSupportedNV = EGL_TRUE;
    315 
    316    return &dri2_surf->base;
    317 
    318  cleanup_dri_drawable:
    319    dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
    320  cleanup_pixmap:
    321    if (type == EGL_PBUFFER_BIT)
    322       xcb_free_pixmap(dri2_dpy->conn, dri2_surf->drawable);
    323  cleanup_surf:
    324    free(dri2_surf);
    325 
    326    return NULL;
    327 }
    328 
    329 /**
    330  * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
    331  */
    332 static _EGLSurface *
    333 dri2_x11_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
    334                                _EGLConfig *conf, void *native_window,
    335                                const EGLint *attrib_list)
    336 {
    337    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    338    _EGLSurface *surf;
    339 
    340    surf = dri2_x11_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
    341                                   native_window, attrib_list);
    342    if (surf != NULL) {
    343       /* When we first create the DRI2 drawable, its swap interval on the
    344        * server side is 1.
    345        */
    346       surf->SwapInterval = 1;
    347 
    348       /* Override that with a driconf-set value. */
    349       dri2_x11_swap_interval(drv, disp, surf, dri2_dpy->default_swap_interval);
    350    }
    351 
    352    return surf;
    353 }
    354 
    355 static _EGLSurface *
    356 dri2_x11_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
    357                                _EGLConfig *conf, void *native_pixmap,
    358                                const EGLint *attrib_list)
    359 {
    360    return dri2_x11_create_surface(drv, disp, EGL_PIXMAP_BIT, conf,
    361                                   native_pixmap, attrib_list);
    362 }
    363 
    364 static _EGLSurface *
    365 dri2_x11_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
    366                                 _EGLConfig *conf, const EGLint *attrib_list)
    367 {
    368    return dri2_x11_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
    369                                   XCB_WINDOW_NONE, attrib_list);
    370 }
    371 
    372 static EGLBoolean
    373 dri2_x11_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
    374 {
    375    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    376    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
    377 
    378    (void) drv;
    379 
    380    dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
    381 
    382    if (dri2_dpy->dri2) {
    383       xcb_dri2_destroy_drawable (dri2_dpy->conn, dri2_surf->drawable);
    384    } else {
    385       assert(dri2_dpy->swrast);
    386       swrastDestroyDrawable(dri2_dpy, dri2_surf);
    387    }
    388 
    389    if (surf->Type == EGL_PBUFFER_BIT)
    390       xcb_free_pixmap (dri2_dpy->conn, dri2_surf->drawable);
    391 
    392    free(surf);
    393 
    394    return EGL_TRUE;
    395 }
    396 
    397 /**
    398  * Function utilizes swrastGetDrawableInfo to get surface
    399  * geometry from x server and calls default query surface
    400  * implementation that returns the updated values.
    401  *
    402  * In case of errors we still return values that we currently
    403  * have.
    404  */
    405 static EGLBoolean
    406 dri2_query_surface(_EGLDriver *drv, _EGLDisplay *dpy,
    407                    _EGLSurface *surf, EGLint attribute,
    408                    EGLint *value)
    409 {
    410    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
    411    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
    412    int x, y, w = -1, h = -1;
    413 
    414    __DRIdrawable *drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
    415 
    416    switch (attribute) {
    417    case EGL_WIDTH:
    418    case EGL_HEIGHT:
    419       swrastGetDrawableInfo(drawable, &x, &y, &w, &h, dri2_surf);
    420       if (w != -1 && h != -1) {
    421          surf->Width = w;
    422          surf->Height = h;
    423       }
    424       break;
    425    default:
    426       break;
    427    }
    428    return _eglQuerySurface(drv, dpy, surf, attribute, value);
    429 }
    430 
    431 /**
    432  * Process list of buffer received from the server
    433  *
    434  * Processes the list of buffers received in a reply from the server to either
    435  * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat.
    436  */
    437 static void
    438 dri2_x11_process_buffers(struct dri2_egl_surface *dri2_surf,
    439                          xcb_dri2_dri2_buffer_t *buffers, unsigned count)
    440 {
    441    struct dri2_egl_display *dri2_dpy =
    442       dri2_egl_display(dri2_surf->base.Resource.Display);
    443    xcb_rectangle_t rectangle;
    444    unsigned i;
    445 
    446    dri2_surf->buffer_count = count;
    447    dri2_surf->have_fake_front = 0;
    448 
    449    /* This assumes the DRI2 buffer attachment tokens matches the
    450     * __DRIbuffer tokens. */
    451    for (i = 0; i < count; i++) {
    452       dri2_surf->buffers[i].attachment = buffers[i].attachment;
    453       dri2_surf->buffers[i].name = buffers[i].name;
    454       dri2_surf->buffers[i].pitch = buffers[i].pitch;
    455       dri2_surf->buffers[i].cpp = buffers[i].cpp;
    456       dri2_surf->buffers[i].flags = buffers[i].flags;
    457 
    458       /* We only use the DRI drivers single buffer configs.  This
    459        * means that if we try to render to a window, DRI2 will give us
    460        * the fake front buffer, which we'll use as a back buffer.
    461        * Note that EGL doesn't require that several clients rendering
    462        * to the same window must see the same aux buffers. */
    463       if (dri2_surf->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
    464          dri2_surf->have_fake_front = 1;
    465    }
    466 
    467    if (dri2_surf->region != XCB_NONE)
    468       xcb_xfixes_destroy_region(dri2_dpy->conn, dri2_surf->region);
    469 
    470    rectangle.x = 0;
    471    rectangle.y = 0;
    472    rectangle.width = dri2_surf->base.Width;
    473    rectangle.height = dri2_surf->base.Height;
    474    dri2_surf->region = xcb_generate_id(dri2_dpy->conn);
    475    xcb_xfixes_create_region(dri2_dpy->conn, dri2_surf->region, 1, &rectangle);
    476 }
    477 
    478 static __DRIbuffer *
    479 dri2_x11_get_buffers(__DRIdrawable * driDrawable,
    480                      int *width, int *height,
    481                      unsigned int *attachments, int count,
    482                      int *out_count, void *loaderPrivate)
    483 {
    484    struct dri2_egl_surface *dri2_surf = loaderPrivate;
    485    struct dri2_egl_display *dri2_dpy =
    486       dri2_egl_display(dri2_surf->base.Resource.Display);
    487    xcb_dri2_dri2_buffer_t *buffers;
    488    xcb_dri2_get_buffers_reply_t *reply;
    489    xcb_dri2_get_buffers_cookie_t cookie;
    490 
    491    (void) driDrawable;
    492 
    493    cookie = xcb_dri2_get_buffers_unchecked (dri2_dpy->conn,
    494 					    dri2_surf->drawable,
    495 					    count, count, attachments);
    496    reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn, cookie, NULL);
    497    if (reply == NULL)
    498       return NULL;
    499    buffers = xcb_dri2_get_buffers_buffers (reply);
    500    if (buffers == NULL)
    501       return NULL;
    502 
    503    *out_count = reply->count;
    504    dri2_surf->base.Width = *width = reply->width;
    505    dri2_surf->base.Height = *height = reply->height;
    506    dri2_x11_process_buffers(dri2_surf, buffers, *out_count);
    507 
    508    free(reply);
    509 
    510    return dri2_surf->buffers;
    511 }
    512 
    513 static __DRIbuffer *
    514 dri2_x11_get_buffers_with_format(__DRIdrawable * driDrawable,
    515                                  int *width, int *height,
    516                                  unsigned int *attachments, int count,
    517                                  int *out_count, void *loaderPrivate)
    518 {
    519    struct dri2_egl_surface *dri2_surf = loaderPrivate;
    520    struct dri2_egl_display *dri2_dpy =
    521       dri2_egl_display(dri2_surf->base.Resource.Display);
    522    xcb_dri2_dri2_buffer_t *buffers;
    523    xcb_dri2_get_buffers_with_format_reply_t *reply;
    524    xcb_dri2_get_buffers_with_format_cookie_t cookie;
    525    xcb_dri2_attach_format_t *format_attachments;
    526 
    527    (void) driDrawable;
    528 
    529    format_attachments = (xcb_dri2_attach_format_t *) attachments;
    530    cookie = xcb_dri2_get_buffers_with_format_unchecked (dri2_dpy->conn,
    531 							dri2_surf->drawable,
    532 							count, count,
    533 							format_attachments);
    534 
    535    reply = xcb_dri2_get_buffers_with_format_reply (dri2_dpy->conn,
    536 						   cookie, NULL);
    537    if (reply == NULL)
    538       return NULL;
    539 
    540    buffers = xcb_dri2_get_buffers_with_format_buffers (reply);
    541    dri2_surf->base.Width = *width = reply->width;
    542    dri2_surf->base.Height = *height = reply->height;
    543    *out_count = reply->count;
    544    dri2_x11_process_buffers(dri2_surf, buffers, *out_count);
    545 
    546    free(reply);
    547 
    548    return dri2_surf->buffers;
    549 }
    550 
    551 static void
    552 dri2_x11_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
    553 {
    554    (void) driDrawable;
    555 
    556    /* FIXME: Does EGL support front buffer rendering at all? */
    557 
    558 #if 0
    559    struct dri2_egl_surface *dri2_surf = loaderPrivate;
    560 
    561    dri2WaitGL(dri2_surf);
    562 #else
    563    (void) loaderPrivate;
    564 #endif
    565 }
    566 
    567 static int
    568 dri2_x11_do_authenticate(struct dri2_egl_display *dri2_dpy, uint32_t id)
    569 {
    570    xcb_dri2_authenticate_reply_t *authenticate;
    571    xcb_dri2_authenticate_cookie_t authenticate_cookie;
    572    int ret = 0;
    573 
    574    authenticate_cookie =
    575       xcb_dri2_authenticate_unchecked(dri2_dpy->conn, dri2_dpy->screen->root, id);
    576    authenticate =
    577       xcb_dri2_authenticate_reply(dri2_dpy->conn, authenticate_cookie, NULL);
    578 
    579    if (authenticate == NULL || !authenticate->authenticated)
    580       ret = -1;
    581 
    582    free(authenticate);
    583 
    584    return ret;
    585 }
    586 
    587 static EGLBoolean
    588 dri2_x11_local_authenticate(struct dri2_egl_display *dri2_dpy)
    589 {
    590 #ifdef HAVE_LIBDRM
    591    drm_magic_t magic;
    592 
    593    if (drmGetMagic(dri2_dpy->fd, &magic)) {
    594       _eglLog(_EGL_WARNING, "DRI2: failed to get drm magic");
    595       return EGL_FALSE;
    596    }
    597 
    598    if (dri2_x11_do_authenticate(dri2_dpy, magic) < 0) {
    599       _eglLog(_EGL_WARNING, "DRI2: failed to authenticate");
    600       return EGL_FALSE;
    601    }
    602 #endif
    603    return EGL_TRUE;
    604 }
    605 
    606 static EGLBoolean
    607 dri2_x11_connect(struct dri2_egl_display *dri2_dpy)
    608 {
    609    xcb_xfixes_query_version_reply_t *xfixes_query;
    610    xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
    611    xcb_dri2_query_version_reply_t *dri2_query;
    612    xcb_dri2_query_version_cookie_t dri2_query_cookie;
    613    xcb_dri2_connect_reply_t *connect;
    614    xcb_dri2_connect_cookie_t connect_cookie;
    615    xcb_generic_error_t *error;
    616    char *driver_name, *loader_driver_name, *device_name;
    617    const xcb_query_extension_reply_t *extension;
    618 
    619    xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_xfixes_id);
    620    xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri2_id);
    621 
    622    extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_xfixes_id);
    623    if (!(extension && extension->present))
    624       return EGL_FALSE;
    625 
    626    extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_dri2_id);
    627    if (!(extension && extension->present))
    628       return EGL_FALSE;
    629 
    630    xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->conn,
    631 						  XCB_XFIXES_MAJOR_VERSION,
    632 						  XCB_XFIXES_MINOR_VERSION);
    633 
    634    dri2_query_cookie = xcb_dri2_query_version (dri2_dpy->conn,
    635 					       XCB_DRI2_MAJOR_VERSION,
    636 					       XCB_DRI2_MINOR_VERSION);
    637 
    638    connect_cookie = xcb_dri2_connect_unchecked(dri2_dpy->conn, dri2_dpy->screen->root,
    639                                    XCB_DRI2_DRIVER_TYPE_DRI);
    640 
    641    xfixes_query =
    642       xcb_xfixes_query_version_reply (dri2_dpy->conn,
    643 				      xfixes_query_cookie, &error);
    644    if (xfixes_query == NULL ||
    645        error != NULL || xfixes_query->major_version < 2) {
    646       _eglLog(_EGL_WARNING, "DRI2: failed to query xfixes version");
    647       free(error);
    648       return EGL_FALSE;
    649    }
    650    free(xfixes_query);
    651 
    652    dri2_query =
    653       xcb_dri2_query_version_reply (dri2_dpy->conn, dri2_query_cookie, &error);
    654    if (dri2_query == NULL || error != NULL) {
    655       _eglLog(_EGL_WARNING, "DRI2: failed to query version");
    656       free(error);
    657       return EGL_FALSE;
    658    }
    659    dri2_dpy->dri2_major = dri2_query->major_version;
    660    dri2_dpy->dri2_minor = dri2_query->minor_version;
    661    free(dri2_query);
    662 
    663    connect = xcb_dri2_connect_reply (dri2_dpy->conn, connect_cookie, NULL);
    664    if (connect == NULL ||
    665        connect->driver_name_length + connect->device_name_length == 0) {
    666       _eglLog(_EGL_WARNING, "DRI2: failed to authenticate");
    667       return EGL_FALSE;
    668    }
    669 
    670    device_name = xcb_dri2_connect_device_name (connect);
    671 
    672    dri2_dpy->fd = loader_open_device(device_name);
    673    if (dri2_dpy->fd == -1) {
    674       _eglLog(_EGL_WARNING,
    675               "DRI2: could not open %s (%s)", device_name, strerror(errno));
    676       free(connect);
    677       return EGL_FALSE;
    678    }
    679 
    680    if (!dri2_x11_local_authenticate(dri2_dpy)) {
    681       close(dri2_dpy->fd);
    682       free(connect);
    683       return EGL_FALSE;
    684    }
    685 
    686    driver_name = xcb_dri2_connect_driver_name (connect);
    687 
    688    /* If Mesa knows about the appropriate driver for this fd, then trust it.
    689     * Otherwise, default to the server's value.
    690     */
    691    loader_driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
    692    if (loader_driver_name) {
    693       dri2_dpy->driver_name = loader_driver_name;
    694    } else {
    695       dri2_dpy->driver_name =
    696          strndup(driver_name,
    697                  xcb_dri2_connect_driver_name_length(connect));
    698    }
    699 
    700    if (dri2_dpy->driver_name == NULL) {
    701       close(dri2_dpy->fd);
    702       free(dri2_dpy->driver_name);
    703       free(connect);
    704       return EGL_FALSE;
    705    }
    706 
    707 #ifdef HAVE_WAYLAND_PLATFORM
    708    dri2_dpy->device_name =
    709       strndup(device_name,
    710               xcb_dri2_connect_device_name_length(connect));
    711 #endif
    712 
    713    free(connect);
    714 
    715    return EGL_TRUE;
    716 }
    717 
    718 static int
    719 dri2_x11_authenticate(_EGLDisplay *disp, uint32_t id)
    720 {
    721    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    722 
    723    return dri2_x11_do_authenticate(dri2_dpy, id);
    724 }
    725 
    726 static EGLBoolean
    727 dri2_x11_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
    728                                  _EGLDisplay *disp, bool supports_preserved)
    729 {
    730    xcb_depth_iterator_t d;
    731    xcb_visualtype_t *visuals;
    732    int i, j, count;
    733    unsigned int rgba_masks[4];
    734    EGLint surface_type;
    735    EGLint config_attrs[] = {
    736 	   EGL_NATIVE_VISUAL_ID,   0,
    737 	   EGL_NATIVE_VISUAL_TYPE, 0,
    738 	   EGL_NONE
    739    };
    740 
    741    d = xcb_screen_allowed_depths_iterator(dri2_dpy->screen);
    742    count = 0;
    743 
    744    surface_type =
    745       EGL_WINDOW_BIT |
    746       EGL_PIXMAP_BIT |
    747       EGL_PBUFFER_BIT;
    748 
    749    if (supports_preserved)
    750       surface_type |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
    751 
    752    while (d.rem > 0) {
    753       EGLBoolean class_added[6] = { 0, };
    754 
    755       visuals = xcb_depth_visuals(d.data);
    756       for (i = 0; i < xcb_depth_visuals_length(d.data); i++) {
    757 	 if (class_added[visuals[i]._class])
    758 	    continue;
    759 
    760 	 class_added[visuals[i]._class] = EGL_TRUE;
    761 	 for (j = 0; dri2_dpy->driver_configs[j]; j++) {
    762             struct dri2_egl_config *dri2_conf;
    763             const __DRIconfig *config = dri2_dpy->driver_configs[j];
    764 
    765             config_attrs[1] = visuals[i].visual_id;
    766             config_attrs[3] = visuals[i]._class;
    767 
    768             rgba_masks[0] = visuals[i].red_mask;
    769             rgba_masks[1] = visuals[i].green_mask;
    770             rgba_masks[2] = visuals[i].blue_mask;
    771             rgba_masks[3] = 0;
    772             dri2_conf = dri2_add_config(disp, config, count + 1, surface_type,
    773                                         config_attrs, rgba_masks);
    774             if (dri2_conf)
    775                count++;
    776 
    777             /* Allow a 24-bit RGB visual to match a 32-bit RGBA EGLConfig.
    778              * Otherwise it will only match a 32-bit RGBA visual.  On a
    779              * composited window manager on X11, this will make all of the
    780              * EGLConfigs with destination alpha get blended by the
    781              * compositor.  This is probably not what the application
    782              * wants... especially on drivers that only have 32-bit RGBA
    783              * EGLConfigs! */
    784             if (d.data->depth == 24) {
    785                rgba_masks[3] =
    786                   ~(rgba_masks[0] | rgba_masks[1] | rgba_masks[2]);
    787                dri2_conf = dri2_add_config(disp, config, count + 1, surface_type,
    788                                            config_attrs, rgba_masks);
    789                if (dri2_conf)
    790                   count++;
    791             }
    792 	 }
    793       }
    794 
    795       xcb_depth_next(&d);
    796    }
    797 
    798    if (!count) {
    799       _eglLog(_EGL_WARNING, "DRI2: failed to create any config");
    800       return EGL_FALSE;
    801    }
    802 
    803    return EGL_TRUE;
    804 }
    805 
    806 static EGLBoolean
    807 dri2_copy_region(_EGLDriver *drv, _EGLDisplay *disp,
    808 		 _EGLSurface *draw, xcb_xfixes_region_t region)
    809 {
    810    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    811    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
    812    enum xcb_dri2_attachment_t render_attachment;
    813    xcb_dri2_copy_region_cookie_t cookie;
    814 
    815    /* No-op for a pixmap or pbuffer surface */
    816    if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT)
    817       return EGL_TRUE;
    818 
    819    if (dri2_dpy->flush)
    820       dri2_dpy->flush->flush(dri2_surf->dri_drawable);
    821 
    822    if (dri2_surf->have_fake_front)
    823       render_attachment = XCB_DRI2_ATTACHMENT_BUFFER_FAKE_FRONT_LEFT;
    824    else
    825       render_attachment = XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT;
    826 
    827    cookie = xcb_dri2_copy_region_unchecked(dri2_dpy->conn,
    828 					   dri2_surf->drawable,
    829 					   region,
    830 					   XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT,
    831 					   render_attachment);
    832    free(xcb_dri2_copy_region_reply(dri2_dpy->conn, cookie, NULL));
    833 
    834    return EGL_TRUE;
    835 }
    836 
    837 static int64_t
    838 dri2_x11_swap_buffers_msc(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw,
    839                           int64_t msc, int64_t divisor, int64_t remainder)
    840 {
    841    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    842    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
    843    uint32_t msc_hi = msc >> 32;
    844    uint32_t msc_lo = msc & 0xffffffff;
    845    uint32_t divisor_hi = divisor >> 32;
    846    uint32_t divisor_lo = divisor & 0xffffffff;
    847    uint32_t remainder_hi = remainder >> 32;
    848    uint32_t remainder_lo = remainder & 0xffffffff;
    849    xcb_dri2_swap_buffers_cookie_t cookie;
    850    xcb_dri2_swap_buffers_reply_t *reply;
    851    int64_t swap_count = -1;
    852 
    853    /* No-op for a pixmap or pbuffer surface */
    854    if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT)
    855       return 0;
    856 
    857    if (draw->SwapBehavior == EGL_BUFFER_PRESERVED || !dri2_dpy->swap_available)
    858       return dri2_copy_region(drv, disp, draw, dri2_surf->region) ? 0 : -1;
    859 
    860    dri2_flush_drawable_for_swapbuffers(disp, draw);
    861 
    862    cookie = xcb_dri2_swap_buffers_unchecked(dri2_dpy->conn, dri2_surf->drawable,
    863                   msc_hi, msc_lo, divisor_hi, divisor_lo, remainder_hi, remainder_lo);
    864 
    865    reply = xcb_dri2_swap_buffers_reply(dri2_dpy->conn, cookie, NULL);
    866 
    867    if (reply) {
    868       swap_count = (((int64_t)reply->swap_hi) << 32) | reply->swap_lo;
    869       free(reply);
    870    }
    871 
    872    /* Since we aren't watching for the server's invalidate events like we're
    873     * supposed to (due to XCB providing no mechanism for filtering the events
    874     * the way xlib does), and SwapBuffers is a common cause of invalidate
    875     * events, just shove one down to the driver, even though we haven't told
    876     * the driver that we're the kind of loader that provides reliable
    877     * invalidate events.  This causes the driver to request buffers again at
    878     * its next draw, so that we get the correct buffers if a pageflip
    879     * happened.  The driver should still be using the viewport hack to catch
    880     * window resizes.
    881     */
    882    if (dri2_dpy->flush &&
    883        dri2_dpy->flush->base.version >= 3 && dri2_dpy->flush->invalidate)
    884       dri2_dpy->flush->invalidate(dri2_surf->dri_drawable);
    885 
    886    return swap_count;
    887 }
    888 
    889 static EGLBoolean
    890 dri2_x11_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
    891 {
    892    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    893    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
    894 
    895    if (dri2_dpy->dri2) {
    896       if (dri2_x11_swap_buffers_msc(drv, disp, draw, 0, 0, 0) != -1) {
    897           return EGL_TRUE;
    898       }
    899       /* Swap failed with a window drawable. */
    900       _eglError(EGL_BAD_NATIVE_WINDOW, __func__);
    901       return EGL_FALSE;
    902    } else {
    903       assert(dri2_dpy->swrast);
    904 
    905       dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable);
    906       return EGL_TRUE;
    907    }
    908 }
    909 
    910 static EGLBoolean
    911 dri2_x11_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *disp,
    912                              _EGLSurface *draw,
    913                              EGLint numRects, const EGLint *rects)
    914 {
    915    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    916    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
    917    EGLBoolean ret;
    918    xcb_xfixes_region_t region;
    919    xcb_rectangle_t rectangles[16];
    920    int i;
    921 
    922    if (numRects > (int)ARRAY_SIZE(rectangles))
    923       return dri2_copy_region(drv, disp, draw, dri2_surf->region);
    924 
    925    for (i = 0; i < numRects; i++) {
    926       rectangles[i].x = rects[i * 4];
    927       rectangles[i].y = dri2_surf->base.Height - rects[i * 4 + 1] - rects[i * 4 + 3];
    928       rectangles[i].width = rects[i * 4 + 2];
    929       rectangles[i].height = rects[i * 4 + 3];
    930    }
    931 
    932    region = xcb_generate_id(dri2_dpy->conn);
    933    xcb_xfixes_create_region(dri2_dpy->conn, region, numRects, rectangles);
    934    ret = dri2_copy_region(drv, disp, draw, region);
    935    xcb_xfixes_destroy_region(dri2_dpy->conn, region);
    936 
    937    return ret;
    938 }
    939 
    940 static EGLBoolean
    941 dri2_x11_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw,
    942 		     EGLint x, EGLint y, EGLint width, EGLint height)
    943 {
    944    const EGLint rect[4] = { x, y, width, height };
    945 
    946    if (x < 0 || y < 0 || width < 0 || height < 0)
    947       _eglError(EGL_BAD_PARAMETER, "eglPostSubBufferNV");
    948 
    949    return dri2_x11_swap_buffers_region(drv, disp, draw, 1, rect);
    950 }
    951 
    952 static EGLBoolean
    953 dri2_x11_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
    954                        EGLint interval)
    955 {
    956    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    957    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
    958 
    959    if (interval > surf->Config->MaxSwapInterval)
    960       interval = surf->Config->MaxSwapInterval;
    961    else if (interval < surf->Config->MinSwapInterval)
    962       interval = surf->Config->MinSwapInterval;
    963 
    964    if (interval != surf->SwapInterval && dri2_dpy->swap_available)
    965       xcb_dri2_swap_interval(dri2_dpy->conn, dri2_surf->drawable, interval);
    966 
    967    surf->SwapInterval = interval;
    968 
    969    return EGL_TRUE;
    970 }
    971 
    972 static EGLBoolean
    973 dri2_x11_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
    974                       void *native_pixmap_target)
    975 {
    976    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    977    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
    978    xcb_gcontext_t gc;
    979    xcb_pixmap_t target;
    980 
    981    STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_pixmap_target));
    982    target = (uintptr_t) native_pixmap_target;
    983 
    984    (void) drv;
    985 
    986    dri2_dpy->flush->flush(dri2_surf->dri_drawable);
    987 
    988    gc = xcb_generate_id(dri2_dpy->conn);
    989    xcb_create_gc(dri2_dpy->conn, gc, target, 0, NULL);
    990    xcb_copy_area(dri2_dpy->conn,
    991 		  dri2_surf->drawable,
    992 		  target,
    993 		  gc,
    994 		  0, 0,
    995 		  0, 0,
    996 		  dri2_surf->base.Width,
    997 		  dri2_surf->base.Height);
    998    xcb_free_gc(dri2_dpy->conn, gc);
    999 
   1000    return EGL_TRUE;
   1001 }
   1002 
   1003 static _EGLImage *
   1004 dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
   1005 			     EGLClientBuffer buffer, const EGLint *attr_list)
   1006 {
   1007    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1008    struct dri2_egl_image *dri2_img;
   1009    unsigned int attachments[1];
   1010    xcb_drawable_t drawable;
   1011    xcb_dri2_get_buffers_cookie_t buffers_cookie;
   1012    xcb_dri2_get_buffers_reply_t *buffers_reply;
   1013    xcb_dri2_dri2_buffer_t *buffers;
   1014    xcb_get_geometry_cookie_t geometry_cookie;
   1015    xcb_get_geometry_reply_t *geometry_reply;
   1016    xcb_generic_error_t *error;
   1017    int stride, format;
   1018 
   1019    (void) ctx;
   1020 
   1021    drawable = (xcb_drawable_t) (uintptr_t) buffer;
   1022    xcb_dri2_create_drawable (dri2_dpy->conn, drawable);
   1023    attachments[0] = XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT;
   1024    buffers_cookie =
   1025       xcb_dri2_get_buffers_unchecked (dri2_dpy->conn,
   1026 				      drawable, 1, 1, attachments);
   1027    geometry_cookie = xcb_get_geometry (dri2_dpy->conn, drawable);
   1028    buffers_reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn,
   1029 					       buffers_cookie, NULL);
   1030    if (buffers_reply == NULL)
   1031      return NULL;
   1032 
   1033    buffers = xcb_dri2_get_buffers_buffers (buffers_reply);
   1034    if (buffers == NULL) {
   1035       return NULL;
   1036    }
   1037 
   1038    geometry_reply = xcb_get_geometry_reply (dri2_dpy->conn,
   1039 					    geometry_cookie, &error);
   1040    if (geometry_reply == NULL || error != NULL) {
   1041       _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
   1042       free(error);
   1043       free(buffers_reply);
   1044       return NULL;
   1045    }
   1046 
   1047    switch (geometry_reply->depth) {
   1048    case 16:
   1049       format = __DRI_IMAGE_FORMAT_RGB565;
   1050       break;
   1051    case 24:
   1052       format = __DRI_IMAGE_FORMAT_XRGB8888;
   1053       break;
   1054    case 32:
   1055       format = __DRI_IMAGE_FORMAT_ARGB8888;
   1056       break;
   1057    default:
   1058       _eglError(EGL_BAD_PARAMETER,
   1059 		"dri2_create_image_khr: unsupported pixmap depth");
   1060       free(buffers_reply);
   1061       free(geometry_reply);
   1062       return NULL;
   1063    }
   1064 
   1065    dri2_img = malloc(sizeof *dri2_img);
   1066    if (!dri2_img) {
   1067       free(buffers_reply);
   1068       free(geometry_reply);
   1069       _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
   1070       return EGL_NO_IMAGE_KHR;
   1071    }
   1072 
   1073    if (!_eglInitImage(&dri2_img->base, disp)) {
   1074       free(buffers_reply);
   1075       free(geometry_reply);
   1076       free(dri2_img);
   1077       return EGL_NO_IMAGE_KHR;
   1078    }
   1079 
   1080    stride = buffers[0].pitch / buffers[0].cpp;
   1081    dri2_img->dri_image =
   1082       dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
   1083 					   buffers_reply->width,
   1084 					   buffers_reply->height,
   1085 					   format,
   1086 					   buffers[0].name,
   1087 					   stride,
   1088 					   dri2_img);
   1089 
   1090    free(buffers_reply);
   1091    free(geometry_reply);
   1092 
   1093    return &dri2_img->base;
   1094 }
   1095 
   1096 static _EGLImage *
   1097 dri2_x11_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
   1098 			  _EGLContext *ctx, EGLenum target,
   1099 			  EGLClientBuffer buffer, const EGLint *attr_list)
   1100 {
   1101    (void) drv;
   1102 
   1103    switch (target) {
   1104    case EGL_NATIVE_PIXMAP_KHR:
   1105       return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
   1106    default:
   1107       return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
   1108    }
   1109 }
   1110 
   1111 static EGLBoolean
   1112 dri2_x11_get_sync_values(_EGLDisplay *display, _EGLSurface *surface,
   1113                          EGLuint64KHR *ust, EGLuint64KHR *msc,
   1114                          EGLuint64KHR *sbc)
   1115 {
   1116    struct dri2_egl_display *dri2_dpy = dri2_egl_display(display);
   1117    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
   1118    xcb_dri2_get_msc_cookie_t cookie;
   1119    xcb_dri2_get_msc_reply_t *reply;
   1120 
   1121    cookie = xcb_dri2_get_msc(dri2_dpy->conn, dri2_surf->drawable);
   1122    reply = xcb_dri2_get_msc_reply(dri2_dpy->conn, cookie, NULL);
   1123 
   1124    if (!reply) {
   1125       _eglError(EGL_BAD_ACCESS, __func__);
   1126       return EGL_FALSE;
   1127    }
   1128 
   1129    *ust = ((EGLuint64KHR) reply->ust_hi << 32) | reply->ust_lo;
   1130    *msc = ((EGLuint64KHR) reply->msc_hi << 32) | reply->msc_lo;
   1131    *sbc = ((EGLuint64KHR) reply->sbc_hi << 32) | reply->sbc_lo;
   1132    free(reply);
   1133 
   1134    return EGL_TRUE;
   1135 }
   1136 
   1137 static struct dri2_egl_display_vtbl dri2_x11_swrast_display_vtbl = {
   1138    .authenticate = NULL,
   1139    .create_window_surface = dri2_x11_create_window_surface,
   1140    .create_pixmap_surface = dri2_x11_create_pixmap_surface,
   1141    .create_pbuffer_surface = dri2_x11_create_pbuffer_surface,
   1142    .destroy_surface = dri2_x11_destroy_surface,
   1143    .create_image = dri2_fallback_create_image_khr,
   1144    .swap_interval = dri2_fallback_swap_interval,
   1145    .swap_buffers = dri2_x11_swap_buffers,
   1146    .swap_buffers_region = dri2_fallback_swap_buffers_region,
   1147    .post_sub_buffer = dri2_fallback_post_sub_buffer,
   1148    .copy_buffers = dri2_x11_copy_buffers,
   1149    .query_buffer_age = dri2_fallback_query_buffer_age,
   1150    .query_surface = dri2_query_surface,
   1151    .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
   1152    .get_sync_values = dri2_fallback_get_sync_values,
   1153    .get_dri_drawable = dri2_surface_get_dri_drawable,
   1154 };
   1155 
   1156 static struct dri2_egl_display_vtbl dri2_x11_display_vtbl = {
   1157    .authenticate = dri2_x11_authenticate,
   1158    .create_window_surface = dri2_x11_create_window_surface,
   1159    .create_pixmap_surface = dri2_x11_create_pixmap_surface,
   1160    .create_pbuffer_surface = dri2_x11_create_pbuffer_surface,
   1161    .destroy_surface = dri2_x11_destroy_surface,
   1162    .create_image = dri2_x11_create_image_khr,
   1163    .swap_interval = dri2_x11_swap_interval,
   1164    .swap_buffers = dri2_x11_swap_buffers,
   1165    .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage,
   1166    .swap_buffers_region = dri2_x11_swap_buffers_region,
   1167    .post_sub_buffer = dri2_x11_post_sub_buffer,
   1168    .copy_buffers = dri2_x11_copy_buffers,
   1169    .query_buffer_age = dri2_fallback_query_buffer_age,
   1170    .query_surface = dri2_query_surface,
   1171    .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
   1172    .get_sync_values = dri2_x11_get_sync_values,
   1173    .get_dri_drawable = dri2_surface_get_dri_drawable,
   1174 };
   1175 
   1176 static const __DRIswrastLoaderExtension swrast_loader_extension = {
   1177    .base = { __DRI_SWRAST_LOADER, 1 },
   1178 
   1179    .getDrawableInfo = swrastGetDrawableInfo,
   1180    .putImage        = swrastPutImage,
   1181    .getImage        = swrastGetImage,
   1182 };
   1183 
   1184 static const __DRIextension *swrast_loader_extensions[] = {
   1185    &swrast_loader_extension.base,
   1186    NULL,
   1187 };
   1188 
   1189 static EGLBoolean
   1190 dri2_get_xcb_connection(_EGLDriver *drv, _EGLDisplay *disp,
   1191                         struct dri2_egl_display *dri2_dpy)
   1192 {
   1193    xcb_screen_iterator_t s;
   1194    int screen = 0;
   1195    const char *msg;
   1196 
   1197    disp->DriverData = (void *) dri2_dpy;
   1198    if (disp->PlatformDisplay == NULL) {
   1199       dri2_dpy->conn = xcb_connect(NULL, &screen);
   1200       dri2_dpy->own_device = true;
   1201    } else {
   1202       Display *dpy = disp->PlatformDisplay;
   1203 
   1204       dri2_dpy->conn = XGetXCBConnection(dpy);
   1205       screen = DefaultScreen(dpy);
   1206    }
   1207 
   1208    if (!dri2_dpy->conn || xcb_connection_has_error(dri2_dpy->conn)) {
   1209       msg = "xcb_connect failed";
   1210       goto disconnect;
   1211    }
   1212 
   1213    s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
   1214    dri2_dpy->screen = get_xcb_screen(s, screen);
   1215    if (!dri2_dpy->screen) {
   1216       msg = "failed to get xcb screen";
   1217       goto disconnect;
   1218    }
   1219 
   1220    return EGL_TRUE;
   1221 disconnect:
   1222    if (disp->PlatformDisplay == NULL)
   1223       xcb_disconnect(dri2_dpy->conn);
   1224 
   1225    return _eglError(EGL_BAD_ALLOC, msg);
   1226 }
   1227 
   1228 static EGLBoolean
   1229 dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp)
   1230 {
   1231    struct dri2_egl_display *dri2_dpy;
   1232 
   1233    dri2_dpy = calloc(1, sizeof *dri2_dpy);
   1234    if (!dri2_dpy)
   1235       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
   1236 
   1237    if (!dri2_get_xcb_connection(drv, disp, dri2_dpy))
   1238       goto cleanup_dpy;
   1239 
   1240    /*
   1241     * Every hardware driver_name is set using strdup. Doing the same in
   1242     * here will allow is to simply free the memory at dri2_terminate().
   1243     */
   1244    dri2_dpy->fd = -1;
   1245    dri2_dpy->driver_name = strdup("swrast");
   1246    if (!dri2_load_driver_swrast(disp))
   1247       goto cleanup_conn;
   1248 
   1249    dri2_dpy->loader_extensions = swrast_loader_extensions;
   1250 
   1251    if (!dri2_create_screen(disp))
   1252       goto cleanup_driver;
   1253 
   1254    if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp, true))
   1255       goto cleanup_configs;
   1256 
   1257    /* Fill vtbl last to prevent accidentally calling virtual function during
   1258     * initialization.
   1259     */
   1260    dri2_dpy->vtbl = &dri2_x11_swrast_display_vtbl;
   1261 
   1262    return EGL_TRUE;
   1263 
   1264  cleanup_configs:
   1265    _eglCleanupDisplay(disp);
   1266    dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
   1267  cleanup_driver:
   1268    dlclose(dri2_dpy->driver);
   1269  cleanup_conn:
   1270    free(dri2_dpy->driver_name);
   1271    if (disp->PlatformDisplay == NULL)
   1272       xcb_disconnect(dri2_dpy->conn);
   1273  cleanup_dpy:
   1274    free(dri2_dpy);
   1275    disp->DriverData = NULL;
   1276 
   1277    return EGL_FALSE;
   1278 }
   1279 
   1280 static void
   1281 dri2_x11_setup_swap_interval(struct dri2_egl_display *dri2_dpy)
   1282 {
   1283    GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
   1284    int arbitrary_max_interval = 1000;
   1285 
   1286    /* default behavior for no SwapBuffers support: no vblank syncing
   1287     * either.
   1288     */
   1289    dri2_dpy->min_swap_interval = 0;
   1290    dri2_dpy->max_swap_interval = 0;
   1291 
   1292    if (!dri2_dpy->swap_available)
   1293       return;
   1294 
   1295    /* If we do have swapbuffers, then we can support pretty much any swap
   1296     * interval, but we allow driconf to override applications.
   1297     */
   1298    if (dri2_dpy->config)
   1299       dri2_dpy->config->configQueryi(dri2_dpy->dri_screen,
   1300                                      "vblank_mode", &vblank_mode);
   1301    switch (vblank_mode) {
   1302    case DRI_CONF_VBLANK_NEVER:
   1303       dri2_dpy->min_swap_interval = 0;
   1304       dri2_dpy->max_swap_interval = 0;
   1305       dri2_dpy->default_swap_interval = 0;
   1306       break;
   1307    case DRI_CONF_VBLANK_ALWAYS_SYNC:
   1308       dri2_dpy->min_swap_interval = 1;
   1309       dri2_dpy->max_swap_interval = arbitrary_max_interval;
   1310       dri2_dpy->default_swap_interval = 1;
   1311       break;
   1312    case DRI_CONF_VBLANK_DEF_INTERVAL_0:
   1313       dri2_dpy->min_swap_interval = 0;
   1314       dri2_dpy->max_swap_interval = arbitrary_max_interval;
   1315       dri2_dpy->default_swap_interval = 0;
   1316       break;
   1317    default:
   1318    case DRI_CONF_VBLANK_DEF_INTERVAL_1:
   1319       dri2_dpy->min_swap_interval = 0;
   1320       dri2_dpy->max_swap_interval = arbitrary_max_interval;
   1321       dri2_dpy->default_swap_interval = 1;
   1322       break;
   1323    }
   1324 }
   1325 
   1326 #ifdef HAVE_DRI3
   1327 
   1328 static const __DRIextension *dri3_image_loader_extensions[] = {
   1329    &dri3_image_loader_extension.base,
   1330    &image_lookup_extension.base,
   1331    &use_invalidate.base,
   1332    NULL,
   1333 };
   1334 
   1335 static EGLBoolean
   1336 dri2_initialize_x11_dri3(_EGLDriver *drv, _EGLDisplay *disp)
   1337 {
   1338    struct dri2_egl_display *dri2_dpy;
   1339 
   1340    dri2_dpy = calloc(1, sizeof *dri2_dpy);
   1341    if (!dri2_dpy)
   1342       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
   1343 
   1344    if (!dri2_get_xcb_connection(drv, disp, dri2_dpy))
   1345       goto cleanup_dpy;
   1346 
   1347    if (!dri3_x11_connect(dri2_dpy))
   1348       goto cleanup_conn;
   1349 
   1350    if (!dri2_load_driver_dri3(disp))
   1351       goto cleanup_conn;
   1352 
   1353    dri2_dpy->loader_extensions = dri3_image_loader_extensions;
   1354 
   1355    dri2_dpy->swap_available = true;
   1356    dri2_dpy->invalidate_available = true;
   1357 
   1358    if (!dri2_create_screen(disp))
   1359       goto cleanup_fd;
   1360 
   1361    dri2_x11_setup_swap_interval(dri2_dpy);
   1362 
   1363    if (!dri2_dpy->is_different_gpu)
   1364       disp->Extensions.KHR_image_pixmap = EGL_TRUE;
   1365    disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE;
   1366    disp->Extensions.CHROMIUM_sync_control = EGL_TRUE;
   1367    disp->Extensions.EXT_buffer_age = EGL_TRUE;
   1368 
   1369    dri2_set_WL_bind_wayland_display(drv, disp);
   1370 
   1371    if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp, false))
   1372       goto cleanup_configs;
   1373 
   1374    dri2_dpy->loader_dri3_ext.core = dri2_dpy->core;
   1375    dri2_dpy->loader_dri3_ext.image_driver = dri2_dpy->image_driver;
   1376    dri2_dpy->loader_dri3_ext.flush = dri2_dpy->flush;
   1377    dri2_dpy->loader_dri3_ext.tex_buffer = dri2_dpy->tex_buffer;
   1378    dri2_dpy->loader_dri3_ext.image = dri2_dpy->image;
   1379    dri2_dpy->loader_dri3_ext.config = dri2_dpy->config;
   1380 
   1381    /* Fill vtbl last to prevent accidentally calling virtual function during
   1382     * initialization.
   1383     */
   1384    dri2_dpy->vtbl = &dri3_x11_display_vtbl;
   1385 
   1386    _eglLog(_EGL_INFO, "Using DRI3");
   1387 
   1388    return EGL_TRUE;
   1389 
   1390  cleanup_configs:
   1391    _eglCleanupDisplay(disp);
   1392    dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
   1393    dlclose(dri2_dpy->driver);
   1394  cleanup_fd:
   1395    close(dri2_dpy->fd);
   1396  cleanup_conn:
   1397    if (disp->PlatformDisplay == NULL)
   1398       xcb_disconnect(dri2_dpy->conn);
   1399  cleanup_dpy:
   1400    free(dri2_dpy);
   1401    disp->DriverData = NULL;
   1402 
   1403    return EGL_FALSE;
   1404 }
   1405 #endif
   1406 
   1407 static const __DRIdri2LoaderExtension dri2_loader_extension_old = {
   1408    .base = { __DRI_DRI2_LOADER, 2 },
   1409 
   1410    .getBuffers           = dri2_x11_get_buffers,
   1411    .flushFrontBuffer     = dri2_x11_flush_front_buffer,
   1412    .getBuffersWithFormat = NULL,
   1413 };
   1414 
   1415 static const __DRIdri2LoaderExtension dri2_loader_extension = {
   1416    .base = { __DRI_DRI2_LOADER, 3 },
   1417 
   1418    .getBuffers           = dri2_x11_get_buffers,
   1419    .flushFrontBuffer     = dri2_x11_flush_front_buffer,
   1420    .getBuffersWithFormat = dri2_x11_get_buffers_with_format,
   1421 };
   1422 
   1423 static const __DRIextension *dri2_loader_extensions_old[] = {
   1424    &dri2_loader_extension_old.base,
   1425    &image_lookup_extension.base,
   1426    NULL,
   1427 };
   1428 
   1429 static const __DRIextension *dri2_loader_extensions[] = {
   1430    &dri2_loader_extension.base,
   1431    &image_lookup_extension.base,
   1432    NULL,
   1433 };
   1434 
   1435 static EGLBoolean
   1436 dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
   1437 {
   1438    struct dri2_egl_display *dri2_dpy;
   1439 
   1440    dri2_dpy = calloc(1, sizeof *dri2_dpy);
   1441    if (!dri2_dpy)
   1442       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
   1443 
   1444    if (!dri2_get_xcb_connection(drv, disp, dri2_dpy))
   1445       goto cleanup_dpy;
   1446 
   1447    if (!dri2_x11_connect(dri2_dpy))
   1448       goto cleanup_conn;
   1449 
   1450    if (!dri2_load_driver(disp))
   1451       goto cleanup_fd;
   1452 
   1453    if (dri2_dpy->dri2_minor >= 1)
   1454       dri2_dpy->loader_extensions = dri2_loader_extensions;
   1455    else
   1456       dri2_dpy->loader_extensions = dri2_loader_extensions_old;
   1457 
   1458    dri2_dpy->swap_available = (dri2_dpy->dri2_minor >= 2);
   1459    dri2_dpy->invalidate_available = (dri2_dpy->dri2_minor >= 3);
   1460 
   1461    if (!dri2_create_screen(disp))
   1462       goto cleanup_driver;
   1463 
   1464    dri2_x11_setup_swap_interval(dri2_dpy);
   1465 
   1466    disp->Extensions.KHR_image_pixmap = EGL_TRUE;
   1467    disp->Extensions.NOK_swap_region = EGL_TRUE;
   1468    disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE;
   1469    disp->Extensions.NV_post_sub_buffer = EGL_TRUE;
   1470    disp->Extensions.CHROMIUM_sync_control = EGL_TRUE;
   1471 
   1472    dri2_set_WL_bind_wayland_display(drv, disp);
   1473 
   1474    if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp, true))
   1475       goto cleanup_configs;
   1476 
   1477    /* Fill vtbl last to prevent accidentally calling virtual function during
   1478     * initialization.
   1479     */
   1480    dri2_dpy->vtbl = &dri2_x11_display_vtbl;
   1481 
   1482    _eglLog(_EGL_INFO, "Using DRI2");
   1483 
   1484    return EGL_TRUE;
   1485 
   1486  cleanup_configs:
   1487    _eglCleanupDisplay(disp);
   1488    dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
   1489  cleanup_driver:
   1490    dlclose(dri2_dpy->driver);
   1491  cleanup_fd:
   1492    close(dri2_dpy->fd);
   1493  cleanup_conn:
   1494    if (disp->PlatformDisplay == NULL)
   1495       xcb_disconnect(dri2_dpy->conn);
   1496  cleanup_dpy:
   1497    free(dri2_dpy);
   1498    disp->DriverData = NULL;
   1499 
   1500    return EGL_FALSE;
   1501 }
   1502 
   1503 EGLBoolean
   1504 dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp)
   1505 {
   1506    EGLBoolean initialized = EGL_FALSE;
   1507 
   1508    if (!getenv("LIBGL_ALWAYS_SOFTWARE")) {
   1509 #ifdef HAVE_DRI3
   1510       if (!getenv("LIBGL_DRI3_DISABLE"))
   1511          initialized = dri2_initialize_x11_dri3(drv, disp);
   1512 #endif
   1513 
   1514       if (!initialized)
   1515          initialized = dri2_initialize_x11_dri2(drv, disp);
   1516    }
   1517 
   1518    if (!initialized)
   1519       initialized = dri2_initialize_x11_swrast(drv, disp);
   1520 
   1521    return initialized;
   1522 }
   1523 
   1524