Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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